aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework
diff options
context:
space:
mode:
authoronefang2019-05-19 21:24:15 +1000
committeronefang2019-05-19 21:24:15 +1000
commit5e4d6cab00cb29cd088ab7b62ab13aff103b64cb (patch)
treea9fbc62df9eb2d1d9ba2698d8552eae71eca20d8 /OpenSim/Region/Framework
parentAdd a build script. (diff)
downloadopensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.zip
opensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.gz
opensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.bz2
opensim-SC_OLD-5e4d6cab00cb29cd088ab7b62ab13aff103b64cb.tar.xz
Dump OpenSim 0.9.0.1 into it's own branch.
Diffstat (limited to '')
-rw-r--r--OpenSim/Data/MySQL/MySQLMuteListData.cs (renamed from OpenSim/Region/Framework/Interfaces/IRegionCombinerModule.cs)57
-rw-r--r--OpenSim/Region/Framework/Interfaces/IAgentAssetTransactions.cs4
-rw-r--r--OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs15
-rw-r--r--OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs5
-rw-r--r--OpenSim/Region/Framework/Interfaces/IBuySellModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/ICapabilitiesModule.cs20
-rw-r--r--OpenSim/Region/Framework/Interfaces/ICloudModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/ICommander.cs4
-rw-r--r--OpenSim/Region/Framework/Interfaces/IDwellModule.cs1
-rw-r--r--OpenSim/Region/Framework/Interfaces/IDynamicFloaterModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IDynamicMenuModule.cs1
-rw-r--r--OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs26
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityCreator.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityInventory.cs27
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs9
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEstateModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEtcdModule.cs37
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEventQueue.cs22
-rw-r--r--OpenSim/Region/Framework/Interfaces/IExternalCapsModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IFriendsModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IGodsModule.cs7
-rw-r--r--OpenSim/Region/Framework/Interfaces/IGroupsMessagingModule.cs12
-rw-r--r--OpenSim/Region/Framework/Interfaces/IGroupsModule.cs7
-rw-r--r--OpenSim/Region/Framework/Interfaces/IHttpRequests.cs6
-rw-r--r--OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs17
-rw-r--r--OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs6
-rw-r--r--OpenSim/Region/Framework/Interfaces/IMapImageUploadModule.cs9
-rw-r--r--OpenSim/Region/Framework/Interfaces/IMessageTransferModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IMoapModule.cs8
-rw-r--r--OpenSim/Region/Framework/Interfaces/INPCModule.cs21
-rw-r--r--OpenSim/Region/Framework/Interfaces/IPermissionsModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IPresenceModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs28
-rw-r--r--OpenSim/Region/Framework/Interfaces/IRegionConsole.cs4
-rw-r--r--OpenSim/Region/Framework/Interfaces/IRegionModuleBase.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IRegionSerialiserModule.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.cs12
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs22
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISnmpModule.cs47
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISoundModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs8
-rw-r--r--OpenSim/Region/Framework/Interfaces/ITerrainModule.cs12
-rw-r--r--OpenSim/Region/Framework/Interfaces/IUrlModule.cs7
-rw-r--r--OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs (renamed from OpenSim/Region/OptionalModules/RegionCombinerModule/RegionData.cs)15
-rw-r--r--OpenSim/Region/Framework/Interfaces/IVoiceModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IWindModelPlugin.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IWindModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IWorldComm.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IWorldMapModule.cs3
-rw-r--r--OpenSim/Region/Framework/Properties/AssemblyInfo.cs10
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs18
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/BinBVHAnimation.cs40
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/DefaultAvatarAnimations.cs6
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/MovementAnimationOverrides.cs102
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs518
-rw-r--r--OpenSim/Region/Framework/Scenes/AsyncInventorySender.cs9
-rw-r--r--OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs38
-rw-r--r--OpenSim/Region/Framework/Scenes/Border.cs148
-rw-r--r--OpenSim/Region/Framework/Scenes/CoalescedSceneObjects.cs40
-rw-r--r--OpenSim/Region/Framework/Scenes/CollisionSounds.cs342
-rw-r--r--OpenSim/Region/Framework/Scenes/EntityManager.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/EventManager.cs337
-rw-r--r--OpenSim/Region/Framework/Scenes/GodController.cs287
-rw-r--r--OpenSim/Region/Framework/Scenes/KeyframeMotion.cs372
-rw-r--r--OpenSim/Region/Framework/Scenes/Prioritizer.cs164
-rw-r--r--OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs8
-rw-r--r--OpenSim/Region/Framework/Scenes/SOPMaterial.cs177
-rw-r--r--OpenSim/Region/Framework/Scenes/SOPVehicle.cs803
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs948
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs291
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Permissions.cs525
-rwxr-xr-x[-rw-r--r--]OpenSim/Region/Framework/Scenes/Scene.cs2560
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneBase.cs23
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs59
-rwxr-xr-x[-rw-r--r--]OpenSim/Region/Framework/Scenes/SceneGraph.cs833
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneManager.cs256
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs337
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs3160
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs2966
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs973
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs4969
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs6
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs30
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs317
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneXmlLoader.cs14
-rwxr-xr-x[-rw-r--r--]OpenSim/Region/Framework/Scenes/SimStatsReporter.cs629
-rw-r--r--OpenSim/Region/Framework/Scenes/TerrainChannel.cs182
-rw-r--r--OpenSim/Region/Framework/Scenes/TerrainCompressor.cs1589
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/BorderTests.cs340
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs22
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs20
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs39
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectCopyTests.cs34
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectCrossingTests.cs51
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs71
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs56
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs6
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectSpatialTests.cs3
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectStatusTests.cs16
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectUndoRedoTests.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs37
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs15
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAnimationTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs8
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs8
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs10
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneStatisticsTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneTelehubTests.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SharedRegionModuleTests.cs18
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs22
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs68
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs18
-rw-r--r--OpenSim/Region/Framework/Scenes/UndoState.cs367
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs231
119 files changed, 17124 insertions, 8968 deletions
diff --git a/OpenSim/Region/Framework/Interfaces/IRegionCombinerModule.cs b/OpenSim/Data/MySQL/MySQLMuteListData.cs
index c6f531e..a5935a3 100644
--- a/OpenSim/Region/Framework/Interfaces/IRegionCombinerModule.cs
+++ b/OpenSim/Data/MySQL/MySQLMuteListData.cs
@@ -26,39 +26,42 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections;
29using System.Collections.Generic; 30using System.Collections.Generic;
30using System.Linq; 31using System.Data;
31using System.Text;
32using OpenSim.Region.Framework.Scenes;
33using System.IO;
34using OpenMetaverse; 32using OpenMetaverse;
33using OpenSim.Framework;
34using MySql.Data.MySqlClient;
35 35
36namespace OpenSim.Region.Framework.Interfaces 36namespace OpenSim.Data.MySQL
37{ 37{
38 public interface IRegionCombinerModule 38 public class MySqlMuteListData : MySQLGenericTableHandler<MuteData>, IMuteListData
39 { 39 {
40 /// <summary> 40 public MySqlMuteListData(string connectionString)
41 /// Does the given id belong to the root region of a megaregion? 41 : base(connectionString, "MuteList", "MuteListStore")
42 /// </summary> 42 {
43 bool IsRootForMegaregion(UUID regionId); 43 }
44 44
45 /// <summary> 45 public MuteData[] Get(UUID agentID)
46 /// Gets the size of megaregion. 46 {
47 /// </summary> 47 MuteData[] data = base.Get("AgentID", agentID.ToString());
48 /// <remarks> 48 return data;
49 /// Returns size in meters. 49 }
50 /// Do not rely on this method remaining the same - this area is actively under development.
51 /// </remarks>
52 /// <param name="sceneId">
53 /// The id of the root region for a megaregion.
54 /// This may change in the future to allow any region id that makes up a megaregion.
55 /// Currently, will throw an exception if this does not match a root region.
56 /// </param>
57 Vector2 GetSizeOfMegaregion(UUID regionId);
58 50
59 /// <summary> 51 public bool Delete(UUID agentID, UUID muteID, string muteName)
60 /// Tests to see of position (relative to the region) is within the megaregion 52 {
61 /// </summary> 53 string cmnd ="delete from MuteList where AgentID = ?AgentID and MuteID = ?MuteID and MuteName = ?MuteName";
62 bool PositionIsInMegaregion(UUID currentRegion, int xx, int yy); 54
55 using (MySqlCommand cmd = new MySqlCommand(cmnd))
56 {
57 cmd.Parameters.AddWithValue("?AgentID", agentID.ToString());
58 cmd.Parameters.AddWithValue("?MuteID", muteID.ToString());
59 cmd.Parameters.AddWithValue("?MuteName", muteName);
60
61 if (ExecuteNonQuery(cmd) > 0)
62 return true;
63 return false;
64 }
65 }
63 } 66 }
64} \ No newline at end of file 67} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Interfaces/IAgentAssetTransactions.cs b/OpenSim/Region/Framework/Interfaces/IAgentAssetTransactions.cs
index 0cc8fb6..b8278d6 100644
--- a/OpenSim/Region/Framework/Interfaces/IAgentAssetTransactions.cs
+++ b/OpenSim/Region/Framework/Interfaces/IAgentAssetTransactions.cs
@@ -36,10 +36,10 @@ 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
43 void HandleTaskItemUpdateFromTransaction( 43 void HandleTaskItemUpdateFromTransaction(
44 IClientAPI remoteClient, SceneObjectPart part, UUID transactionID, TaskInventoryItem item); 44 IClientAPI remoteClient, SceneObjectPart part, UUID transactionID, TaskInventoryItem item);
45 45
diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
index d9901bd..2f5ff9b 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,8 @@ 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,
94 bool addToInventory, bool append);
93 95
94 /// <summary> 96 /// <summary>
95 /// Rez an attachment from user inventory and change inventory status to match. 97 /// Rez an attachment from user inventory and change inventory status to match.
@@ -98,7 +100,11 @@ namespace OpenSim.Region.Framework.Interfaces
98 /// <param name="itemID"></param> 100 /// <param name="itemID"></param>
99 /// <param name="AttachmentPt"></param> 101 /// <param name="AttachmentPt"></param>
100 /// <returns>The scene object that was attached. Null if the scene object could not be found</returns> 102 /// <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); 103 ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt);
104
105 // Same as above, but also load script states from a separate doc
106 ISceneEntity RezSingleAttachmentFromInventory(
107 IScenePresence presence, UUID itemID, uint AttachmentPt, XmlDocument doc);
102 108
103 /// <summary> 109 /// <summary>
104 /// Rez multiple attachments from a user's inventory 110 /// Rez multiple attachments from a user's inventory
@@ -106,7 +112,7 @@ namespace OpenSim.Region.Framework.Interfaces
106 /// <param name="sp"></param> 112 /// <param name="sp"></param>
107 /// <param name="rezlist"></param> 113 /// <param name="rezlist"></param>
108 void RezMultipleAttachmentsFromInventory(IScenePresence sp,List<KeyValuePair<UUID, uint>> rezlist); 114 void RezMultipleAttachmentsFromInventory(IScenePresence sp,List<KeyValuePair<UUID, uint>> rezlist);
109 115
110 /// <summary> 116 /// <summary>
111 /// Detach the given item to the ground. 117 /// Detach the given item to the ground.
112 /// </summary> 118 /// </summary>
@@ -129,8 +135,7 @@ namespace OpenSim.Region.Framework.Interfaces
129 /// <param name="sp">/param> 135 /// <param name="sp">/param>
130 /// <param name="grp">The attachment to detach.</param> 136 /// <param name="grp">The attachment to detach.</param>
131 void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup grp); 137 void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup grp);
132 138
133 /// <summary>
134 /// Update the position of an attachment. 139 /// Update the position of an attachment.
135 /// </summary> 140 /// </summary>
136 /// <param name="sog"></param> 141 /// <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/IBuySellModule.cs b/OpenSim/Region/Framework/Interfaces/IBuySellModule.cs
index d1ce4c0..1bbf10e 100644
--- a/OpenSim/Region/Framework/Interfaces/IBuySellModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IBuySellModule.cs
@@ -31,7 +31,7 @@ using OpenSim.Framework;
31namespace OpenSim.Region.Framework.Interfaces 31namespace OpenSim.Region.Framework.Interfaces
32{ 32{
33 public interface IBuySellModule 33 public interface IBuySellModule
34 { 34 {
35 /// <summary> 35 /// <summary>
36 /// Try to buy an object 36 /// Try to buy an object
37 /// </summary> 37 /// </summary>
diff --git a/OpenSim/Region/Framework/Interfaces/ICapabilitiesModule.cs b/OpenSim/Region/Framework/Interfaces/ICapabilitiesModule.cs
index 522c82d..761b1bb 100644
--- a/OpenSim/Region/Framework/Interfaces/ICapabilitiesModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/ICapabilitiesModule.cs
@@ -40,30 +40,32 @@ 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
59 Dictionary<ulong, string> GetChildrenSeeds(UUID agentID); 59 Dictionary<ulong, string> GetChildrenSeeds(UUID agentID);
60 60
61 string GetChildSeed(UUID agentID, ulong handle); 61 string GetChildSeed(UUID agentID, ulong handle);
62 62
63 void SetChildrenSeed(UUID agentID, Dictionary<ulong, string> seeds); 63 void SetChildrenSeed(UUID agentID, Dictionary<ulong, string> seeds);
64 64
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/ICloudModule.cs b/OpenSim/Region/Framework/Interfaces/ICloudModule.cs
index 54172bd..a73b564 100644
--- a/OpenSim/Region/Framework/Interfaces/ICloudModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/ICloudModule.cs
@@ -27,7 +27,7 @@
27 27
28namespace OpenSim.Region.Framework.Interfaces 28namespace OpenSim.Region.Framework.Interfaces
29{ 29{
30 public interface ICloudModule 30 public interface ICloudModule
31 { 31 {
32 /// <summary> 32 /// <summary>
33 /// Retrieves the cloud density at the given region coordinates 33 /// Retrieves the cloud density at the given region coordinates
diff --git a/OpenSim/Region/Framework/Interfaces/ICommander.cs b/OpenSim/Region/Framework/Interfaces/ICommander.cs
index 6b872c1..5d6428a 100644
--- a/OpenSim/Region/Framework/Interfaces/ICommander.cs
+++ b/OpenSim/Region/Framework/Interfaces/ICommander.cs
@@ -40,12 +40,12 @@ namespace OpenSim.Region.Framework.Interfaces
40 /// Provide general help information about this commander. 40 /// Provide general help information about this commander.
41 /// </value> 41 /// </value>
42 string Help { get; } 42 string Help { get; }
43 43
44 /// <summary> 44 /// <summary>
45 /// The commands available for this commander 45 /// The commands available for this commander
46 /// </summary> 46 /// </summary>
47 Dictionary<string, ICommand> Commands { get; } 47 Dictionary<string, ICommand> Commands { get; }
48 48
49 void ProcessConsoleCommand(string function, string[] args); 49 void ProcessConsoleCommand(string function, string[] args);
50 void RegisterCommand(string commandName, ICommand command); 50 void RegisterCommand(string commandName, ICommand command);
51 void Run(string function, object[] args); 51 void Run(string function, object[] args);
diff --git a/OpenSim/Region/Framework/Interfaces/IDwellModule.cs b/OpenSim/Region/Framework/Interfaces/IDwellModule.cs
index db50439..ebef5a4 100644
--- a/OpenSim/Region/Framework/Interfaces/IDwellModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IDwellModule.cs
@@ -33,5 +33,6 @@ namespace OpenSim.Region.Framework.Interfaces
33 public interface IDwellModule 33 public interface IDwellModule
34 { 34 {
35 int GetDwell(UUID parcelID); 35 int GetDwell(UUID parcelID);
36 int GetDwell(LandData land);
36 } 37 }
37} 38}
diff --git a/OpenSim/Region/Framework/Interfaces/IDynamicFloaterModule.cs b/OpenSim/Region/Framework/Interfaces/IDynamicFloaterModule.cs
index 7684ce3..1ff8fd2 100644
--- a/OpenSim/Region/Framework/Interfaces/IDynamicFloaterModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IDynamicFloaterModule.cs
@@ -36,7 +36,7 @@ namespace OpenSim.Region.Framework.Interfaces
36 36
37 public abstract class FloaterData 37 public abstract class FloaterData
38 { 38 {
39 public abstract int Channel { get; } 39 public abstract int Channel { get; }
40 public abstract string FloaterName { get; set; } 40 public abstract string FloaterName { get; set; }
41 public virtual string XmlName { get; set; } 41 public virtual string XmlName { get; set; }
42 public virtual string XmlText { get; set; } 42 public virtual string XmlText { get; set; }
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/IDynamicTextureManager.cs b/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs
index 6df5cc2..093ea9c 100644
--- a/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs
+++ b/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs
@@ -44,14 +44,13 @@ namespace OpenSim.Region.Framework.Interfaces
44 /// <param name='isReuseable'></param> 44 /// <param name='isReuseable'></param>
45 void ReturnData(UUID id, IDynamicTexture texture); 45 void ReturnData(UUID id, IDynamicTexture texture);
46 46
47 UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams);
47 UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams, 48 UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams,
48 int updateTimer); 49 bool SetBlending, byte AlphaValue);
49 UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams, 50 UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams,
50 int updateTimer, bool SetBlending, byte AlphaValue); 51 bool SetBlending, int disp, byte AlphaValue, int face);
51 UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams, 52
52 int updateTimer, bool SetBlending, int disp, byte AlphaValue, int face); 53 UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, string extraParams);
53 UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, string extraParams,
54 int updateTimer);
55 54
56 /// Apply a dynamically generated texture to all sides of the given prim. The texture is not persisted to the 55 /// Apply a dynamically generated texture to all sides of the given prim. The texture is not persisted to the
57 /// asset service. 56 /// asset service.
@@ -62,8 +61,6 @@ namespace OpenSim.Region.Framework.Interfaces
62 /// based texture or "image" to create a texture from an image at a particular URL</param> 61 /// based texture or "image" to create a texture from an image at a particular URL</param>
63 /// <param name="data">The data for the generator</param> 62 /// <param name="data">The data for the generator</param>
64 /// <param name="extraParams">Parameters for the generator that don't form part of the main data.</param> 63 /// <param name="extraParams">Parameters for the generator that don't form part of the main data.</param>
65 /// <param name="updateTimer">If zero, the image is never updated after the first generation. If positive
66 /// the image is updated at the given interval. Not implemented for </param>
67 /// <param name="SetBlending"> 64 /// <param name="SetBlending">
68 /// If true, the newly generated texture is blended with the appropriate existing ones on the prim 65 /// If true, the newly generated texture is blended with the appropriate existing ones on the prim
69 /// </param> 66 /// </param>
@@ -76,7 +73,7 @@ namespace OpenSim.Region.Framework.Interfaces
76 /// can be obtained as SceneObjectPart.Shape.Textures.DefaultTexture.TextureID 73 /// can be obtained as SceneObjectPart.Shape.Textures.DefaultTexture.TextureID
77 /// </returns> 74 /// </returns>
78 UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, string extraParams, 75 UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, string extraParams,
79 int updateTimer, bool SetBlending, byte AlphaValue); 76 bool SetBlending, byte AlphaValue);
80 77
81 /// <summary> 78 /// <summary>
82 /// Apply a dynamically generated texture to the given prim. 79 /// Apply a dynamically generated texture to the given prim.
@@ -87,8 +84,6 @@ namespace OpenSim.Region.Framework.Interfaces
87 /// based texture or "image" to create a texture from an image at a particular URL</param> 84 /// based texture or "image" to create a texture from an image at a particular URL</param>
88 /// <param name="data">The data for the generator</param> 85 /// <param name="data">The data for the generator</param>
89 /// <param name="extraParams">Parameters for the generator that don't form part of the main data.</param> 86 /// <param name="extraParams">Parameters for the generator that don't form part of the main data.</param>
90 /// <param name="updateTimer">If zero, the image is never updated after the first generation. If positive
91 /// the image is updated at the given interval. Not implemented for </param>
92 /// <param name="SetBlending"> 87 /// <param name="SetBlending">
93 /// If true, the newly generated texture is blended with the appropriate existing ones on the prim 88 /// If true, the newly generated texture is blended with the appropriate existing ones on the prim
94 /// </param> 89 /// </param>
@@ -109,10 +104,9 @@ namespace OpenSim.Region.Framework.Interfaces
109 /// to obtain it directly from the SceneObjectPart. For instance, if ALL_SIDES is set then this texture 104 /// to obtain it directly from the SceneObjectPart. For instance, if ALL_SIDES is set then this texture
110 /// can be obtained as SceneObjectPart.Shape.Textures.DefaultTexture.TextureID 105 /// can be obtained as SceneObjectPart.Shape.Textures.DefaultTexture.TextureID
111 /// </returns> 106 /// </returns>
112 UUID AddDynamicTextureData( 107 UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, string extraParams,
113 UUID simID, UUID primID, string contentType, string data, string extraParams, 108 bool SetBlending, int disp, byte AlphaValue, int face);
114 int updateTimer, bool SetBlending, int disp, byte AlphaValue, int face); 109
115
116 void GetDrawStringSize(string contentType, string text, string fontName, int fontSize, 110 void GetDrawStringSize(string contentType, string text, string fontName, int fontSize,
117 out double xSize, out double ySize); 111 out double xSize, out double ySize);
118 } 112 }
@@ -140,7 +134,7 @@ namespace OpenSim.Region.Framework.Interfaces
140 bool AsyncConvertUrl(UUID id, string url, string extraParams); 134 bool AsyncConvertUrl(UUID id, string url, string extraParams);
141 bool AsyncConvertData(UUID id, string bodyData, string extraParams); 135 bool AsyncConvertData(UUID id, string bodyData, string extraParams);
142 136
143 void GetDrawStringSize(string text, string fontName, int fontSize, 137 void GetDrawStringSize(string text, string fontName, int fontSize,
144 out double xSize, out double ySize); 138 out double xSize, out double ySize);
145 } 139 }
146 140
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityCreator.cs b/OpenSim/Region/Framework/Interfaces/IEntityCreator.cs
index c39627c..1df6486 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityCreator.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityCreator.cs
@@ -41,7 +41,7 @@ namespace OpenSim.Region.Framework.Interfaces
41 /// </summary> 41 /// </summary>
42 /// <returns></returns> 42 /// <returns></returns>
43 PCode[] CreationCapabilities { get; } 43 PCode[] CreationCapabilities { get; }
44 44
45 /// <summary> 45 /// <summary>
46 /// Create an entity 46 /// Create an entity
47 /// </summary> 47 /// </summary>
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
index 9ffda51..e7c2428 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
@@ -36,8 +36,8 @@ namespace OpenSim.Region.Framework.Interfaces
36 /// <summary> 36 /// <summary>
37 /// Interface to an entity's (SceneObjectPart's) inventory 37 /// Interface to an entity's (SceneObjectPart's) inventory
38 /// </summary> 38 /// </summary>
39 /// 39 ///
40 /// This is not a finished 1.0 candidate interface 40 /// This is not a finished 1.0 candidate interface
41 public interface IEntityInventory 41 public interface IEntityInventory
42 { 42 {
43 /// <summary> 43 /// <summary>
@@ -48,21 +48,21 @@ namespace OpenSim.Region.Framework.Interfaces
48 /// <summary> 48 /// <summary>
49 /// Reset UUIDs for all the items in the prim's inventory. 49 /// Reset UUIDs for all the items in the prim's inventory.
50 /// </summary> 50 /// </summary>
51 /// 51 ///
52 /// This involves either generating 52 /// This involves either generating
53 /// new ones or setting existing UUIDs to the correct parent UUIDs. 53 /// new ones or setting existing UUIDs to the correct parent UUIDs.
54 /// 54 ///
55 /// If this method is called and there are inventory items, then we regard the inventory as having changed. 55 /// If this method is called and there are inventory items, then we regard the inventory as having changed.
56 /// 56 ///
57 /// <param name="linkNum">Link number for the part</param> 57 /// <param name="linkNum">Link number for the part</param>
58 void ResetInventoryIDs(); 58 void ResetInventoryIDs();
59 59
60 /// <summary> 60 /// <summary>
61 /// Reset parent object UUID for all the items in the prim's inventory. 61 /// Reset parent object UUID for all the items in the prim's inventory.
62 /// </summary> 62 /// </summary>
63 /// 63 ///
64 /// If this method is called and there are inventory items, then we regard the inventory as having changed. 64 /// If this method is called and there are inventory items, then we regard the inventory as having changed.
65 /// 65 ///
66 /// <param name="linkNum">Link number for the part</param> 66 /// <param name="linkNum">Link number for the part</param>
67 void ResetObjectID(); 67 void ResetObjectID();
68 68
@@ -87,7 +87,7 @@ namespace OpenSim.Region.Framework.Interfaces
87 /// <param name="stateSource"></param> 87 /// <param name="stateSource"></param>
88 /// <returns>Number of scripts started.</returns> 88 /// <returns>Number of scripts started.</returns>
89 int CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource); 89 int CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource);
90 90
91 ArrayList GetScriptErrors(UUID itemID); 91 ArrayList GetScriptErrors(UUID itemID);
92 void ResumeScripts(); 92 void ResumeScripts();
93 93
@@ -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>
@@ -236,15 +238,15 @@ namespace OpenSim.Region.Framework.Interfaces
236 /// <summary> 238 /// <summary>
237 /// Get the scene object(s) referenced by an inventory item. 239 /// Get the scene object(s) referenced by an inventory item.
238 /// </summary> 240 /// </summary>
239 /// 241 ///
240 /// This is returned in a 'rez ready' state. That is, name, description, permissions and other details have 242 /// This is returned in a 'rez ready' state. That is, name, description, permissions and other details have
241 /// been adjusted to reflect the part and item from which it originates. 243 /// been adjusted to reflect the part and item from which it originates.
242 /// 244 ///
243 /// <param name="item">Inventory item</param> 245 /// <param name="item">Inventory item</param>
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.
@@ -276,6 +278,8 @@ namespace OpenSim.Region.Framework.Interfaces
276 /// <param name="datastore"></param> 278 /// <param name="datastore"></param>
277 void ProcessInventoryBackup(ISimulationDataService datastore); 279 void ProcessInventoryBackup(ISimulationDataService datastore);
278 280
281 void AggregateInnerPerms(ref uint owner, ref uint group, ref uint everyone);
282
279 uint MaskEffectivePermissions(); 283 uint MaskEffectivePermissions();
280 284
281 void ApplyNextOwnerPermissions(); 285 void ApplyNextOwnerPermissions();
@@ -310,7 +314,7 @@ namespace OpenSim.Region.Framework.Interfaces
310 /// </summary> 314 /// </summary>
311 /// <returns></returns> 315 /// <returns></returns>
312 List<UUID> GetInventoryList(); 316 List<UUID> GetInventoryList();
313 317
314 /// <summary> 318 /// <summary>
315 /// Get the xml representing the saved states of scripts in this inventory. 319 /// Get the xml representing the saved states of scripts in this inventory.
316 /// </summary> 320 /// </summary>
@@ -318,5 +322,6 @@ namespace OpenSim.Region.Framework.Interfaces
318 /// A <see cref="Dictionary`2"/> 322 /// A <see cref="Dictionary`2"/>
319 /// </returns> 323 /// </returns>
320 Dictionary<UUID, string> GetScriptStates(); 324 Dictionary<UUID, string> GetScriptStates();
325 Dictionary<UUID, string> GetScriptStates(bool oldIDs);
321 } 326 }
322} 327}
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
index d07b15a..1b690ba 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, EntityTransferContext ctx); 38 public delegate ScenePresence CrossAgentToNewRegionDelegate(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, EntityTransferContext ctx);
39 public delegate ScenePresence CrossAsyncDelegate(ScenePresence agent, bool isFlying);
39 40
40 public interface IEntityTransferModule 41 public interface IEntityTransferModule
41 { 42 {
@@ -82,7 +83,7 @@ namespace OpenSim.Region.Framework.Interfaces
82 /// </summary> 83 /// </summary>
83 /// <param name='id'>The agent ID</para></param> 84 /// <param name='id'>The agent ID</para></param>
84 /// <returns>true if the agent is in the process of being teleported, false otherwise.</returns> 85 /// <returns>true if the agent is in the process of being teleported, false otherwise.</returns>
85 bool IsInTransit(UUID id); 86 bool IsInTransit(UUID id);
86 87
87 bool Cross(ScenePresence agent, bool isFlying); 88 bool Cross(ScenePresence agent, bool isFlying);
88 89
@@ -94,11 +95,15 @@ namespace OpenSim.Region.Framework.Interfaces
94 95
95 GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, EntityTransferContext ctx, 96 GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, EntityTransferContext ctx,
96 out Vector3 newpos, out string reason); 97 out Vector3 newpos, out string reason);
98 GridRegion GetObjectDestination(SceneObjectGroup grp, Vector3 targetPosition, out Vector3 newpos);
99 bool checkAgentAccessToRegion(ScenePresence agent, GridRegion destiny, Vector3 position, EntityTransferContext ctx, out string reason);
97 100
98 void Cross(SceneObjectGroup sog, Vector3 position, bool silent); 101 bool CrossPrimGroupIntoNewRegion(GridRegion destination, Vector3 newPosition, SceneObjectGroup grp, bool silent, bool removeScripts);
99 102
100 ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, EntityTransferContext ctx); 103 ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, EntityTransferContext ctx);
101 104
105 bool CrossAgentCreateFarChild(ScenePresence agent, GridRegion neighbourRegion, Vector3 pos, EntityTransferContext ctx);
106
102 bool HandleIncomingSceneObject(SceneObjectGroup so, Vector3 newPosition); 107 bool HandleIncomingSceneObject(SceneObjectGroup so, Vector3 newPosition);
103 } 108 }
104 109
diff --git a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
index 461c880..6b8b999 100644
--- a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
@@ -39,6 +39,8 @@ namespace OpenSim.Region.Framework.Interfaces
39 event ChangeDelegate OnRegionInfoChange; 39 event ChangeDelegate OnRegionInfoChange;
40 event ChangeDelegate OnEstateInfoChange; 40 event ChangeDelegate OnEstateInfoChange;
41 event MessageDelegate OnEstateMessage; 41 event MessageDelegate OnEstateMessage;
42 event EstateTeleportOneUserHomeRequest OnEstateTeleportOneUserHomeRequest;
43 event EstateTeleportAllUsersHomeRequest OnEstateTeleportAllUsersHomeRequest;
42 44
43 uint GetRegionFlags(); 45 uint GetRegionFlags();
44 bool IsManager(UUID avatarID); 46 bool IsManager(UUID avatarID);
diff --git a/OpenSim/Region/Framework/Interfaces/IEtcdModule.cs b/OpenSim/Region/Framework/Interfaces/IEtcdModule.cs
new file mode 100644
index 0000000..123cb67
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/IEtcdModule.cs
@@ -0,0 +1,37 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29
30public interface IEtcdModule
31{
32 bool Store(string k, string v);
33 bool Store(string k, string v, int ttl);
34 string Get(string k);
35 void Watch(string k, Action<string> callback);
36 void Delete(string k);
37}
diff --git a/OpenSim/Region/Framework/Interfaces/IEventQueue.cs b/OpenSim/Region/Framework/Interfaces/IEventQueue.cs
index dfc269e..7edd75a 100644
--- a/OpenSim/Region/Framework/Interfaces/IEventQueue.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEventQueue.cs
@@ -30,6 +30,7 @@ using OpenMetaverse;
30using OpenMetaverse.Packets; 30using OpenMetaverse.Packets;
31using OpenMetaverse.Messages.Linden; 31using OpenMetaverse.Messages.Linden;
32using OpenMetaverse.StructuredData; 32using OpenMetaverse.StructuredData;
33using OpenSim.Framework;
33 34
34namespace OpenSim.Region.Framework.Interfaces 35namespace OpenSim.Region.Framework.Interfaces
35{ 36{
@@ -38,26 +39,27 @@ namespace OpenSim.Region.Framework.Interfaces
38 bool Enqueue(OSD o, UUID avatarID); 39 bool Enqueue(OSD o, UUID avatarID);
39 40
40 // These are required to decouple Scenes from EventQueueHelper 41 // These are required to decouple Scenes from EventQueueHelper
41 void DisableSimulator(ulong handle, UUID avatarID); 42// void DisableSimulator(ulong handle, UUID avatarID);
42 void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID, int regionSizeX, int regionSizeY); 43 void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID, int regionSizeX, int regionSizeY);
43 void EstablishAgentCommunication(UUID avatarID, IPEndPoint endPoint, 44 void EstablishAgentCommunication(UUID avatarID, IPEndPoint endPoint,
44 string capsPath, ulong regionHandle, int regionSizeX, int regionSizeY); 45 string capsPath, ulong regionHandle, int regionSizeX, int regionSizeY);
45 void TeleportFinishEvent(ulong regionHandle, byte simAccess, 46 void TeleportFinishEvent(ulong regionHandle, byte simAccess,
46 IPEndPoint regionExternalEndPoint, 47 IPEndPoint regionExternalEndPoint,
47 uint locationID, uint flags, string capsURL, 48 uint locationID, uint flags, string capsURL,
48 UUID agentID, int regionSizeX, int regionSizeY); 49 UUID agentID, int regionSizeX, int regionSizeY);
49 void CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt, 50 void CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt,
50 IPEndPoint newRegionExternalEndPoint, 51 IPEndPoint newRegionExternalEndPoint,
51 string capsURL, UUID avatarID, UUID sessionID, 52 string capsURL, UUID avatarID, UUID sessionID,
52 int regionSizeX, int regionSizeY); 53 int regionSizeX, int regionSizeY);
53 void ChatterboxInvitation(UUID sessionID, string sessionName, 54 void ChatterboxInvitation(UUID sessionID, string sessionName,
54 UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog, 55 UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog,
55 uint timeStamp, bool offline, int parentEstateID, Vector3 position, 56 uint timeStamp, bool offline, int parentEstateID, Vector3 position,
56 uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket); 57 uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket);
57 void ChatterBoxSessionAgentListUpdates(UUID sessionID, UUID fromAgent, UUID anotherAgent, bool canVoiceChat, 58 void ChatterBoxSessionAgentListUpdates(UUID sessionID, UUID fromAgent, UUID anotherAgent,
58 bool isModerator, bool textMute); 59 bool canVoiceChat, bool isModerator, bool textMute, bool isEnterorLeave);
60 void ChatterBoxForceClose(UUID toAgent, UUID sessionID, string reason);
59 void ParcelProperties(ParcelPropertiesMessage parcelPropertiesMessage, UUID avatarID); 61 void ParcelProperties(ParcelPropertiesMessage parcelPropertiesMessage, UUID avatarID);
60 void GroupMembership(AgentGroupDataUpdatePacket groupUpdate, UUID avatarID); 62 void GroupMembershipData(UUID receiverAgent, GroupMembershipData[] data);
61 OSD ScriptRunningEvent(UUID objectID, UUID itemID, bool running, bool mono); 63 OSD ScriptRunningEvent(UUID objectID, UUID itemID, bool running, bool mono);
62 OSD BuildEvent(string eventName, OSD eventBody); 64 OSD BuildEvent(string eventName, OSD eventBody);
63 void partPhysicsProperties(uint localID, byte physhapetype, float density, float friction, float bounce, float gravmod, UUID avatarID); 65 void partPhysicsProperties(uint localID, byte physhapetype, float density, float friction, float bounce, float gravmod, UUID avatarID);
diff --git a/OpenSim/Region/Framework/Interfaces/IExternalCapsModule.cs b/OpenSim/Region/Framework/Interfaces/IExternalCapsModule.cs
index a730cfd..4ce150f 100644
--- a/OpenSim/Region/Framework/Interfaces/IExternalCapsModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IExternalCapsModule.cs
@@ -37,7 +37,7 @@ namespace OpenSim.Region.Framework.Interfaces
37 /// <summary> 37 /// <summary>
38 /// This function extends the simple URL configuration in the caps handlers 38 /// This function extends the simple URL configuration in the caps handlers
39 /// to facilitate more interesting computation when an external handler is 39 /// to facilitate more interesting computation when an external handler is
40 /// sent to the viewer. 40 /// sent to the viewer.
41 /// </summary> 41 /// </summary>
42 /// <param name="agentID">New user UUID</param> 42 /// <param name="agentID">New user UUID</param>
43 /// <param name="caps">Internal caps registry, where the external handler will be registered</param> 43 /// <param name="caps">Internal caps registry, where the external handler will be registered</param>
diff --git a/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs b/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs
index 7e87006..ec014f4 100644
--- a/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs
@@ -28,6 +28,7 @@
28using System.Collections.Generic; 28using System.Collections.Generic;
29using OpenMetaverse; 29using OpenMetaverse;
30using OpenSim.Framework; 30using OpenSim.Framework;
31using OpenSim.Region.Framework.Scenes;
31using FriendInfo = OpenSim.Services.Interfaces.FriendInfo; 32using FriendInfo = OpenSim.Services.Interfaces.FriendInfo;
32 33
33namespace OpenSim.Region.Framework.Interfaces 34namespace OpenSim.Region.Framework.Interfaces
@@ -93,6 +94,7 @@ namespace OpenSim.Region.Framework.Interfaces
93 /// <param name="perms">These come from the FriendRights enum.</param> 94 /// <param name="perms">These come from the FriendRights enum.</param>
94 void GrantRights(IClientAPI remoteClient, UUID friendID, int perms); 95 void GrantRights(IClientAPI remoteClient, UUID friendID, int perms);
95 96
97 void IsNowRoot(ScenePresence sp);
96 bool SendFriendsOnlineIfNeeded(IClientAPI client); 98 bool SendFriendsOnlineIfNeeded(IClientAPI client);
97 } 99 }
98} \ No newline at end of file 100} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Interfaces/IGodsModule.cs b/OpenSim/Region/Framework/Interfaces/IGodsModule.cs
index 552ce01..52615e3 100644
--- a/OpenSim/Region/Framework/Interfaces/IGodsModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IGodsModule.cs
@@ -43,16 +43,15 @@ namespace OpenSim.Region.Framework.Interfaces
43 /// <param name="token"></param> 43 /// <param name="token"></param>
44 /// <param name="godLike"></param> 44 /// <param name="godLike"></param>
45 /// <param name="controllingClient"></param> 45 /// <param name="controllingClient"></param>
46 void RequestGodlikePowers(UUID agentID, UUID sessionID, UUID token, bool godLike, IClientAPI controllingClient); 46 void RequestGodlikePowers(UUID agentID, UUID sessionID, UUID token, bool godLike);
47 47
48 /// <summary> 48 /// <summary>
49 /// Kicks User specified from the simulator. This logs them off of the grid. 49 /// Kicks User specified from the simulator. This logs them off of the grid.
50 /// </summary> 50 /// </summary>
51 /// <param name="godID">The person doing the kicking</param> 51 /// <param name="godID">The person doing the kicking</param>
52 /// <param name="sessionID">The session of the person doing the kicking</param>
53 /// <param name="agentID">the person that is being kicked</param> 52 /// <param name="agentID">the person that is being kicked</param>
54 /// <param name="kickflags">This isn't used apparently</param> 53 /// <param name="kickflags">This isn't used apparently</param>
55 /// <param name="reason">The message to send to the user after it's been turned into a field</param> 54 /// <param name="reason">The message to send to the user after it's been turned into a field</param>
56 void KickUser(UUID godID, UUID sessionID, UUID agentID, uint kickflags, byte[] reason); 55 void KickUser(UUID godID, UUID agentID, uint kickflags, byte[] reason);
57 } 56 }
58} 57}
diff --git a/OpenSim/Region/Framework/Interfaces/IGroupsMessagingModule.cs b/OpenSim/Region/Framework/Interfaces/IGroupsMessagingModule.cs
index 7dc1552..46d6863 100644
--- a/OpenSim/Region/Framework/Interfaces/IGroupsMessagingModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IGroupsMessagingModule.cs
@@ -34,9 +34,9 @@ namespace OpenSim.Region.Framework.Interfaces
34 /// <summary> 34 /// <summary>
35 /// Provide mechanisms for messaging groups. 35 /// Provide mechanisms for messaging groups.
36 /// </summary> 36 /// </summary>
37 /// 37 ///
38 /// TODO: Provide a mechanism for receiving group messages as well as sending them 38 /// TODO: Provide a mechanism for receiving group messages as well as sending them
39 /// 39 ///
40 public interface IGroupsMessagingModule 40 public interface IGroupsMessagingModule
41 { 41 {
42 /// <summary> 42 /// <summary>
@@ -56,13 +56,13 @@ namespace OpenSim.Region.Framework.Interfaces
56 /// True if the chat session was started successfully, false otherwise. 56 /// True if the chat session was started successfully, false otherwise.
57 /// </returns> 57 /// </returns>
58 bool StartGroupChatSession(UUID agentID, UUID groupID); 58 bool StartGroupChatSession(UUID agentID, UUID groupID);
59 59
60 /// <summary> 60 /// <summary>
61 /// Send a message to each member of a group whose chat session is active. 61 /// Send a message to each member of a group whose chat session is active.
62 /// </summary> 62 /// </summary>
63 /// <param name="im"> 63 /// <param name="im">
64 /// The message itself. The fields that must be populated are 64 /// The message itself. The fields that must be populated are
65 /// 65 ///
66 /// imSessionID - Populate this with the group ID (session ID and group ID are currently identical) 66 /// imSessionID - Populate this with the group ID (session ID and group ID are currently identical)
67 /// fromAgentName - Populate this with whatever arbitrary name you want to show up in the chat dialog 67 /// fromAgentName - Populate this with whatever arbitrary name you want to show up in the chat dialog
68 /// message - The message itself 68 /// message - The message itself
@@ -76,7 +76,7 @@ namespace OpenSim.Region.Framework.Interfaces
76 /// </summary> 76 /// </summary>
77 /// <param name="im"> 77 /// <param name="im">
78 /// The message itself. The fields that must be populated are 78 /// The message itself. The fields that must be populated are
79 /// 79 ///
80 /// imSessionID - Populate this with the group ID (session ID and group ID are currently identical) 80 /// imSessionID - Populate this with the group ID (session ID and group ID are currently identical)
81 /// fromAgentName - Populate this with whatever arbitrary name you want to show up in the chat dialog 81 /// fromAgentName - Populate this with whatever arbitrary name you want to show up in the chat dialog
82 /// message - The message itself 82 /// message - The message itself
@@ -84,7 +84,7 @@ namespace OpenSim.Region.Framework.Interfaces
84 /// </param> 84 /// </param>
85 /// <param name="groupID"></param> 85 /// <param name="groupID"></param>
86 /// <param name="sendingAgentForGroupCalls"> 86 /// <param name="sendingAgentForGroupCalls">
87 /// The requesting agent to use when querying the groups service. Sometimes this is different from 87 /// The requesting agent to use when querying the groups service. Sometimes this is different from
88 /// im.fromAgentID, with group notices, for example. 88 /// im.fromAgentID, with group notices, for example.
89 /// </param> 89 /// </param>
90 /// <param name="sendCondition"> 90 /// <param name="sendCondition">
diff --git a/OpenSim/Region/Framework/Interfaces/IGroupsModule.cs b/OpenSim/Region/Framework/Interfaces/IGroupsModule.cs
index 9ae5e87..0d1f4f4 100644
--- a/OpenSim/Region/Framework/Interfaces/IGroupsModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IGroupsModule.cs
@@ -51,7 +51,7 @@ namespace OpenSim.Region.Framework.Interfaces
51 /// <param name="maturePublish"></param> 51 /// <param name="maturePublish"></param>
52 /// <returns>The UUID of the created group</returns> 52 /// <returns>The UUID of the created group</returns>
53 UUID CreateGroup( 53 UUID CreateGroup(
54 IClientAPI remoteClient, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, 54 IClientAPI remoteClient, string name, string charter, bool showInList, UUID insigniaID, int membershipFee,
55 bool openEnrollment, bool allowPublish, bool maturePublish); 55 bool openEnrollment, bool allowPublish, bool maturePublish);
56 56
57 /// <summary> 57 /// <summary>
@@ -67,7 +67,7 @@ namespace OpenSim.Region.Framework.Interfaces
67 /// <param name="GroupID">ID of the group</param> 67 /// <param name="GroupID">ID of the group</param>
68 /// <returns>The group's data. Null if there is no such group.</returns> 68 /// <returns>The group's data. Null if there is no such group.</returns>
69 GroupRecord GetGroupRecord(UUID GroupID); 69 GroupRecord GetGroupRecord(UUID GroupID);
70 70
71 void ActivateGroup(IClientAPI remoteClient, UUID groupID); 71 void ActivateGroup(IClientAPI remoteClient, UUID groupID);
72 List<GroupTitlesData> GroupTitlesRequest(IClientAPI remoteClient, UUID groupID); 72 List<GroupTitlesData> GroupTitlesRequest(IClientAPI remoteClient, UUID groupID);
73 List<GroupMembersData> GroupMembersRequest(IClientAPI remoteClient, UUID groupID); 73 List<GroupMembersData> GroupMembersRequest(IClientAPI remoteClient, UUID groupID);
@@ -76,13 +76,14 @@ namespace OpenSim.Region.Framework.Interfaces
76 GroupProfileData GroupProfileRequest(IClientAPI remoteClient, UUID groupID); 76 GroupProfileData GroupProfileRequest(IClientAPI remoteClient, UUID groupID);
77 GroupMembershipData[] GetMembershipData(UUID UserID); 77 GroupMembershipData[] GetMembershipData(UUID UserID);
78 GroupMembershipData GetMembershipData(UUID GroupID, UUID UserID); 78 GroupMembershipData GetMembershipData(UUID GroupID, UUID UserID);
79 GroupMembershipData GetActiveMembershipData(UUID UserID);
79 80
80 void UpdateGroupInfo(IClientAPI remoteClient, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish); 81 void UpdateGroupInfo(IClientAPI remoteClient, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish);
81 82
82 void SetGroupAcceptNotices(IClientAPI remoteClient, UUID groupID, bool acceptNotices, bool listInProfile); 83 void SetGroupAcceptNotices(IClientAPI remoteClient, UUID groupID, bool acceptNotices, bool listInProfile);
83 84
84 void GroupTitleUpdate(IClientAPI remoteClient, UUID GroupID, UUID TitleRoleID); 85 void GroupTitleUpdate(IClientAPI remoteClient, UUID GroupID, UUID TitleRoleID);
85 86
86 GroupNoticeData[] GroupNoticesListRequest(IClientAPI remoteClient, UUID GroupID); 87 GroupNoticeData[] GroupNoticesListRequest(IClientAPI remoteClient, UUID GroupID);
87 string GetGroupTitle(UUID avatarID); 88 string GetGroupTitle(UUID avatarID);
88 void GroupRoleUpdate(IClientAPI remoteClient, UUID GroupID, UUID RoleID, string name, string description, string title, ulong powers, byte updateType); 89 void GroupRoleUpdate(IClientAPI remoteClient, UUID GroupID, UUID RoleID, string name, string description, string title, ulong powers, byte updateType);
diff --git a/OpenSim/Region/Framework/Interfaces/IHttpRequests.cs b/OpenSim/Region/Framework/Interfaces/IHttpRequests.cs
index 124504c..978c248 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>
@@ -78,15 +77,14 @@ namespace OpenSim.Region.Framework.Interfaces
78 /// then returned via IServiceRequest when the response is asynchronously fetched. 77 /// then returned via IServiceRequest when the response is asynchronously fetched.
79 /// </param> 78 /// </param>
80 UUID StartHttpRequest( 79 UUID StartHttpRequest(
81 uint localID, UUID itemID, string url, List<string> parameters, Dictionary<string, string> headers, string body, 80 uint localID, UUID itemID, string url, List<string> parameters, Dictionary<string, string> headers, string body,
82 out HttpInitialRequestStatus status); 81 out HttpInitialRequestStatus status);
83 82
84 /// <summary> 83 /// <summary>
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/IInventoryAccessModule.cs b/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs
index 6bad018..292b0d6 100644
--- a/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs
@@ -70,6 +70,7 @@ namespace OpenSim.Region.Framework.Interfaces
70 /// </remarks> 70 /// </remarks>
71 /// <param name="remoteClient"></param> 71 /// <param name="remoteClient"></param>
72 /// <param name="itemID"></param> 72 /// <param name="itemID"></param>
73 /// <param name="rezGroupID"></param>
73 /// <param name="RayEnd"></param> 74 /// <param name="RayEnd"></param>
74 /// <param name="RayStart"></param> 75 /// <param name="RayStart"></param>
75 /// <param name="RayTargetID"></param> 76 /// <param name="RayTargetID"></param>
@@ -81,6 +82,11 @@ namespace OpenSim.Region.Framework.Interfaces
81 /// <param name="attachment"></param> 82 /// <param name="attachment"></param>
82 /// <returns>The SceneObjectGroup rezzed or null if rez was unsuccessful.</returns> 83 /// <returns>The SceneObjectGroup rezzed or null if rez was unsuccessful.</returns>
83 SceneObjectGroup RezObject( 84 SceneObjectGroup RezObject(
85 IClientAPI remoteClient, UUID itemID, UUID rezGroupID, Vector3 RayEnd, Vector3 RayStart,
86 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
87 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment);
88 // compatibily do not use
89 SceneObjectGroup RezObject(
84 IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart, 90 IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart,
85 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, 91 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
86 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment); 92 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment);
@@ -97,6 +103,7 @@ namespace OpenSim.Region.Framework.Interfaces
97 /// The item from which the object asset came. Can be null, in which case pre and post rez item adjustment and checks are not performed. 103 /// The item from which the object asset came. Can be null, in which case pre and post rez item adjustment and checks are not performed.
98 /// </param> 104 /// </param>
99 /// <param name="assetID">The asset id for the object to rez.</param> 105 /// <param name="assetID">The asset id for the object to rez.</param>
106 /// <param name="rezObjectID">The requested group id for the object to rez.</param>
100 /// <param name="RayEnd"></param> 107 /// <param name="RayEnd"></param>
101 /// <param name="RayStart"></param> 108 /// <param name="RayStart"></param>
102 /// <param name="RayTargetID"></param> 109 /// <param name="RayTargetID"></param>
@@ -107,8 +114,16 @@ namespace OpenSim.Region.Framework.Interfaces
107 /// <param name="fromTaskID"></param> 114 /// <param name="fromTaskID"></param>
108 /// <param name="attachment"></param> 115 /// <param name="attachment"></param>
109 /// <returns>The SceneObjectGroup rezzed or null if rez was unsuccessful.</returns> 116 /// <returns>The SceneObjectGroup rezzed or null if rez was unsuccessful.</returns>
117
118 SceneObjectGroup RezObject(IClientAPI remoteClient, InventoryItemBase item, UUID rezGroupID,
119 UUID assetID, Vector3 RayEnd, Vector3 RayStart,
120 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
121 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment);
122
123 // compatibility do not use
110 SceneObjectGroup RezObject( 124 SceneObjectGroup RezObject(
111 IClientAPI remoteClient, InventoryItemBase item, UUID assetID, Vector3 RayEnd, Vector3 RayStart, 125 IClientAPI remoteClient, InventoryItemBase item,
126 UUID assetID, Vector3 RayEnd, Vector3 RayStart,
112 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, 127 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
113 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment); 128 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment);
114 129
diff --git a/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs
index 1a89721..86aca8e 100644
--- a/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) Contributors 2 * Copyright (c) Contributors
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
@@ -40,7 +40,7 @@ namespace OpenSim.Region.Framework.Interfaces
40 Array = 2, 40 Array = 2,
41 Value = 3 41 Value = 3
42 } 42 }
43 43
44 public enum JsonStoreValueType 44 public enum JsonStoreValueType
45 { 45 {
46 Undefined = 0, 46 Undefined = 0,
@@ -50,7 +50,7 @@ namespace OpenSim.Region.Framework.Interfaces
50 String = 4, 50 String = 4,
51 UUID = 5 51 UUID = 5
52 } 52 }
53 53
54 public struct JsonStoreStats 54 public struct JsonStoreStats
55 { 55 {
56 public int StoreCount; 56 public int StoreCount;
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/IMessageTransferModule.cs b/OpenSim/Region/Framework/Interfaces/IMessageTransferModule.cs
index 290b826..b06ff2b 100644
--- a/OpenSim/Region/Framework/Interfaces/IMessageTransferModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IMessageTransferModule.cs
@@ -31,7 +31,7 @@ namespace OpenSim.Region.Framework.Interfaces
31{ 31{
32 public delegate void MessageResultNotification(bool success); 32 public delegate void MessageResultNotification(bool success);
33 public delegate void UndeliveredMessage(GridInstantMessage im); 33 public delegate void UndeliveredMessage(GridInstantMessage im);
34 34
35 public interface IMessageTransferModule 35 public interface IMessageTransferModule
36 { 36 {
37 event UndeliveredMessage OnUndeliveredMessage; 37 event UndeliveredMessage OnUndeliveredMessage;
diff --git a/OpenSim/Region/Framework/Interfaces/IMoapModule.cs b/OpenSim/Region/Framework/Interfaces/IMoapModule.cs
index 1d3d240..e8be70f 100644
--- a/OpenSim/Region/Framework/Interfaces/IMoapModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IMoapModule.cs
@@ -45,7 +45,7 @@ namespace OpenSim.Region.Framework.Interfaces
45 /// <param name="face"></param> 45 /// <param name="face"></param>
46 /// <returns></returns> 46 /// <returns></returns>
47 MediaEntry GetMediaEntry(SceneObjectPart part, int face); 47 MediaEntry GetMediaEntry(SceneObjectPart part, int face);
48 48
49 /// <summary> 49 /// <summary>
50 /// Set the media entry for a given prim face. 50 /// Set the media entry for a given prim face.
51 /// </summary> 51 /// </summary>
@@ -53,13 +53,13 @@ namespace OpenSim.Region.Framework.Interfaces
53 /// <param name="face"></param> 53 /// <param name="face"></param>
54 /// <param name="me"></param> 54 /// <param name="me"></param>
55 void SetMediaEntry(SceneObjectPart part, int face, MediaEntry me); 55 void SetMediaEntry(SceneObjectPart part, int face, MediaEntry me);
56 56
57 /// <summary> 57 /// <summary>
58 /// Clear the media entry for a given prim face. 58 /// Clear the media entry for a given prim face.
59 /// </summary> 59 /// </summary>
60 /// 60 ///
61 /// This is the equivalent of setting a media entry of null 61 /// This is the equivalent of setting a media entry of null
62 /// 62 ///
63 /// <param name="part"></param> 63 /// <param name="part"></param>
64 /// <param name="face">/param> 64 /// <param name="face">/param>
65 void ClearMediaEntry(SceneObjectPart part, int face); 65 void ClearMediaEntry(SceneObjectPart part, int face);
diff --git a/OpenSim/Region/Framework/Interfaces/INPCModule.cs b/OpenSim/Region/Framework/Interfaces/INPCModule.cs
index 478833e..df872f4 100644
--- a/OpenSim/Region/Framework/Interfaces/INPCModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/INPCModule.cs
@@ -31,6 +31,17 @@ using OpenSim.Region.Framework.Scenes;
31 31
32namespace OpenSim.Region.Framework.Interfaces 32namespace OpenSim.Region.Framework.Interfaces
33{ 33{
34 // option flags for NPCs
35 public enum NPCOptionsFlags : int
36 {
37 None = 0x00, // no flags (max restriction)
38 AllowNotOwned = 0x01, // allow NPCs to be created not Owned
39 AllowSenseAsAvatar = 0x02, // allow NPCs to set to be sensed as Avatars
40 AllowCloneOtherAvatars = 0x04, // allow NPCs to created cloning a avatar in region
41 NoNPCGroup = 0x08, // NPCs will have no group title, otherwise will have "- NPC -"
42 objectGroup = 0x10 // NPC will have host sog groupID
43 }
44
34 /// <summary> 45 /// <summary>
35 /// Temporary interface. More methods to come at some point to make NPCs 46 /// Temporary interface. More methods to come at some point to make NPCs
36 /// more object oriented rather than controlling purely through module 47 /// more object oriented rather than controlling purely through module
@@ -38,12 +49,18 @@ namespace OpenSim.Region.Framework.Interfaces
38 /// </summary> 49 /// </summary>
39 public interface INPC 50 public interface INPC
40 { 51 {
52
41 /// <summary> 53 /// <summary>
42 /// Should this NPC be sensed by LSL sensors as an 'agent' 54 /// Should this NPC be sensed by LSL sensors as an 'agent'
43 /// (interpreted here to mean a normal user) rather than an OpenSim 55 /// (interpreted here to mean a normal user) rather than an OpenSim
44 /// specific NPC extension? 56 /// specific NPC extension?
45 /// </summary> 57 /// </summary>
46 bool SenseAsAgent { get; } 58 bool SenseAsAgent { get; }
59 UUID ActiveGroupId { get; set; }
60 UUID Owner { get; }
61 string profileAbout { get; set; }
62 UUID profileImage { get; set; }
63 string Born { get; set; }
47 } 64 }
48 65
49 public interface INPCModule 66 public interface INPCModule
@@ -94,7 +111,7 @@ namespace OpenSim.Region.Framework.Interfaces
94 /// failure. 111 /// failure.
95 /// </returns> 112 /// </returns>
96 UUID CreateNPC(string firstname, string lastname, 113 UUID CreateNPC(string firstname, string lastname,
97 Vector3 position, UUID agentID, UUID owner, bool senseAsAgent, Scene scene, 114 Vector3 position, UUID agentID, UUID owner, string groupTitle, UUID groupID, bool senseAsAgent, Scene scene,
98 AvatarAppearance appearance); 115 AvatarAppearance appearance);
99 116
100 /// <summary> 117 /// <summary>
@@ -284,5 +301,7 @@ namespace OpenSim.Region.Framework.Interfaces
284 /// agent, the agent is unowned or the agent was not an NPC. 301 /// agent, the agent is unowned or the agent was not an NPC.
285 /// </returns> 302 /// </returns>
286 UUID GetOwner(UUID agentID); 303 UUID GetOwner(UUID agentID);
304
305 NPCOptionsFlags NPCOptionFlags {get;}
287 } 306 }
288} 307}
diff --git a/OpenSim/Region/Framework/Interfaces/IPermissionsModule.cs b/OpenSim/Region/Framework/Interfaces/IPermissionsModule.cs
index 1ed978b..933ca14 100644
--- a/OpenSim/Region/Framework/Interfaces/IPermissionsModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IPermissionsModule.cs
@@ -42,7 +42,7 @@ namespace OpenSim.Region.Framework.Interfaces
42 42
43 public interface IPermissionsModule 43 public interface IPermissionsModule
44 { 44 {
45 45
46 /// <summary> 46 /// <summary>
47 /// Returns the type of permissions that the user has over an object. 47 /// Returns the type of permissions that the user has over an object.
48 /// </summary> 48 /// </summary>
diff --git a/OpenSim/Region/Framework/Interfaces/IPresenceModule.cs b/OpenSim/Region/Framework/Interfaces/IPresenceModule.cs
index d44c1e1..fb5933c 100644
--- a/OpenSim/Region/Framework/Interfaces/IPresenceModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IPresenceModule.cs
@@ -33,7 +33,7 @@ namespace OpenSim.Region.Framework.Interfaces
33 { 33 {
34 public string UserID; 34 public string UserID;
35 public UUID RegionID; 35 public UUID RegionID;
36 36
37 public PresenceInfo(string userID, UUID regionID) 37 public PresenceInfo(string userID, UUID regionID)
38 { 38 {
39 UserID = userID; 39 UserID = userID;
diff --git a/OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs b/OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs
index 99bc87d..9370ccd 100644
--- a/OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IRegionArchiverModule.cs
@@ -40,17 +40,17 @@ namespace OpenSim.Region.Framework.Interfaces
40 { 40 {
41 void HandleLoadOarConsoleCommand(string module, string[] cmdparams); 41 void HandleLoadOarConsoleCommand(string module, string[] cmdparams);
42 void HandleSaveOarConsoleCommand(string module, string[] cmdparams); 42 void HandleSaveOarConsoleCommand(string module, string[] cmdparams);
43 43
44 /// <summary> 44 /// <summary>
45 /// Archive the region to the given path 45 /// Archive the region to the given path
46 /// </summary> 46 /// </summary>
47 /// 47 ///
48 /// This method occurs asynchronously. If you want notification of when it has completed then subscribe to 48 /// This method occurs asynchronously. If you want notification of when it has completed then subscribe to
49 /// the EventManager.OnOarFileSaved event. 49 /// the EventManager.OnOarFileSaved event.
50 /// 50 ///
51 /// <param name="savePath"></param> 51 /// <param name="savePath"></param>
52 void ArchiveRegion(string savePath, Dictionary<string, object> options); 52 void ArchiveRegion(string savePath, Dictionary<string, object> options);
53 53
54 /// <summary> 54 /// <summary>
55 /// Archive the region to the given path 55 /// Archive the region to the given path
56 /// </summary> 56 /// </summary>
@@ -94,35 +94,35 @@ namespace OpenSim.Region.Framework.Interfaces
94 /// </remarks> 94 /// </remarks>
95 /// <param name="loadPath"></param> 95 /// <param name="loadPath"></param>
96 void DearchiveRegion(string loadPath); 96 void DearchiveRegion(string loadPath);
97 97
98 /// <summary> 98 /// <summary>
99 /// Dearchive the given region archive. This replaces the existing scene. 99 /// Dearchive the given region archive. This replaces the existing scene.
100 /// </summary> 100 /// </summary>
101 /// 101 ///
102 /// If you want notification of when it has completed then subscribe to the EventManager.OnOarFileLoaded event. 102 /// If you want notification of when it has completed then subscribe to the EventManager.OnOarFileLoaded event.
103 /// 103 ///
104 /// <param name="loadPath"></param> 104 /// <param name="loadPath"></param>
105 /// <param name="requestId">If supplied, this request Id is later returned in the saved event</param> 105 /// <param name="requestId">If supplied, this request Id is later returned in the saved event</param>
106 /// <param name="options"> 106 /// <param name="options">
107 /// Dictionary of options. 107 /// Dictionary of options.
108 /// </param> 108 /// </param>
109 void DearchiveRegion(string loadPath, Guid requestId, Dictionary<string,object> options); 109 void DearchiveRegion(string loadPath, Guid requestId, Dictionary<string,object> options);
110 110
111 /// <summary> 111 /// <summary>
112 /// Dearchive a region from a stream. This replaces the existing scene. 112 /// Dearchive a region from a stream. This replaces the existing scene.
113 /// </summary> 113 /// </summary>
114 /// 114 ///
115 /// If you want notification of when it has completed then subscribe to the EventManager.OnOarFileLoaded event. 115 /// If you want notification of when it has completed then subscribe to the EventManager.OnOarFileLoaded event.
116 /// 116 ///
117 /// <param name="loadStream"></param> 117 /// <param name="loadStream"></param>
118 void DearchiveRegion(Stream loadStream); 118 void DearchiveRegion(Stream loadStream);
119 119
120 /// <summary> 120 /// <summary>
121 /// Dearchive a region from a stream. This replaces the existing scene. 121 /// Dearchive a region from a stream. This replaces the existing scene.
122 /// </summary> 122 /// </summary>
123 /// 123 ///
124 /// If you want notification of when it has completed then subscribe to the EventManager.OnOarFileLoaded event. 124 /// If you want notification of when it has completed then subscribe to the EventManager.OnOarFileLoaded event.
125 /// 125 ///
126 /// <param name="loadStream"></param> 126 /// <param name="loadStream"></param>
127 /// <param name="requestId">If supplied, this request Id is later returned in the saved event</param> 127 /// <param name="requestId">If supplied, this request Id is later returned in the saved event</param>
128 /// <param name="options"> 128 /// <param name="options">
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/IRegionModuleBase.cs b/OpenSim/Region/Framework/Interfaces/IRegionModuleBase.cs
index 2089bce..5b8f0f0 100644
--- a/OpenSim/Region/Framework/Interfaces/IRegionModuleBase.cs
+++ b/OpenSim/Region/Framework/Interfaces/IRegionModuleBase.cs
@@ -92,7 +92,7 @@ namespace OpenSim.Region.Framework.Interfaces
92 /// this will be multiple times in one instance, while a nonshared 92 /// this will be multiple times in one instance, while a nonshared
93 /// module instance will only be called once. 93 /// module instance will only be called once.
94 /// This method is called after AddRegion has been called in all 94 /// This method is called after AddRegion has been called in all
95 /// modules for that scene, providing an opportunity to request 95 /// modules for that scene, providing an opportunity to request
96 /// another module's interface, or hook an event from another module. 96 /// another module's interface, or hook an event from another module.
97 /// </summary> 97 /// </summary>
98 /// <param name="scene"> 98 /// <param name="scene">
diff --git a/OpenSim/Region/Framework/Interfaces/IRegionSerialiserModule.cs b/OpenSim/Region/Framework/Interfaces/IRegionSerialiserModule.cs
index c5b21a8..60586ff 100644
--- a/OpenSim/Region/Framework/Interfaces/IRegionSerialiserModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IRegionSerialiserModule.cs
@@ -102,9 +102,9 @@ namespace OpenSim.Region.Framework.Interfaces
102 /// <param name="min"></param> 102 /// <param name="min"></param>
103 /// <param name="max"></param> 103 /// <param name="max"></param>
104 void SavePrimListToXml2(EntityBase[] entityList, TextWriter stream, Vector3 min, Vector3 max); 104 void SavePrimListToXml2(EntityBase[] entityList, TextWriter stream, Vector3 min, Vector3 max);
105 105
106 void SaveNamedPrimsToXml2(Scene scene, string primName, string fileName); 106 void SaveNamedPrimsToXml2(Scene scene, string primName, string fileName);
107 107
108 /// <summary> 108 /// <summary>
109 /// Deserializes a scene object from its xml2 representation. This does not load the object into the scene. 109 /// Deserializes a scene object from its xml2 representation. This does not load the object into the scene.
110 /// </summary> 110 /// </summary>
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..f8a6b53 100644
--- a/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs
@@ -64,12 +64,19 @@ namespace OpenSim.Region.Framework.Interfaces
64 List<SceneObjectGroup> LoadObjects(UUID regionUUID); 64 List<SceneObjectGroup> LoadObjects(UUID regionUUID);
65 65
66 /// <summary> 66 /// <summary>
67 /// Store a terrain revision in region storage 67 /// Store terrain in region storage
68 /// </summary> 68 /// </summary>
69 /// <param name="ter">HeightField data</param> 69 /// <param name="ter">HeightField data</param>
70 /// <param name="regionID">region UUID</param> 70 /// <param name="regionID">region UUID</param>
71 void StoreTerrain(TerrainData terrain, UUID regionID); 71 void StoreTerrain(TerrainData terrain, UUID regionID);
72 72
73 /// <summary>
74 /// Store baked terrain in region storage
75 /// </summary>
76 /// <param name="ter">HeightField data</param>
77 /// <param name="regionID">region UUID</param>
78 void StoreBakedTerrain(TerrainData terrain, UUID regionID);
79
73 // Legacy version kept for downward compabibility 80 // Legacy version kept for downward compabibility
74 void StoreTerrain(double[,] terrain, UUID regionID); 81 void StoreTerrain(double[,] terrain, UUID regionID);
75 82
@@ -82,6 +89,7 @@ namespace OpenSim.Region.Framework.Interfaces
82 /// <param name="sizeZ">the Z dimension of the region being filled</param> 89 /// <param name="sizeZ">the Z dimension of the region being filled</param>
83 /// <returns>Heightfield data</returns> 90 /// <returns>Heightfield data</returns>
84 TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ); 91 TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ);
92 TerrainData LoadBakedTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ);
85 93
86 // Legacy version kept for downward compabibility 94 // Legacy version kept for downward compabibility
87 double[,] LoadTerrain(UUID regionID); 95 double[,] LoadTerrain(UUID regionID);
@@ -125,6 +133,8 @@ namespace OpenSim.Region.Framework.Interfaces
125 /// <param name="regionUUID">the region UUID</param> 133 /// <param name="regionUUID">the region UUID</param>
126 void RemoveRegionEnvironmentSettings(UUID regionUUID); 134 void RemoveRegionEnvironmentSettings(UUID regionUUID);
127 135
136 UUID[] GetObjectIDs(UUID regionID);
137
128 void SaveExtra(UUID regionID, string name, string value); 138 void SaveExtra(UUID regionID, string name, string value);
129 139
130 void RemoveExtra(UUID regionID, string name); 140 void RemoveExtra(UUID regionID, string name);
diff --git a/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs b/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
index 917b5d1..19ba787 100644
--- a/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
@@ -45,7 +45,7 @@ namespace OpenSim.Region.Framework.Interfaces
45 /// Dispose the database 45 /// Dispose the database
46 /// </summary> 46 /// </summary>
47 void Dispose(); 47 void Dispose();
48 48
49 /// <summary> 49 /// <summary>
50 /// Stores all object's details apart from inventory 50 /// Stores all object's details apart from inventory
51 /// </summary> 51 /// </summary>
@@ -75,17 +75,25 @@ namespace OpenSim.Region.Framework.Interfaces
75 List<SceneObjectGroup> LoadObjects(UUID regionUUID); 75 List<SceneObjectGroup> LoadObjects(UUID regionUUID);
76 76
77 /// <summary> 77 /// <summary>
78 /// Store a terrain revision in region storage 78 /// Store a terrain in region storage
79 /// </summary> 79 /// </summary>
80 /// <param name="ter">HeightField data</param> 80 /// <param name="ter">HeightField data</param>
81 /// <param name="regionID">region UUID</param> 81 /// <param name="regionID">region UUID</param>
82 void StoreTerrain(TerrainData terrain, UUID regionID); 82 void StoreTerrain(TerrainData terrain, UUID regionID);
83 83
84 /// <summary>
85 /// Store baked terrain in region storage
86 /// </summary>
87 /// <param name="ter">HeightField data</param>
88 /// <param name="regionID">region UUID</param>
89 void StoreBakedTerrain(TerrainData terrain, UUID regionID);
90
91
84 // Legacy version kept for downward compabibility 92 // Legacy version kept for downward compabibility
85 void StoreTerrain(double[,] terrain, UUID regionID); 93 void StoreTerrain(double[,] terrain, UUID regionID);
86 94
87 /// <summary> 95 /// <summary>
88 /// Load the latest terrain revision from region storage 96 /// Load terrain from region storage
89 /// </summary> 97 /// </summary>
90 /// <param name="regionID">the region UUID</param> 98 /// <param name="regionID">the region UUID</param>
91 /// <param name="pSizeX">the X dimension of the terrain being filled</param> 99 /// <param name="pSizeX">the X dimension of the terrain being filled</param>
@@ -93,12 +101,13 @@ namespace OpenSim.Region.Framework.Interfaces
93 /// <param name="pSizeZ">the Z dimension of the terrain being filled</param> 101 /// <param name="pSizeZ">the Z dimension of the terrain being filled</param>
94 /// <returns>Heightfield data</returns> 102 /// <returns>Heightfield data</returns>
95 TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ); 103 TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ);
104 TerrainData LoadBakedTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ);
96 105
97 // Legacy version kept for downward compabibility 106 // Legacy version kept for downward compabibility
98 double[,] LoadTerrain(UUID regionID); 107 double[,] LoadTerrain(UUID regionID);
99 108
100 void StoreLandObject(ILandObject Parcel); 109 void StoreLandObject(ILandObject Parcel);
101 110
102 /// <summary> 111 /// <summary>
103 /// <list type="bullet"> 112 /// <list type="bullet">
104 /// <item>delete from land where UUID=globalID</item> 113 /// <item>delete from land where UUID=globalID</item>
@@ -107,7 +116,7 @@ namespace OpenSim.Region.Framework.Interfaces
107 /// </summary> 116 /// </summary>
108 /// <param name="globalID"></param> 117 /// <param name="globalID"></param>
109 void RemoveLandObject(UUID globalID); 118 void RemoveLandObject(UUID globalID);
110 119
111 List<LandData> LoadLandObjects(UUID regionUUID); 120 List<LandData> LoadLandObjects(UUID regionUUID);
112 121
113 void StoreRegionSettings(RegionSettings rs); 122 void StoreRegionSettings(RegionSettings rs);
@@ -115,6 +124,7 @@ namespace OpenSim.Region.Framework.Interfaces
115 RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID); 124 RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID);
116 void StoreRegionWindlightSettings(RegionLightShareData wl); 125 void StoreRegionWindlightSettings(RegionLightShareData wl);
117 void RemoveRegionWindlightSettings(UUID regionID); 126 void RemoveRegionWindlightSettings(UUID regionID);
127 UUID[] GetObjectIDs(UUID regionID);
118 128
119 /// <summary> 129 /// <summary>
120 /// Load Environment settings from region storage 130 /// 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..10f421b
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs
@@ -0,0 +1,47 @@
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 OpenSim.Region.Framework.Scenes;
29
30public interface ISnmpModule
31{
32 void Trap(int code, string Message, Scene scene);
33 void Critical(string Message, Scene scene);
34 void Warning(string Message, Scene scene);
35 void Major(string Message, Scene scene);
36 void ColdStart(int step , Scene scene);
37 void Shutdown(int step , Scene scene);
38 //
39 // Node Start/stop events
40 //
41 void LinkUp(Scene scene);
42 void LinkDown(Scene scene);
43 void BootInfo(string data, Scene scene);
44 void trapDebug(string Module,string data, Scene scene);
45 void trapXMRE(int data, string Message, Scene scene);
46
47}
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/ITerrainChannel.cs b/OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs
index f660b8d..78db02a 100644
--- a/OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs
+++ b/OpenSim/Region/Framework/Interfaces/ITerrainChannel.cs
@@ -59,5 +59,13 @@ namespace OpenSim.Region.Framework.Interfaces
59 void LoadFromXmlString(string data); 59 void LoadFromXmlString(string data);
60 // Merge some terrain into this channel 60 // Merge some terrain into this channel
61 void Merge(ITerrainChannel newTerrain, Vector3 displacement, float radianRotation, Vector2 rotationDisplacement); 61 void Merge(ITerrainChannel newTerrain, Vector3 displacement, float radianRotation, Vector2 rotationDisplacement);
62
63 /// </summary>
64 /// <param name="newTerrain"></param>
65 /// <param name="displacement">&lt;x, y, z&gt;</param>
66 /// <param name="rotationDegrees"></param>
67 /// <param name="boundingOrigin">&lt;x, y&gt;</param>
68 /// <param name="boundingSize">&lt;x, y&gt;</param>
69 void MergeWithBounding(ITerrainChannel newTerrain, Vector3 displacement, float rotationDegrees, Vector2 boundingOrigin, Vector2 boundingSize);
62 } 70 }
63} 71}
diff --git a/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs b/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs
index 28f797a..3fc5ce7 100644
--- a/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs
@@ -24,10 +24,9 @@
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 */
27using System.IO;
28 27
28using System.IO;
29using OpenSim.Framework; 29using OpenSim.Framework;
30
31using OpenMetaverse; 30using OpenMetaverse;
32 31
33namespace OpenSim.Region.Framework.Interfaces 32namespace OpenSim.Region.Framework.Interfaces
@@ -43,13 +42,13 @@ namespace OpenSim.Region.Framework.Interfaces
43 /// Use this if you change terrain data outside of the terrain module (e.g. in osTerrainSetHeight) 42 /// Use this if you change terrain data outside of the terrain module (e.g. in osTerrainSetHeight)
44 /// </summary> 43 /// </summary>
45 void TaintTerrain(); 44 void TaintTerrain();
46 45
47 /// <summary> 46 /// <summary>
48 /// When a client initially connects, all the terrain must be pushed to the viewer. 47 /// 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. 48 /// This call causes all the terrain patches to be sent to the client.
50 /// </summary> 49 /// </summary>
51 void PushTerrain(IClientAPI pClient); 50 void PushTerrain(IClientAPI pClient);
52 51
53 /// <summary> 52 /// <summary>
54 /// Load a terrain from a stream. 53 /// Load a terrain from a stream.
55 /// </summary> 54 /// </summary>
@@ -58,8 +57,11 @@ namespace OpenSim.Region.Framework.Interfaces
58 /// </param> 57 /// </param>
59 /// <param name="stream"></param> 58 /// <param name="stream"></param>
60 void LoadFromStream(string filename, Stream stream); 59 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); 60 void LoadFromStream(string filename, System.Uri pathToTerrainHeightmap);
61 void LoadFromStream(string filename, Vector3 displacement,
62 float radianRotation, Vector2 rotationDisplacement, Stream stream);
63 void LoadFromStream(string filename, Vector3 displacement,
64 float rotationDegress, Vector2 boundingOrigin, Vector2 boundingSize, Stream stream);
63 /// <summary> 65 /// <summary>
64 /// Save a terrain to a stream. 66 /// Save a terrain to a stream.
65 /// </summary> 67 /// </summary>
diff --git a/OpenSim/Region/Framework/Interfaces/IUrlModule.cs b/OpenSim/Region/Framework/Interfaces/IUrlModule.cs
index 79e9f9d..3fc0c44 100644
--- a/OpenSim/Region/Framework/Interfaces/IUrlModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IUrlModule.cs
@@ -25,6 +25,7 @@
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.Collections;
28using System.Collections.Generic; 29using System.Collections.Generic;
29using OpenMetaverse; 30using OpenMetaverse;
30using OpenSim.Framework; 31using OpenSim.Framework;
@@ -35,12 +36,12 @@ namespace OpenSim.Region.Framework.Interfaces
35 public interface IUrlModule 36 public interface IUrlModule
36 { 37 {
37 string ExternalHostNameForLSL { get; } 38 string ExternalHostNameForLSL { get; }
38 UUID RequestURL(IScriptModule engine, SceneObjectPart host, UUID itemID); 39 UUID RequestURL(IScriptModule engine, SceneObjectPart host, UUID itemID, Hashtable options);
39 UUID RequestSecureURL(IScriptModule engine, SceneObjectPart host, UUID itemID); 40 UUID RequestSecureURL(IScriptModule engine, SceneObjectPart host, UUID itemID, Hashtable options);
40 void ReleaseURL(string url); 41 void ReleaseURL(string url);
41 void HttpResponse(UUID request, int status, string body); 42 void HttpResponse(UUID request, int status, string body);
42 void HttpContentType(UUID request, string type); 43 void HttpContentType(UUID request, string type);
43 44
44 string GetHttpHeader(UUID request, string header); 45 string GetHttpHeader(UUID request, string header);
45 int GetFreeUrls(); 46 int GetFreeUrls();
46 47
diff --git a/OpenSim/Region/OptionalModules/RegionCombinerModule/RegionData.cs b/OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs
index 42fca9f..027a7e2 100644
--- a/OpenSim/Region/OptionalModules/RegionCombinerModule/RegionData.cs
+++ b/OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs
@@ -25,16 +25,11 @@
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 OpenMetaverse;
29using OpenSim.Region.Framework.Scenes; 28using OpenSim.Region.Framework.Scenes;
29using OpenMetaverse;
30 30
31namespace OpenSim.Region.RegionCombinerModule 31public interface IUserAccountCacheModule
32{ 32{
33 public class RegionData 33 void Remove(string name);
34 { 34 void Remove(UUID id);
35 public UUID RegionId; 35}
36 public Scene RegionScene;
37 // Offset of this region from the base of the root region.
38 public Vector3 Offset;
39 }
40} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Interfaces/IVoiceModule.cs b/OpenSim/Region/Framework/Interfaces/IVoiceModule.cs
index 2e555fa..2fe7454 100644
--- a/OpenSim/Region/Framework/Interfaces/IVoiceModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IVoiceModule.cs
@@ -40,6 +40,6 @@ namespace OpenSim.Region.Framework.Interfaces
40 /// This is used by osSetParcelSIPAddress 40 /// This is used by osSetParcelSIPAddress
41 /// </summary> 41 /// </summary>
42 void setLandSIPAddress(string SIPAddress,UUID GlobalID); 42 void setLandSIPAddress(string SIPAddress,UUID GlobalID);
43 43
44 } 44 }
45} 45}
diff --git a/OpenSim/Region/Framework/Interfaces/IWindModelPlugin.cs b/OpenSim/Region/Framework/Interfaces/IWindModelPlugin.cs
index 16b6024..b4bc15c 100644
--- a/OpenSim/Region/Framework/Interfaces/IWindModelPlugin.cs
+++ b/OpenSim/Region/Framework/Interfaces/IWindModelPlugin.cs
@@ -53,7 +53,7 @@ namespace OpenSim.Region.Framework.Interfaces
53 /// <summary> 53 /// <summary>
54 /// Update wind. 54 /// Update wind.
55 /// </summary> 55 /// </summary>
56 void WindUpdate(uint frame); 56 bool WindUpdate(uint frame);
57 57
58 /// <summary> 58 /// <summary>
59 /// Returns the wind vector at the given local region coordinates. 59 /// Returns the wind vector at the given local region coordinates.
diff --git a/OpenSim/Region/Framework/Interfaces/IWindModule.cs b/OpenSim/Region/Framework/Interfaces/IWindModule.cs
index 4a26a71..424df87 100644
--- a/OpenSim/Region/Framework/Interfaces/IWindModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IWindModule.cs
@@ -31,7 +31,7 @@ namespace OpenSim.Region.Framework.Interfaces
31{ 31{
32 public interface IWindModule : INonSharedRegionModule 32 public interface IWindModule : INonSharedRegionModule
33 { 33 {
34 34
35 /// <summary> 35 /// <summary>
36 /// Retrieves the current wind speed at the given Region Coordinates 36 /// Retrieves the current wind speed at the given Region Coordinates
37 /// </summary> 37 /// </summary>
diff --git a/OpenSim/Region/Framework/Interfaces/IWorldComm.cs b/OpenSim/Region/Framework/Interfaces/IWorldComm.cs
index d76a0d7..3da4130 100644
--- a/OpenSim/Region/Framework/Interfaces/IWorldComm.cs
+++ b/OpenSim/Region/Framework/Interfaces/IWorldComm.cs
@@ -140,7 +140,7 @@ namespace OpenSim.Region.Framework.Interfaces
140 /// </summary> 140 /// </summary>
141 /// <returns>ListenerInfo with filter filled in</returns> 141 /// <returns>ListenerInfo with filter filled in</returns>
142 IWorldCommListenerInfo GetNextMessage(); 142 IWorldCommListenerInfo GetNextMessage();
143 143
144 void ListenControl(UUID itemID, int handle, int active); 144 void ListenControl(UUID itemID, int handle, int active);
145 void ListenRemove(UUID itemID, int handle); 145 void ListenRemove(UUID itemID, int handle);
146 void DeleteListener(UUID itemID); 146 void DeleteListener(UUID itemID);
diff --git a/OpenSim/Region/Framework/Interfaces/IWorldMapModule.cs b/OpenSim/Region/Framework/Interfaces/IWorldMapModule.cs
index 9c781e1..ee7c4ec 100644
--- a/OpenSim/Region/Framework/Interfaces/IWorldMapModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IWorldMapModule.cs
@@ -36,7 +36,6 @@ namespace OpenSim.Region.Framework.Interfaces
36 /// Generate a map tile for the scene. a terrain texture for this scene 36 /// Generate a map tile for the scene. a terrain texture for this scene
37 /// </summary> 37 /// </summary>
38 void GenerateMaptile(); 38 void GenerateMaptile();
39 List<MapBlockData> Map2BlockFromGridRegion(GridRegion r, uint flag); 39 void MapBlockFromGridRegion(MapBlockData block, GridRegion r, uint flag);
40 MapBlockData MapBlockFromGridRegion(GridRegion r, uint flag);
41 } 40 }
42} 41}
diff --git a/OpenSim/Region/Framework/Properties/AssemblyInfo.cs b/OpenSim/Region/Framework/Properties/AssemblyInfo.cs
index e5a3a4c..f91dfd3 100644
--- a/OpenSim/Region/Framework/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/Framework/Properties/AssemblyInfo.cs
@@ -3,7 +3,7 @@ using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices; 3using System.Runtime.InteropServices;
4using Mono.Addins; 4using Mono.Addins;
5 5
6// General Information about an assembly is controlled through the following 6// General Information about an assembly is controlled through the following
7// set of attributes. Change these attribute values to modify the information 7// set of attributes. Change these attribute values to modify the information
8// associated with an assembly. 8// associated with an assembly.
9[assembly: AssemblyTitle("OpenSim.Region.Framework")] 9[assembly: AssemblyTitle("OpenSim.Region.Framework")]
@@ -15,8 +15,8 @@ using Mono.Addins;
15[assembly: AssemblyTrademark("")] 15[assembly: AssemblyTrademark("")]
16[assembly: AssemblyCulture("")] 16[assembly: AssemblyCulture("")]
17 17
18// Setting ComVisible to false makes the types in this assembly not visible 18// Setting ComVisible to false makes the types in this assembly not visible
19// to COM components. If you need to access a type in this assembly from 19// to COM components. If you need to access a type in this assembly from
20// COM, set the ComVisible attribute to true on that type. 20// COM, set the ComVisible attribute to true on that type.
21[assembly: ComVisible(false)] 21[assembly: ComVisible(false)]
22 22
@@ -27,10 +27,10 @@ using Mono.Addins;
27// Version information for an assembly consists of the following four values: 27// Version information for an assembly consists of the following four values:
28// 28//
29// Major Version 29// Major Version
30// Minor Version 30// Minor Version
31// Build Number 31// Build Number
32// Revision 32// Revision
33// 33//
34[assembly: AssemblyVersion("0.8.3.*")] 34[assembly: AssemblyVersion(OpenSim.VersionInfo.AssemblyVersionNumber)]
35[assembly: AddinRoot("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)] 35[assembly: AddinRoot("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)]
36 36
diff --git a/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs
index eb1a970..4d350dd 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs
@@ -48,16 +48,16 @@ namespace OpenSim.Region.Framework.Scenes.Animation
48 private OpenSim.Framework.Animation m_defaultAnimation = new OpenSim.Framework.Animation(); 48 private OpenSim.Framework.Animation m_defaultAnimation = new OpenSim.Framework.Animation();
49 private List<OpenSim.Framework.Animation> m_animations = new List<OpenSim.Framework.Animation>(); 49 private List<OpenSim.Framework.Animation> m_animations = new List<OpenSim.Framework.Animation>();
50 50
51 public OpenSim.Framework.Animation DefaultAnimation 51 public OpenSim.Framework.Animation DefaultAnimation
52 { 52 {
53 get { return m_defaultAnimation; } 53 get { return m_defaultAnimation; }
54 } 54 }
55 55
56 public OpenSim.Framework.Animation ImplicitDefaultAnimation 56 public OpenSim.Framework.Animation ImplicitDefaultAnimation
57 { 57 {
58 get { return m_implicitDefaultAnimation; } 58 get { return m_implicitDefaultAnimation; }
59 } 59 }
60 60
61 public AnimationSet() 61 public AnimationSet()
62 { 62 {
63 ResetDefaultAnimation(); 63 ResetDefaultAnimation();
@@ -101,7 +101,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
101 /// </summary> 101 /// </summary>
102 /// <param name='animID'></param> 102 /// <param name='animID'></param>
103 /// <param name='allowNoDefault'> 103 /// <param name='allowNoDefault'>
104 /// If true, then the default animation can be entirely removed. 104 /// If true, then the default animation can be entirely removed.
105 /// If false, then removing the default animation will reset it to the simulator default (currently STAND). 105 /// If false, then removing the default animation will reset it to the simulator default (currently STAND).
106 /// </param> 106 /// </param>
107 public bool Remove(UUID animID, bool allowNoDefault) 107 public bool Remove(UUID animID, bool allowNoDefault)
@@ -215,9 +215,9 @@ namespace OpenSim.Region.Framework.Scenes.Animation
215 foreach (OpenSim.Framework.Animation anim in m_animations) 215 foreach (OpenSim.Framework.Animation anim in m_animations)
216 theArray[i++] = anim; 216 theArray[i++] = anim;
217 } 217 }
218 catch 218 catch
219 { 219 {
220 /* S%^t happens. Ignore. */ 220 /* S%^t happens. Ignore. */
221 } 221 }
222 return theArray; 222 return theArray;
223 } 223 }
diff --git a/OpenSim/Region/Framework/Scenes/Animation/BinBVHAnimation.cs b/OpenSim/Region/Framework/Scenes/Animation/BinBVHAnimation.cs
index b3b38b2..def993f 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/BinBVHAnimation.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/BinBVHAnimation.cs
@@ -33,8 +33,8 @@ namespace OpenSim.Region.Framework.Scenes.Animation
33{ 33{
34 /// <summary> 34 /// <summary>
35 /// Written to decode and encode a binary animation asset. 35 /// Written to decode and encode a binary animation asset.
36 /// The SecondLife Client reads in a BVH file and converts 36 /// The SecondLife Client reads in a BVH file and converts
37 /// it to the format described here. This isn't 37 /// it to the format described here. This isn't
38 /// </summary> 38 /// </summary>
39 public class BinBVHAnimation 39 public class BinBVHAnimation
40 { 40 {
@@ -109,7 +109,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
109 /// Contains an array of joints 109 /// Contains an array of joints
110 /// </summary> 110 /// </summary>
111 public binBVHJoint[] Joints; 111 public binBVHJoint[] Joints;
112 112
113 113
114 public byte[] ToBytes() 114 public byte[] ToBytes()
115 { 115 {
@@ -136,14 +136,14 @@ namespace OpenSim.Region.Framework.Scenes.Animation
136 Joints[i].WriteBytesToStream(iostream, InPoint, OutPoint); 136 Joints[i].WriteBytesToStream(iostream, InPoint, OutPoint);
137 } 137 }
138 iostream.Write(BinBVHUtil.ES(Utils.IntToBytes(0))); 138 iostream.Write(BinBVHUtil.ES(Utils.IntToBytes(0)));
139 139
140 using (MemoryStream ms2 = (MemoryStream)iostream.BaseStream) 140 using (MemoryStream ms2 = (MemoryStream)iostream.BaseStream)
141 outputbytes = ms2.ToArray(); 141 outputbytes = ms2.ToArray();
142 } 142 }
143 143
144 return outputbytes; 144 return outputbytes;
145 } 145 }
146 146
147 public BinBVHAnimation() 147 public BinBVHAnimation()
148 { 148 {
149 rotationkeys = 0; 149 rotationkeys = 0;
@@ -160,7 +160,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
160 EaseOutTime = 0; 160 EaseOutTime = 0;
161 HandPose = 1; 161 HandPose = 1;
162 m_jointCount = 0; 162 m_jointCount = 0;
163 163
164 Joints = new binBVHJoint[1]; 164 Joints = new binBVHJoint[1];
165 Joints[0] = new binBVHJoint(); 165 Joints[0] = new binBVHJoint();
166 Joints[0].Name = "mPelvis"; 166 Joints[0].Name = "mPelvis";
@@ -180,7 +180,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
180 Joints[0].positionkeys[0].key_element.X = ((float)rnd.NextDouble() * 2 - 1); 180 Joints[0].positionkeys[0].key_element.X = ((float)rnd.NextDouble() * 2 - 1);
181 Joints[0].positionkeys[0].key_element.Y = ((float)rnd.NextDouble() * 2 - 1); 181 Joints[0].positionkeys[0].key_element.Y = ((float)rnd.NextDouble() * 2 - 1);
182 Joints[0].positionkeys[0].key_element.Z = ((float)rnd.NextDouble() * 2 - 1); 182 Joints[0].positionkeys[0].key_element.Z = ((float)rnd.NextDouble() * 2 - 1);
183 183
184 184
185 } 185 }
186 186
@@ -235,7 +235,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
235 } 235 }
236 } 236 }
237 237
238 238
239 /// <summary> 239 /// <summary>
240 /// Variable length strings seem to be null terminated in the animation asset.. but.. 240 /// Variable length strings seem to be null terminated in the animation asset.. but..
241 /// use with caution, home grown. 241 /// use with caution, home grown.
@@ -294,7 +294,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
294 /// <returns>The Joint data serialized into the binBVHJoint structure</returns> 294 /// <returns>The Joint data serialized into the binBVHJoint structure</returns>
295 private binBVHJoint readJoint(byte[] data, ref int i) 295 private binBVHJoint readJoint(byte[] data, ref int i)
296 { 296 {
297 297
298 binBVHJointKey[] positions; 298 binBVHJointKey[] positions;
299 binBVHJointKey[] rotations; 299 binBVHJointKey[] rotations;
300 300
@@ -312,14 +312,14 @@ namespace OpenSim.Region.Framework.Scenes.Animation
312 312
313 pJoint.Name = ReadBytesUntilNull(data, ref i); // Joint name 313 pJoint.Name = ReadBytesUntilNull(data, ref i); // Joint name
314 314
315 /* 315 /*
316 2 <- Priority Revisited 316 2 <- Priority Revisited
317 0 317 0
318 0 318 0
319 0 319 0
320 */ 320 */
321 321
322 /* 322 /*
323 5 <-- 5 keyframes 323 5 <-- 5 keyframes
324 0 324 0
325 0 325 0
@@ -327,7 +327,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
327 ... 5 Keyframe data blocks 327 ... 5 Keyframe data blocks
328 */ 328 */
329 329
330 /* 330 /*
331 2 <-- 2 keyframes 331 2 <-- 2 keyframes
332 0 332 0
333 0 333 0
@@ -428,8 +428,8 @@ namespace OpenSim.Region.Framework.Scenes.Animation
428 } 428 }
429 return m_keys; 429 return m_keys;
430 } 430 }
431 431
432 432
433 433
434 } 434 }
435 /// <summary> 435 /// <summary>
@@ -443,7 +443,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
443 public string Name; 443 public string Name;
444 444
445 /// <summary> 445 /// <summary>
446 /// Joint Animation Override? Was the same as the Priority in testing.. 446 /// Joint Animation Override? Was the same as the Priority in testing..
447 /// </summary> 447 /// </summary>
448 public int Priority; 448 public int Priority;
449 449
@@ -523,7 +523,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
523 public static class BinBVHUtil 523 public static class BinBVHUtil
524 { 524 {
525 public const float ONE_OVER_U16_MAX = 1.0f / UInt16.MaxValue; 525 public const float ONE_OVER_U16_MAX = 1.0f / UInt16.MaxValue;
526 526
527 public static UInt16 FloatToUInt16(float val, float lower, float upper) 527 public static UInt16 FloatToUInt16(float val, float lower, float upper)
528 { 528 {
529 UInt16 uival = 0; 529 UInt16 uival = 0;
@@ -536,7 +536,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
536 { 536 {
537 upper -= lower; 537 upper -= lower;
538 val = val - lower; 538 val = val - lower;
539 539
540 // start with 500 upper and 200 lower.. subtract 200 from the upper and the value 540 // start with 500 upper and 200 lower.. subtract 200 from the upper and the value
541 } 541 }
542 else //if (lower < 0 && upper > 0) 542 else //if (lower < 0 && upper > 0)
@@ -558,8 +558,8 @@ namespace OpenSim.Region.Framework.Scenes.Animation
558 558
559 return uival; 559 return uival;
560 } 560 }
561 561
562 562
563 /// <summary> 563 /// <summary>
564 /// Endian Swap 564 /// Endian Swap
565 /// Swaps endianness if necessary 565 /// Swaps endianness if necessary
@@ -590,7 +590,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
590 output[i] = Convert.ToByte(chr[i]); 590 output[i] = Convert.ToByte(chr[i]);
591 591
592 } 592 }
593 593
594 output[i] = Convert.ToByte('\0'); 594 output[i] = Convert.ToByte('\0');
595 return output; 595 return output;
596 } 596 }
diff --git a/OpenSim/Region/Framework/Scenes/Animation/DefaultAvatarAnimations.cs b/OpenSim/Region/Framework/Scenes/Animation/DefaultAvatarAnimations.cs
index b79dd8f..2128d58 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/DefaultAvatarAnimations.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/DefaultAvatarAnimations.cs
@@ -55,10 +55,14 @@ namespace OpenSim.Region.Framework.Scenes.Animation
55 private static void LoadAnimations(string path) 55 private static void LoadAnimations(string path)
56 { 56 {
57// Dictionary<string, UUID> animations = new Dictionary<string, UUID>(); 57// Dictionary<string, UUID> animations = new Dictionary<string, UUID>();
58 58
59 using (XmlTextReader reader = new XmlTextReader(path)) 59 using (XmlTextReader reader = new XmlTextReader(path))
60 { 60 {
61 reader.ProhibitDtd = true;
62
61 XmlDocument doc = new XmlDocument(); 63 XmlDocument doc = new XmlDocument();
64 doc.XmlResolver = null;
65
62 doc.Load(reader); 66 doc.Load(reader);
63// if (doc.DocumentElement != null) 67// if (doc.DocumentElement != null)
64// { 68// {
diff --git a/OpenSim/Region/Framework/Scenes/Animation/MovementAnimationOverrides.cs b/OpenSim/Region/Framework/Scenes/Animation/MovementAnimationOverrides.cs
new file mode 100644
index 0000000..ca3ebfb
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Animation/MovementAnimationOverrides.cs
@@ -0,0 +1,102 @@
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.PhysicsModules.SharedBase;
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 object MAOLock = new object();
56 private Dictionary<string, UUID> m_overrides = new Dictionary<string, UUID>();
57 public void SetOverride(string state, UUID animID)
58 {
59 if (animID == UUID.Zero)
60 {
61 if (state == "ALL")
62 m_overrides.Clear();
63 else
64 m_overrides.Remove(state);
65 return;
66 }
67
68 m_log.DebugFormat("Setting override for {0} to {1}", state, animID);
69
70 lock (MAOLock)
71 m_overrides[state] = animID;
72 }
73
74 public UUID GetOverriddenAnimation(string state)
75 {
76 lock (MAOLock)
77 {
78 if (m_overrides.ContainsKey(state))
79 return m_overrides[state];
80 }
81
82 return UUID.Zero;
83 }
84
85 public Dictionary<string, UUID> CloneAOPairs()
86 {
87 lock (MAOLock)
88 {
89 return new Dictionary<string, UUID>(m_overrides);
90 }
91 }
92
93 public void CopyAOPairsFrom(Dictionary<string, UUID> src)
94 {
95 lock (MAOLock)
96 {
97 m_overrides.Clear();
98 m_overrides = new Dictionary<string, UUID>(src);
99 }
100 }
101 }
102}
diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
index 6d51029..5c33f12 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 }
@@ -120,7 +123,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
120 /// </summary> 123 /// </summary>
121 /// <param name='animID'></param> 124 /// <param name='animID'></param>
122 /// <param name='allowNoDefault'> 125 /// <param name='allowNoDefault'>
123 /// If true, then the default animation can be entirely removed. 126 /// If true, then the default animation can be entirely removed.
124 /// If false, then removing the default animation will reset it to the simulator default (currently STAND). 127 /// If false, then removing the default animation will reset it to the simulator default (currently STAND).
125 /// </param> 128 /// </param>
126 public void RemoveAnimation(UUID animID, bool allowNoDefault) 129 public void RemoveAnimation(UUID animID, bool allowNoDefault)
@@ -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)
184 { 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
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,151 @@ 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 stable on Hover assume falling
403 if(actor.PIDHoverActive && fallVelocity < 0.05f)
404 {
295 Falling = true; 405 Falling = true;
406 currentControlState = motionControlStates.falling;
407 m_lastFallVelocity = fallVelocity;
408 return "FALLDOWN";
409 }
296 410
297 if (m_animTickFall == 0 || (fallVelocity >= 0.0f)) 411 if (fallVelocity < -2.5f)
412 Falling = true;
413
414 if (m_animTickFall == 0 || (fallVelocity >= -0.5f))
298 { 415 {
299 // not falling yet, or going up
300 // reset start of fall time
301 m_animTickFall = Environment.TickCount; 416 m_animTickFall = Environment.TickCount;
302 } 417 }
303 else if (!m_jumping && (fallElapsed > FALL_DELAY) && (fallVelocity < -3.0f) && (m_scenePresence.WasFlying)) 418 else
304 { 419 {
305 // Falling long enough to trigger the animation 420 int fallElapsed = (Environment.TickCount - m_animTickFall);
306 return "FALLDOWN"; 421 if ((fallElapsed > FALL_DELAY) && (fallVelocity < -3.0f))
422 {
423 currentControlState = motionControlStates.falling;
424 m_lastFallVelocity = fallVelocity;
425 // Falling long enough to trigger the animation
426 return "FALLDOWN";
427 }
307 } 428 }
308 429
309 // Check if the user has stopped walking just now 430 // Check if the user has stopped walking just now
310 if (CurrentMovementAnimation == "WALK" && (move == Vector3.Zero)) 431 if (CurrentMovementAnimation == "WALK" && !heldOnXY && !heldDown && !heldUp)
311 return "STAND"; 432 return "STAND";
312 433
313 return CurrentMovementAnimation; 434 return CurrentMovementAnimation;
314 } 435 }
315 436
316 #endregion Falling/Floating/Landing 437 m_animTickFall = 0;
317 438
439 #endregion Falling/Floating/Landing
318 440
319 #region Jumping // section added for jumping... 441 #region Jumping // section added for jumping...
320 442
321 int jumptime; 443 if (isColliding && heldUp && currentControlState != motionControlStates.jumping && !actor.PIDHoverActive)
322 jumptime = Environment.TickCount - m_animTickJump;
323
324 if ((move.Z > 0f) && (!m_jumping))
325 { 444 {
326 // Start jumping, prejump 445 // Start jumping, prejump
327 m_animTickFall = 0; 446 currentControlState = motionControlStates.jumping;
328 m_jumping = true; 447 m_jumping = true;
329 Falling = false; 448 Falling = false;
330 actor.Selected = true; // borrowed for jumping flag
331 m_animTickJump = Environment.TickCount; 449 m_animTickJump = Environment.TickCount;
332 m_jumpVelocity = 0.35f;
333 return "PREJUMP"; 450 return "PREJUMP";
334 } 451 }
335 452
336 if (m_jumping) 453 if (currentControlState == motionControlStates.jumping)
337 { 454 {
455 int jumptime = Environment.TickCount - m_animTickJump;
338 if ((jumptime > (JUMP_PERIOD * 1.5f)) && actor.IsColliding) 456 if ((jumptime > (JUMP_PERIOD * 1.5f)) && actor.IsColliding)
339 { 457 {
340 // end jumping 458 // end jumping
341 m_jumping = false; 459 m_jumping = false;
342 Falling = false; 460 Falling = false;
343 actor.Selected = false; // borrowed for jumping flag 461 actor.Selected = false; // borrowed for jumping flag
344 m_jumpVelocity = 0f; 462 m_animTickLand = Environment.TickCount;
345 m_animTickFall = Environment.TickCount; 463 currentControlState = motionControlStates.landing;
346 return "LAND"; 464 return "LAND";
347 } 465 }
348 else if (jumptime > JUMP_PERIOD) 466 else if (jumptime > JUMP_PERIOD)
349 { 467 {
350 // jump down 468 // jump down
351 m_jumpVelocity = 0f;
352 return "JUMP"; 469 return "JUMP";
353 } 470 }
354 else if (jumptime > PREJUMP_DELAY) 471 else if (jumptime > PREJUMP_DELAY)
355 { 472 {
356 // jump up 473 // jump up
357 m_jumping = true; 474 m_jumping = true;
358 m_jumpVelocity = 10f;
359 return "JUMP"; 475 return "JUMP";
360 } 476 }
477 return CurrentMovementAnimation;
361 } 478 }
362 479
363 #endregion Jumping 480 #endregion Jumping
364 481
365 #region Ground Movement 482 #region Ground Movement
366 483
367 if (CurrentMovementAnimation == "FALLDOWN") 484 if (currentControlState == motionControlStates.falling)
368 { 485 {
369 Falling = false; 486 Falling = false;
370 m_animTickFall = Environment.TickCount; 487 currentControlState = motionControlStates.landing;
488 m_animTickLand = Environment.TickCount;
371 // TODO: SOFT_LAND support 489 // TODO: SOFT_LAND support
372 float fallHeight = m_fallHeight - actor.Position.Z; 490 float fallVsq = m_lastFallVelocity * m_lastFallVelocity;
373 if (fallHeight > 15.0f) 491 if (fallVsq > 300f) // aprox 20*h
374 return "STANDUP"; 492 return "STANDUP";
375 else if (fallHeight > 8.0f) 493 else if (fallVsq > 160f)
376 return "SOFT_LAND"; 494 return "SOFT_LAND";
377 else 495 else
378 return "LAND"; 496 return "LAND";
379 } 497 }
380 else if ((CurrentMovementAnimation == "LAND") || (CurrentMovementAnimation == "SOFT_LAND") || (CurrentMovementAnimation == "STANDUP")) 498
499
500 if (currentControlState == motionControlStates.landing)
381 { 501 {
382 int landElapsed = Environment.TickCount - m_animTickFall; 502 Falling = false;
503 int landElapsed = Environment.TickCount - m_animTickLand;
383 int limit = 1000; 504 int limit = 1000;
384 if (CurrentMovementAnimation == "LAND") 505 if (CurrentMovementAnimation == "LAND")
385 limit = 350; 506 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 507 // NB if the above is set too long a weird anim reset from some place prevents STAND from being sent to client
387 508
388 if ((m_animTickFall != 0) && (landElapsed <= limit)) 509 if ((m_animTickLand != 0) && (landElapsed <= limit))
389 { 510 {
390 return CurrentMovementAnimation; 511 return CurrentMovementAnimation;
391 } 512 }
392 else 513 else
393 { 514 {
394 m_fallHeight = actor.Position.Z; // save latest flying height 515 currentControlState = motionControlStates.onsurface;
516 m_animTickLand = 0;
395 return "STAND"; 517 return "STAND";
396 } 518 }
397 } 519 }
398 520
399 // next section moved outside paren. and realigned for jumping 521 // next section moved outside paren. and realigned for jumping
400 if (move.X != 0f || move.Y != 0f) 522
523 if (heldOnXY)
401 { 524 {
402 m_fallHeight = actor.Position.Z; // save latest flying height 525 currentControlState = motionControlStates.onsurface;
403 Falling = false; 526 Falling = false;
404 // Walking / crouchwalking / running 527 // Walking / crouchwalking / running
405 if (move.Z < 0f) 528 if (heldDown)
406 { 529 {
407 return "CROUCHWALK"; 530 return "CROUCHWALK";
408 } 531 }
@@ -416,11 +539,12 @@ namespace OpenSim.Region.Framework.Scenes.Animation
416 return "WALK"; 539 return "WALK";
417 } 540 }
418 } 541 }
419 else if (!m_jumping) 542 else
420 { 543 {
544 currentControlState = motionControlStates.onsurface;
421 Falling = false; 545 Falling = false;
422 // Not walking 546 // Not walking
423 if (move.Z < 0) 547 if (heldDown)
424 return "CROUCH"; 548 return "CROUCH";
425 else if (heldTurnLeft) 549 else if (heldTurnLeft)
426 return "TURNLEFT"; 550 return "TURNLEFT";
@@ -431,8 +555,6 @@ namespace OpenSim.Region.Framework.Scenes.Animation
431 } 555 }
432 #endregion Ground Movement 556 #endregion Ground Movement
433 557
434 Falling = false;
435
436 return CurrentMovementAnimation; 558 return CurrentMovementAnimation;
437 } 559 }
438 560
@@ -442,7 +564,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
442 /// <returns>'true' if the animation was changed</returns> 564 /// <returns>'true' if the animation was changed</returns>
443 public bool UpdateMovementAnimations() 565 public bool UpdateMovementAnimations()
444 { 566 {
445// m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Updating movement animations for {0}", m_scenePresence.Name); 567 // m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Updating movement animations for {0}", m_scenePresence.Name);
446 568
447 bool ret = false; 569 bool ret = false;
448 lock (m_animations) 570 lock (m_animations)
@@ -450,7 +572,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
450 string newMovementAnimation = DetermineMovementAnimation(); 572 string newMovementAnimation = DetermineMovementAnimation();
451 if (CurrentMovementAnimation != newMovementAnimation) 573 if (CurrentMovementAnimation != newMovementAnimation)
452 { 574 {
453 CurrentMovementAnimation = DetermineMovementAnimation(); 575 CurrentMovementAnimation = newMovementAnimation;
454 576
455// m_log.DebugFormat( 577// m_log.DebugFormat(
456// "[SCENE PRESENCE ANIMATOR]: Determined animation {0} for {1} in UpdateMovementAnimations()", 578// "[SCENE PRESENCE ANIMATOR]: Determined animation {0} for {1} in UpdateMovementAnimations()",
@@ -464,6 +586,24 @@ namespace OpenSim.Region.Framework.Scenes.Animation
464 return ret; 586 return ret;
465 } 587 }
466 588
589 public bool ForceUpdateMovementAnimations()
590 {
591 lock (m_animations)
592 {
593 CurrentMovementAnimation = DetermineMovementAnimation();
594 return TrySetMovementAnimation(CurrentMovementAnimation);
595 }
596 }
597
598 public bool SetMovementAnimations(string motionState)
599 {
600 lock (m_animations)
601 {
602 CurrentMovementAnimation = motionState;
603 return TrySetMovementAnimation(CurrentMovementAnimation);
604 }
605 }
606
467 public UUID[] GetAnimationArray() 607 public UUID[] GetAnimationArray()
468 { 608 {
469 UUID[] animIDs; 609 UUID[] animIDs;
@@ -472,19 +612,153 @@ namespace OpenSim.Region.Framework.Scenes.Animation
472 m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs); 612 m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs);
473 return animIDs; 613 return animIDs;
474 } 614 }
475 615
476 public BinBVHAnimation GenerateRandomAnimation() 616 public BinBVHAnimation GenerateRandomAnimation()
477 { 617 {
478 int rnditerations = 3; 618 int rnditerations = 3;
479 BinBVHAnimation anim = new BinBVHAnimation(); 619 BinBVHAnimation anim = new BinBVHAnimation();
480 List<string> parts = new List<string>(); 620 List<string> parts = new List<string>();
481 parts.Add("mPelvis");parts.Add("mHead");parts.Add("mTorso"); 621
482 parts.Add("mHipLeft");parts.Add("mHipRight");parts.Add("mHipLeft");parts.Add("mKneeLeft"); 622 /// Torso and Head
483 parts.Add("mKneeRight");parts.Add("mCollarLeft");parts.Add("mCollarRight");parts.Add("mNeck"); 623 parts.Add("mPelvis");
484 parts.Add("mElbowLeft");parts.Add("mElbowRight");parts.Add("mWristLeft");parts.Add("mWristRight"); 624 parts.Add("mTorso");
485 parts.Add("mShoulderLeft");parts.Add("mShoulderRight");parts.Add("mAnkleLeft");parts.Add("mAnkleRight"); 625 parts.Add("mChest");
486 parts.Add("mEyeRight");parts.Add("mChest");parts.Add("mToeLeft");parts.Add("mToeRight"); 626 parts.Add("mNeck");
487 parts.Add("mFootLeft");parts.Add("mFootRight");parts.Add("mEyeLeft"); 627 parts.Add("mHead");
628 parts.Add("mSkull");
629 parts.Add("mEyeRight");
630 parts.Add("mEyeLeft");
631 /// Arms
632 parts.Add("mCollarLeft");
633 parts.Add("mShoulderLeft");
634 parts.Add("mElbowLeft");
635 parts.Add("mWristLeft");
636 parts.Add("mCollarRight");
637 parts.Add("mShoulderRight");
638 parts.Add("mElbowRight");
639 parts.Add("mWristRight");
640 /// Legs
641 parts.Add("mHipLeft");
642 parts.Add("mKneeLeft");
643 parts.Add("mAnkleLeft");
644 parts.Add("mFootLeft");
645 parts.Add("mToeLeft");
646 parts.Add("mHipRight");
647 parts.Add("mKneeRight");
648 parts.Add("mAnkleRight");
649 parts.Add("mFootRight");
650 parts.Add("mToeRight");
651 ///Hands
652 parts.Add("mHandThumb1Left");
653 parts.Add("mHandThumb1Right");
654 parts.Add("mHandThumb2Left");
655 parts.Add("mHandThumb2Right");
656 parts.Add("mHandThumb3Left");
657 parts.Add("mHandThumb3Right");
658 parts.Add("mHandIndex1Left");
659 parts.Add("mHandIndex1Right");
660 parts.Add("mHandIndex2Left");
661 parts.Add("mHandIndex2Right");
662 parts.Add("mHandIndex3Left");
663 parts.Add("mHandIndex3Right");
664 parts.Add("mHandMiddle1Left");
665 parts.Add("mHandMiddle1Right");
666 parts.Add("mHandMiddle2Left");
667 parts.Add("mHandMiddle2Right");
668 parts.Add("mHandMiddle3Left");
669 parts.Add("mHandMiddle3Right");
670 parts.Add("mHandRing1Left");
671 parts.Add("mHandRing1Right");
672 parts.Add("mHandRing2Left");
673 parts.Add("mHandRing2Right");
674 parts.Add("mHandRing3Left");
675 parts.Add("mHandRing3Right");
676 parts.Add("mHandPinky1Left");
677 parts.Add("mHandPinky1Right");
678 parts.Add("mHandPinky2Left");
679 parts.Add("mHandPinky2Right");
680 parts.Add("mHandPinky3Left");
681 parts.Add("mHandPinky3Right");
682 ///Face
683 parts.Add("mFaceForeheadLeft");
684 parts.Add("mFaceForeheadCenter");
685 parts.Add("mFaceForeheadRight");
686 parts.Add("mFaceEyebrowOuterLeft");
687 parts.Add("mFaceEyebrowCenterLeft");
688 parts.Add("mFaceEyebrowInnerLeft");
689 parts.Add("mFaceEyebrowOuterRight");
690 parts.Add("mFaceEyebrowCenterRight");
691 parts.Add("mFaceEyebrowInnerRight");
692 parts.Add("mFaceEyeLidUpperLeft");
693 parts.Add("mFaceEyeLidLowerLeft");
694 parts.Add("mFaceEyeLidUpperRight");
695 parts.Add("mFaceEyeLidLowerRight");
696 parts.Add("mFaceEyeAltLeft");
697 parts.Add("mFaceEyeAltRight");
698 parts.Add("mFaceEyecornerInnerLeft");
699 parts.Add("mFaceEyecornerInnerRight");
700 parts.Add("mFaceEar1Left");
701 parts.Add("mFaceEar2Left");
702 parts.Add("mFaceEar1Right");
703 parts.Add("mFaceEar2Right");
704 parts.Add("mFaceNoseLeft");
705 parts.Add("mFaceNoseCenter");
706 parts.Add("mFaceNoseRight");
707 parts.Add("mFaceNoseBase");
708 parts.Add("mFaceNoseBridge");
709 parts.Add("mFaceCheekUpperInnerLeft");
710 parts.Add("mFaceCheekUpperOuterLeft");
711 parts.Add("mFaceCheekUpperInnerRight");
712 parts.Add("mFaceCheekUpperOuterRight");
713 parts.Add("mFaceJaw");
714 parts.Add("mFaceLipUpperLeft");
715 parts.Add("mFaceLipUpperCenter");
716 parts.Add("mFaceLipUpperRight");
717 parts.Add("mFaceLipCornerLeft");
718 parts.Add("mFaceLipCornerRight");
719 parts.Add("mFaceTongueBase");
720 parts.Add("mFaceTongueTip");
721 parts.Add("mFaceLipLowerLeft");
722 parts.Add("mFaceLipLowerCenter");
723 parts.Add("mFaceLipLowerRight");
724 parts.Add("mFaceTeethLower");
725 parts.Add("mFaceTeethUpper");
726 parts.Add("mFaceChin");
727 ///Spine
728 parts.Add("mSpine1");
729 parts.Add("mSpine2");
730 parts.Add("mSpine3");
731 parts.Add("mSpine4");
732 ///Wings
733 parts.Add("mWingsRoot");
734 parts.Add("mWing1Left");
735 parts.Add("mWing2Left");
736 parts.Add("mWing3Left");
737 parts.Add("mWing4Left");
738 parts.Add("mWing1Right");
739 parts.Add("mWing2Right");
740 parts.Add("mWing3Right");
741 parts.Add("mWing4Right");
742 parts.Add("mWing4FanRight");
743 parts.Add("mWing4FanLeft");
744 ///Hind Limbs
745 parts.Add("mHindLimbsRoot");
746 parts.Add("mHindLimb1Left");
747 parts.Add("mHindLimb2Left");
748 parts.Add("mHindLimb3Left");
749 parts.Add("mHindLimb4Left");
750 parts.Add("mHindLimb1Right");
751 parts.Add("mHindLimb2Right");
752 parts.Add("mHindLimb3Right");
753 parts.Add("mHindLimb4Right");
754 ///Tail
755 parts.Add("mTail1");
756 parts.Add("mTail2");
757 parts.Add("mTail3");
758 parts.Add("mTail4");
759 parts.Add("mTail5");
760 parts.Add("mTail6");
761
488 anim.HandPose = 1; 762 anim.HandPose = 1;
489 anim.InPoint = 0; 763 anim.InPoint = 0;
490 anim.OutPoint = (rnditerations * .10f); 764 anim.OutPoint = (rnditerations * .10f);
@@ -508,12 +782,12 @@ namespace OpenSim.Region.Framework.Scenes.Animation
508 for (int i = 0; i < rnditerations; i++) 782 for (int i = 0; i < rnditerations; i++)
509 { 783 {
510 anim.Joints[j].rotationkeys[i] = new binBVHJointKey(); 784 anim.Joints[j].rotationkeys[i] = new binBVHJointKey();
511 anim.Joints[j].rotationkeys[i].time = (i*.10f); 785 anim.Joints[j].rotationkeys[i].time = (i * .10f);
512 anim.Joints[j].rotationkeys[i].key_element.X = ((float) rnd.NextDouble()*2 - 1); 786 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); 787 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); 788 anim.Joints[j].rotationkeys[i].key_element.Z = ((float)rnd.NextDouble() * 2 - 1);
515 anim.Joints[j].positionkeys[i] = new binBVHJointKey(); 789 anim.Joints[j].positionkeys[i] = new binBVHJointKey();
516 anim.Joints[j].positionkeys[i].time = (i*.10f); 790 anim.Joints[j].positionkeys[i].time = (i * .10f);
517 anim.Joints[j].positionkeys[i].key_element.X = 0; 791 anim.Joints[j].positionkeys[i].key_element.X = 0;
518 anim.Joints[j].positionkeys[i].key_element.Y = 0; 792 anim.Joints[j].positionkeys[i].key_element.Y = 0;
519 anim.Joints[j].positionkeys[i].key_element.Z = 0; 793 anim.Joints[j].positionkeys[i].key_element.Z = 0;
@@ -540,20 +814,17 @@ namespace OpenSim.Region.Framework.Scenes.Animation
540 /// <param name="objectIDs"></param> 814 /// <param name="objectIDs"></param>
541 public void SendAnimPack(UUID[] animations, int[] seqs, UUID[] objectIDs) 815 public void SendAnimPack(UUID[] animations, int[] seqs, UUID[] objectIDs)
542 { 816 {
543 if (m_scenePresence.IsChildAgent) 817 m_scenePresence.SendAnimPack(animations, seqs, objectIDs);
544 return; 818 }
545 819
546// m_log.DebugFormat( 820 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}'", 821 {
548// string.Join(",", Array.ConvertAll<UUID, string>(animations, a => a.ToString())), 822 animIDs = null;
549// string.Join(",", Array.ConvertAll<int, string>(seqs, s => s.ToString())), 823 sequenceNums = null;
550// string.Join(",", Array.ConvertAll<UUID, string>(objectIDs, o => o.ToString()))); 824 objectIDs = null;
551 825
552 m_scenePresence.Scene.ForEachClient( 826 if (m_animations != null)
553 delegate(IClientAPI client) 827 m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs);
554 {
555 client.SendAnimations(animations, seqs, m_scenePresence.ControllingClient.AgentId, objectIDs);
556 });
557 } 828 }
558 829
559 public void SendAnimPackToClient(IClientAPI client) 830 public void SendAnimPackToClient(IClientAPI client)
@@ -575,7 +846,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
575 public void SendAnimPack() 846 public void SendAnimPack()
576 { 847 {
577 //m_log.Debug("Sending animation pack to all"); 848 //m_log.Debug("Sending animation pack to all");
578 849
579 if (m_scenePresence.IsChildAgent) 850 if (m_scenePresence.IsChildAgent)
580 return; 851 return;
581 852
@@ -585,7 +856,8 @@ namespace OpenSim.Region.Framework.Scenes.Animation
585 856
586 m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs); 857 m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs);
587 858
588 SendAnimPack(animIDs, sequenceNums, objectIDs); 859 // SendAnimPack(animIDs, sequenceNums, objectIDs);
860 m_scenePresence.SendAnimPack(animIDs, sequenceNums, objectIDs);
589 } 861 }
590 862
591 public string GetAnimName(UUID animId) 863 public string GetAnimName(UUID animId)
diff --git a/OpenSim/Region/Framework/Scenes/AsyncInventorySender.cs b/OpenSim/Region/Framework/Scenes/AsyncInventorySender.cs
index d9d2e64..c874fdb 100644
--- a/OpenSim/Region/Framework/Scenes/AsyncInventorySender.cs
+++ b/OpenSim/Region/Framework/Scenes/AsyncInventorySender.cs
@@ -143,14 +143,13 @@ namespace OpenSim.Region.Framework.Scenes
143// m_log.DebugFormat( 143// m_log.DebugFormat(
144// "[ASYNC INVENTORY SENDER]: Handling request from {0} for {1} on queue", fh.Client.Name, fh.ItemID); 144// "[ASYNC INVENTORY SENDER]: Handling request from {0} for {1} on queue", fh.Client.Name, fh.ItemID);
145 145
146 InventoryItemBase item = new InventoryItemBase(fh.ItemID, fh.Client.AgentId); 146 InventoryItemBase item = m_scene.InventoryService.GetItem(fh.Client.AgentId, fh.ItemID);
147 item = m_scene.InventoryService.GetItem(item); 147
148
149 if (item != null) 148 if (item != null)
150 fh.Client.SendInventoryItemDetails(item.Owner, item); 149 fh.Client.SendInventoryItemDetails(item.Owner, item);
151 150
152 // TODO: Possibly log any failure 151 // TODO: Possibly log any failure
153 } 152 }
154 } 153 }
155 } 154 }
156} \ No newline at end of file 155}
diff --git a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
index 11a0146..7509686 100644
--- a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
+++ b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
@@ -44,29 +44,29 @@ namespace OpenSim.Region.Framework.Scenes
44 public UUID folderID; 44 public UUID folderID;
45 public bool permissionToDelete; 45 public bool permissionToDelete;
46 } 46 }
47 47
48 /// <summary> 48 /// <summary>
49 /// Asynchronously derez objects. This is used to derez large number of objects to inventory without holding 49 /// Asynchronously derez objects. This is used to derez large number of objects to inventory without holding
50 /// up the main client thread. 50 /// up the main client thread.
51 /// </summary> 51 /// </summary>
52 public class AsyncSceneObjectGroupDeleter 52 public class AsyncSceneObjectGroupDeleter
53 { 53 {
54 private static readonly ILog m_log 54 private static readonly ILog m_log
55 = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 55 = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
56 56
57 /// <value> 57 /// <value>
58 /// Is the deleter currently enabled? 58 /// Is the deleter currently enabled?
59 /// </value> 59 /// </value>
60 public bool Enabled; 60 public bool Enabled;
61 61
62 private Timer m_inventoryTicker = new Timer(2000); 62 private Timer m_inventoryTicker = new Timer(2000);
63 private readonly Queue<DeleteToInventoryHolder> m_inventoryDeletes = new Queue<DeleteToInventoryHolder>(); 63 private readonly Queue<DeleteToInventoryHolder> m_inventoryDeletes = new Queue<DeleteToInventoryHolder>();
64 private Scene m_scene; 64 private Scene m_scene;
65 65
66 public AsyncSceneObjectGroupDeleter(Scene scene) 66 public AsyncSceneObjectGroupDeleter(Scene scene)
67 { 67 {
68 m_scene = scene; 68 m_scene = scene;
69 69
70 m_inventoryTicker.AutoReset = false; 70 m_inventoryTicker.AutoReset = false;
71 m_inventoryTicker.Elapsed += InventoryRunDeleteTimer; 71 m_inventoryTicker.Elapsed += InventoryRunDeleteTimer;
72 } 72 }
@@ -75,7 +75,7 @@ namespace OpenSim.Region.Framework.Scenes
75 /// Delete the given object from the scene 75 /// Delete the given object from the scene
76 /// </summary> 76 /// </summary>
77 public void DeleteToInventory(DeRezAction action, UUID folderID, 77 public void DeleteToInventory(DeRezAction action, UUID folderID,
78 List<SceneObjectGroup> objectGroups, IClientAPI remoteClient, 78 List<SceneObjectGroup> objectGroups, IClientAPI remoteClient,
79 bool permissionToDelete) 79 bool permissionToDelete)
80 { 80 {
81 if (Enabled) 81 if (Enabled)
@@ -97,7 +97,7 @@ namespace OpenSim.Region.Framework.Scenes
97 if (Enabled) 97 if (Enabled)
98 lock (m_inventoryTicker) 98 lock (m_inventoryTicker)
99 m_inventoryTicker.Start(); 99 m_inventoryTicker.Start();
100 100
101 // Visually remove it, even if it isnt really gone yet. This means that if we crash before the object 101 // Visually remove it, even if it isnt really gone yet. This means that if we crash before the object
102 // has gone to inventory, it will reappear in the region again on restart instead of being lost. 102 // has gone to inventory, it will reappear in the region again on restart instead of being lost.
103 // This is not ideal since the object will still be available for manipulation when it should be, but it's 103 // This is not ideal since the object will still be available for manipulation when it should be, but it's
@@ -108,7 +108,7 @@ namespace OpenSim.Region.Framework.Scenes
108 g.DeleteGroupFromScene(false); 108 g.DeleteGroupFromScene(false);
109 } 109 }
110 } 110 }
111 111
112 private void InventoryRunDeleteTimer(object sender, ElapsedEventArgs e) 112 private void InventoryRunDeleteTimer(object sender, ElapsedEventArgs e)
113 { 113 {
114// m_log.Debug("[ASYNC DELETER]: Starting send to inventory loop"); 114// m_log.Debug("[ASYNC DELETER]: Starting send to inventory loop");
@@ -116,8 +116,8 @@ namespace OpenSim.Region.Framework.Scenes
116 // We must set appearance parameters in the en_US culture in order to avoid issues where values are saved 116 // We must set appearance parameters in the en_US culture in order to avoid issues where values are saved
117 // in a culture where decimal points are commas and then reloaded in a culture which just treats them as 117 // in a culture where decimal points are commas and then reloaded in a culture which just treats them as
118 // number seperators. 118 // number seperators.
119 Culture.SetCurrentCulture(); 119 Culture.SetCurrentCulture();
120 120
121 while (InventoryDeQueueAndDelete()) 121 while (InventoryDeQueueAndDelete())
122 { 122 {
123 //m_log.Debug("[ASYNC DELETER]: Sent item successfully to inventory, continuing..."); 123 //m_log.Debug("[ASYNC DELETER]: Sent item successfully to inventory, continuing...");
@@ -131,7 +131,7 @@ namespace OpenSim.Region.Framework.Scenes
131 public bool InventoryDeQueueAndDelete() 131 public bool InventoryDeQueueAndDelete()
132 { 132 {
133 DeleteToInventoryHolder x = null; 133 DeleteToInventoryHolder x = null;
134 134
135 try 135 try
136 { 136 {
137 lock (m_inventoryDeletes) 137 lock (m_inventoryDeletes)
@@ -144,13 +144,13 @@ namespace OpenSim.Region.Framework.Scenes
144// m_log.DebugFormat( 144// m_log.DebugFormat(
145// "[ASYNC DELETER]: Sending object to user's inventory, action {1}, count {2}, {0} item(s) remaining.", 145// "[ASYNC DELETER]: Sending object to user's inventory, action {1}, count {2}, {0} item(s) remaining.",
146// left, x.action, x.objectGroups.Count); 146// left, x.action, x.objectGroups.Count);
147 147
148 try 148 try
149 { 149 {
150 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>(); 150 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>();
151 if (invAccess != null) 151 if (invAccess != null)
152 invAccess.CopyToInventory(x.action, x.folderID, x.objectGroups, x.remoteClient, false); 152 invAccess.CopyToInventory(x.action, x.folderID, x.objectGroups, x.remoteClient, false);
153 153
154 if (x.permissionToDelete) 154 if (x.permissionToDelete)
155 { 155 {
156 foreach (SceneObjectGroup g in x.objectGroups) 156 foreach (SceneObjectGroup g in x.objectGroups)
@@ -162,7 +162,7 @@ namespace OpenSim.Region.Framework.Scenes
162 m_log.ErrorFormat( 162 m_log.ErrorFormat(
163 "[ASYNC DELETER]: Exception background sending object: {0}{1}", e.Message, e.StackTrace); 163 "[ASYNC DELETER]: Exception background sending object: {0}{1}", e.Message, e.StackTrace);
164 } 164 }
165 165
166 return true; 166 return true;
167 } 167 }
168 } 168 }
@@ -173,14 +173,14 @@ namespace OpenSim.Region.Framework.Scenes
173 // FIXME: This needs to be fixed. 173 // FIXME: This needs to be fixed.
174 m_log.ErrorFormat( 174 m_log.ErrorFormat(
175 "[ASYNC DELETER]: Queued sending of scene object to agent {0} {1} failed: {2} {3}", 175 "[ASYNC DELETER]: Queued sending of scene object to agent {0} {1} failed: {2} {3}",
176 (x != null ? x.remoteClient.Name : "unavailable"), 176 (x != null ? x.remoteClient.Name : "unavailable"),
177 (x != null ? x.remoteClient.AgentId.ToString() : "unavailable"), 177 (x != null ? x.remoteClient.AgentId.ToString() : "unavailable"),
178 e.Message, 178 e.Message,
179 e.StackTrace); 179 e.StackTrace);
180 } 180 }
181 181
182// m_log.Debug("[ASYNC DELETER]: No objects left in inventory send queue."); 182// m_log.Debug("[ASYNC DELETER]: No objects left in inventory send queue.");
183 183
184 return false; 184 return false;
185 } 185 }
186 } 186 }
diff --git a/OpenSim/Region/Framework/Scenes/Border.cs b/OpenSim/Region/Framework/Scenes/Border.cs
deleted file mode 100644
index 08c0c31..0000000
--- a/OpenSim/Region/Framework/Scenes/Border.cs
+++ /dev/null
@@ -1,148 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Text;
31using OpenMetaverse;
32
33namespace OpenSim.Region.Framework.Scenes
34{
35 public class Border
36 {
37 /// <summary>
38 /// Line perpendicular to the Direction Cardinal. Z value is the
39 /// </summary>
40 public Vector3 BorderLine = Vector3.Zero;
41
42 /// <summary>
43 /// Direction cardinal of the border, think, 'which side of the region this is'. EX South border: Cardinal.S
44 /// </summary>
45 public Cardinals CrossDirection = Cardinals.N;
46 public uint TriggerRegionX = 0;
47 public uint TriggerRegionY = 0;
48
49 public Border()
50 {
51 }
52
53 /// <summary>
54 /// Creates a Border. The line is perpendicular to the direction cardinal.
55 /// IE: if the direction cardinal is South, the line is West->East
56 /// </summary>
57 /// <param name="lineStart">The starting point for the line of the border.
58 /// The position of an object must be greater then this for this border to trigger.
59 /// Perpendicular to the direction cardinal</param>
60 /// <param name="lineEnd">The ending point for the line of the border.
61 /// The position of an object must be less then this for this border to trigger.
62 /// Perpendicular to the direction cardinal</param>
63 /// <param name="triggerCoordinate">The position that triggers border the border
64 /// cross parallel to the direction cardinal. On the North cardinal, this
65 /// normally 256. On the South cardinal, it's normally 0. Any position past this
66 /// point on the cartesian coordinate will trigger the border cross as long as it
67 /// falls within the line start and the line end.</param>
68 /// <param name="triggerRegionX">When this border triggers, teleport to this regionX
69 /// in the grid</param>
70 /// <param name="triggerRegionY">When this border triggers, teleport to this regionY
71 /// in the grid</param>
72 /// <param name="direction">Cardinal for border direction. Think, 'which side of the
73 /// region is this'</param>
74 public Border(float lineStart, float lineEnd, float triggerCoordinate, uint triggerRegionX,
75 uint triggerRegionY, Cardinals direction)
76 {
77 BorderLine = new Vector3(lineStart,lineEnd,triggerCoordinate);
78 CrossDirection = direction;
79 TriggerRegionX = triggerRegionX;
80 TriggerRegionY = triggerRegionY;
81 }
82
83 /// <summary>
84 /// Tests to see if the given position would cross this border.
85 /// </summary>
86 /// <returns></returns>
87 public bool TestCross(Vector3 position)
88 {
89 bool result = false;
90 switch (CrossDirection)
91 {
92 case Cardinals.N: // x+0, y+1
93 if (position.X >= BorderLine.X && position.X <= BorderLine.Y && position.Y > BorderLine.Z)
94 {
95 return true;
96 }
97 break;
98 case Cardinals.NE: // x+1, y+1
99 break;
100 case Cardinals.E: // x+1, y+0
101 if (position.Y >= BorderLine.X && position.Y <= BorderLine.Y && position.X > BorderLine.Z)
102 {
103 return true;
104 }
105 break;
106 case Cardinals.SE: // x+1, y-1
107 break;
108 case Cardinals.S: // x+0, y-1
109 if (position.X >= BorderLine.X && position.X <= BorderLine.Y && position.Y < BorderLine.Z)
110 {
111 return true;
112 }
113 break;
114 case Cardinals.SW: // x-1, y-1
115 break;
116 case Cardinals.W: // x-1, y+0
117 if (position.Y >= BorderLine.X && position.Y <= BorderLine.Y && position.X < BorderLine.Z)
118 {
119 return true;
120 }
121 break;
122 case Cardinals.NW: // x-1, y+1
123 break;
124 }
125
126 return result;
127 }
128
129 public float Extent
130 {
131 get
132 {
133 switch (CrossDirection)
134 {
135 case Cardinals.N:
136 break;
137 case Cardinals.S:
138 break;
139 case Cardinals.W:
140 break;
141 case Cardinals.E:
142 break;
143 }
144 return 0;
145 }
146 }
147 }
148}
diff --git a/OpenSim/Region/Framework/Scenes/CoalescedSceneObjects.cs b/OpenSim/Region/Framework/Scenes/CoalescedSceneObjects.cs
index af8ccda..8831764 100644
--- a/OpenSim/Region/Framework/Scenes/CoalescedSceneObjects.cs
+++ b/OpenSim/Region/Framework/Scenes/CoalescedSceneObjects.cs
@@ -37,12 +37,12 @@ namespace OpenSim.Region.Framework.Scenes
37 /// are grouped together. 37 /// are grouped together.
38 /// </summary> 38 /// </summary>
39 public class CoalescedSceneObjects 39 public class CoalescedSceneObjects
40 { 40 {
41 /// <summary> 41 /// <summary>
42 /// The creator of this coalesence, though not necessarily the objects within it. 42 /// The creator of this coalesence, though not necessarily the objects within it.
43 /// </summary> 43 /// </summary>
44 public UUID CreatorId { get; set; } 44 public UUID CreatorId { get; set; }
45 45
46 /// <summary> 46 /// <summary>
47 /// The number of objects in this coalesence 47 /// The number of objects in this coalesence
48 /// </summary> 48 /// </summary>
@@ -54,12 +54,12 @@ namespace OpenSim.Region.Framework.Scenes
54 return m_memberObjects.Count; 54 return m_memberObjects.Count;
55 } 55 }
56 } 56 }
57 57
58 /// <summary> 58 /// <summary>
59 /// Does this coalesence have any member objects? 59 /// Does this coalesence have any member objects?
60 /// </summary> 60 /// </summary>
61 public bool HasObjects { get { return Count > 0; } } 61 public bool HasObjects { get { return Count > 0; } }
62 62
63 /// <summary> 63 /// <summary>
64 /// Get the objects currently in this coalescence 64 /// Get the objects currently in this coalescence
65 /// </summary> 65 /// </summary>
@@ -70,13 +70,13 @@ namespace OpenSim.Region.Framework.Scenes
70 lock (m_memberObjects) 70 lock (m_memberObjects)
71 return new List<SceneObjectGroup>(m_memberObjects); 71 return new List<SceneObjectGroup>(m_memberObjects);
72 } 72 }
73 } 73 }
74 74
75 /// <summary> 75 /// <summary>
76 /// Get the scene that contains the objects in this coalescence. If there are no objects then null is returned. 76 /// Get the scene that contains the objects in this coalescence. If there are no objects then null is returned.
77 /// </summary> 77 /// </summary>
78 public Scene Scene 78 public Scene Scene
79 { 79 {
80 get 80 get
81 { 81 {
82 if (!HasObjects) 82 if (!HasObjects)
@@ -85,24 +85,24 @@ namespace OpenSim.Region.Framework.Scenes
85 return Objects[0].Scene; 85 return Objects[0].Scene;
86 } 86 }
87 } 87 }
88 88
89 /// <summary> 89 /// <summary>
90 /// At this point, we need to preserve the order of objects added to the coalescence, since the first 90 /// At this point, we need to preserve the order of objects added to the coalescence, since the first
91 /// one will end up matching the item name when rerezzed. 91 /// one will end up matching the item name when rerezzed.
92 /// </summary> 92 /// </summary>
93 protected List<SceneObjectGroup> m_memberObjects = new List<SceneObjectGroup>(); 93 protected List<SceneObjectGroup> m_memberObjects = new List<SceneObjectGroup>();
94 94
95 public CoalescedSceneObjects(UUID creatorId) 95 public CoalescedSceneObjects(UUID creatorId)
96 { 96 {
97 CreatorId = creatorId; 97 CreatorId = creatorId;
98 } 98 }
99 99
100 public CoalescedSceneObjects(UUID creatorId, params SceneObjectGroup[] objs) : this(creatorId) 100 public CoalescedSceneObjects(UUID creatorId, params SceneObjectGroup[] objs) : this(creatorId)
101 { 101 {
102 foreach (SceneObjectGroup obj in objs) 102 foreach (SceneObjectGroup obj in objs)
103 Add(obj); 103 Add(obj);
104 } 104 }
105 105
106 /// <summary> 106 /// <summary>
107 /// Add an object to the coalescence. 107 /// Add an object to the coalescence.
108 /// </summary> 108 /// </summary>
@@ -113,7 +113,7 @@ namespace OpenSim.Region.Framework.Scenes
113 lock (m_memberObjects) 113 lock (m_memberObjects)
114 m_memberObjects.Add(obj); 114 m_memberObjects.Add(obj);
115 } 115 }
116 116
117 /// <summary> 117 /// <summary>
118 /// Removes a scene object from the coalescene 118 /// Removes a scene object from the coalescene
119 /// </summary> 119 /// </summary>
@@ -124,7 +124,7 @@ namespace OpenSim.Region.Framework.Scenes
124 lock (m_memberObjects) 124 lock (m_memberObjects)
125 return m_memberObjects.Remove(obj); 125 return m_memberObjects.Remove(obj);
126 } 126 }
127 127
128 /// <summary> 128 /// <summary>
129 /// Get the total size of the coalescence (the size required to cover all the objects within it) and the 129 /// Get the total size of the coalescence (the size required to cover all the objects within it) and the
130 /// offsets of each of those objects. 130 /// offsets of each of those objects.
@@ -138,16 +138,16 @@ namespace OpenSim.Region.Framework.Scenes
138 float minX, minY, minZ; 138 float minX, minY, minZ;
139 float maxX, maxY, maxZ; 139 float maxX, maxY, maxZ;
140 140
141 Vector3[] offsets 141 Vector3[] offsets
142 = Scene.GetCombinedBoundingBox( 142 = Scene.GetCombinedBoundingBox(
143 Objects, out minX, out maxX, out minY, out maxY, out minZ, out maxZ); 143 Objects, out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
144 144
145 float sizeX = maxX - minX; 145 float sizeX = maxX - minX;
146 float sizeY = maxY - minY; 146 float sizeY = maxY - minY;
147 float sizeZ = maxZ - minZ; 147 float sizeZ = maxZ - minZ;
148 148
149 size = new Vector3(sizeX, sizeY, sizeZ); 149 size = new Vector3(sizeX, sizeY, sizeZ);
150 150
151 return offsets; 151 return offsets;
152 } 152 }
153 } 153 }
diff --git a/OpenSim/Region/Framework/Scenes/CollisionSounds.cs b/OpenSim/Region/Framework/Scenes/CollisionSounds.cs
new file mode 100644
index 0000000..63aafcd
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/CollisionSounds.cs
@@ -0,0 +1,342 @@
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 (part.CollisionSoundType < 0)
120 return;
121
122 if (collidersinfolist.Count == 0 || part == null)
123 return;
124
125 if (part.VolumeDetectActive || (part.Flags & PrimFlags.Physics) == 0)
126 return;
127
128 SceneObjectGroup sog = part.ParentGroup;
129 if (sog == null || sog.IsDeleted || sog.inTransit)
130 return;
131
132 if(sog.CollisionSoundThrottled(part.CollisionSoundType))
133 return;
134
135 float volume = part.CollisionSoundVolume;
136
137 UUID soundID = part.CollisionSound;
138
139 bool HaveSound = false;
140 switch (part.CollisionSoundType)
141 {
142 case 0: // default sounds
143 volume = 1.0f;
144 break;
145 case 1: // selected sound
146 if(soundID == part.invalidCollisionSoundUUID)
147 return;
148 HaveSound = true;
149 break;
150 case 2: // default sounds with volume set by script
151 default:
152 break;
153 }
154
155 if (volume == 0.0f)
156 return;
157
158 bool doneownsound = false;
159
160 int thisMaterial = (int)part.Material;
161 if (thisMaterial >= MaxMaterials)
162 thisMaterial = 3;
163 int thisMatScaled = thisMaterial * MaxMaterials;
164
165 CollisionForSoundInfo colInfo;
166 uint id;
167
168 for(int i = 0; i < collidersinfolist.Count; i++)
169 {
170 colInfo = collidersinfolist[i];
171
172 id = colInfo.colliderID;
173 if (id == 0) // terrain collision
174 {
175 if (!doneownsound)
176 {
177 if (!HaveSound)
178 {
179 float vol = Math.Abs(colInfo.relativeVel);
180 if (vol < 0.2f)
181 continue;
182
183 vol *= vol * .0625f; // 4m/s == full volume
184 if (vol > 1.0f)
185 vol = 1.0f;
186
187 soundID = m_TerrainPart[thisMaterial];
188 volume *= vol;
189 }
190 part.SendCollisionSound(soundID, volume, colInfo.position);
191 doneownsound = true;
192 }
193 continue;
194 }
195
196 SceneObjectPart otherPart = sog.Scene.GetSceneObjectPart(id);
197 if (otherPart != null)
198 {
199 SceneObjectGroup othersog = otherPart.ParentGroup;
200 if(othersog == null || othersog.IsDeleted || othersog.inTransit)
201 continue;
202
203 int otherType = otherPart.CollisionSoundType;
204 if (otherType < 0 || otherPart.VolumeDetectActive)
205 continue;
206
207 if (!HaveSound)
208 {
209 if(othersog.CollisionSoundThrottled(otherType))
210 continue;
211
212 if (otherType == 1)
213 {
214 soundID = otherPart.CollisionSound;
215 volume = otherPart.CollisionSoundVolume;
216 if (volume == 0.0f)
217 continue;
218 }
219 else
220 {
221 if (otherType == 2)
222 {
223 volume = otherPart.CollisionSoundVolume;
224 if (volume == 0.0f)
225 continue;
226 }
227
228 float vol = Math.Abs(colInfo.relativeVel);
229 if (vol < 0.2f)
230 continue;
231
232 vol *= vol * .0625f; // 4m/s == full volume
233 if (vol > 1.0f)
234 vol = 1.0f;
235
236 int otherMaterial = (int)otherPart.Material;
237 if (otherMaterial >= MaxMaterials)
238 otherMaterial = 3;
239
240 soundID = m_PartPart[thisMatScaled + otherMaterial];
241 volume *= vol;
242 }
243 }
244
245 if (doneownsound)
246 otherPart.SendCollisionSound(soundID, volume, colInfo.position);
247 else
248 {
249 part.SendCollisionSound(soundID, volume, colInfo.position);
250 doneownsound = true;
251 }
252 }
253 }
254 }
255
256 public static void AvatarCollisionSound(ScenePresence av, List<CollisionForSoundInfo> collidersinfolist)
257 {
258 if (collidersinfolist.Count == 0 || av == null)
259 return;
260
261 UUID soundID;
262 int otherMaterial;
263
264 int thisMaterial = 4; // flesh
265
266 int thisMatScaled = thisMaterial * MaxMaterials;
267
268 // bool doneownsound = false;
269
270 CollisionForSoundInfo colInfo;
271 uint id;
272 float volume;
273
274 for(int i = 0; i< collidersinfolist.Count; i++)
275 {
276 colInfo = collidersinfolist[i];
277
278 id = colInfo.colliderID;
279
280 if (id == 0) // no terrain collision sounds for now
281 {
282 continue;
283// volume = Math.Abs(colInfo.relativeVel);
284// if (volume < 0.2f)
285// continue;
286
287 }
288
289 SceneObjectPart otherPart = av.Scene.GetSceneObjectPart(id);
290 if (otherPart != null)
291 {
292 if (otherPart.CollisionSoundType < 0)
293 continue;
294 if (otherPart.CollisionSoundType == 1 && otherPart.CollisionSoundVolume > 0f)
295 otherPart.SendCollisionSound(otherPart.CollisionSound, otherPart.CollisionSoundVolume, colInfo.position);
296 else
297 {
298 float volmod = 1.0f;
299 if (otherPart.CollisionSoundType == 2)
300 {
301 volmod = otherPart.CollisionSoundVolume;
302 if(volmod == 0.0)
303 continue;
304 }
305 volume = Math.Abs(colInfo.relativeVel);
306 // Most noral collisions (running into walls, stairs)
307 // should never be heard.
308 if (volume < 3.2f)
309 continue;
310// m_log.DebugFormat("Collision speed was {0}", volume);
311
312 // Cap to 0.2 times volume because climbing stairs should not be noisy
313 // Also changed scaling
314 volume *= volume * .0125f; // 4m/s == volume 0.2
315 if (volume > 0.2f)
316 volume = 0.2f;
317 otherMaterial = (int)otherPart.Material;
318 if (otherMaterial >= MaxMaterials)
319 otherMaterial = 3;
320
321 volume *= volmod;
322 soundID = m_PartPart[thisMatScaled + otherMaterial];
323 otherPart.SendCollisionSound(soundID, volume, colInfo.position);
324 }
325 continue;
326 }
327/*
328 else if (!doneownsound)
329 {
330 ScenePresence otherav = av.Scene.GetScenePresence(Id);
331 if (otherav != null && (!otherav.IsChildAgent))
332 {
333 soundID = snd_FleshFlesh;
334 av.SendCollisionSound(soundID, 1.0);
335 doneownsound = true;
336 }
337 }
338 */
339 }
340 }
341 }
342}
diff --git a/OpenSim/Region/Framework/Scenes/EntityManager.cs b/OpenSim/Region/Framework/Scenes/EntityManager.cs
index 7181313..4654efe 100644
--- a/OpenSim/Region/Framework/Scenes/EntityManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EntityManager.cs
@@ -38,8 +38,8 @@ namespace OpenSim.Region.Framework.Scenes
38 public class EntityManager 38 public class EntityManager
39 { 39 {
40// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 40// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
41 41
42 private readonly DoubleDictionaryThreadAbortSafe<UUID, uint, EntityBase> m_entities 42 private readonly DoubleDictionaryThreadAbortSafe<UUID, uint, EntityBase> m_entities
43 = new DoubleDictionaryThreadAbortSafe<UUID, uint, EntityBase>(); 43 = new DoubleDictionaryThreadAbortSafe<UUID, uint, EntityBase>();
44 44
45 public int Count 45 public int Count
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index 97b9482..f76f882 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -44,7 +44,7 @@ namespace OpenSim.Region.Framework.Scenes
44 public class EventManager 44 public class EventManager
45 { 45 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 47
48 public delegate void OnFrameDelegate(); 48 public delegate void OnFrameDelegate();
49 49
50 /// <summary> 50 /// <summary>
@@ -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
@@ -115,7 +121,7 @@ namespace OpenSim.Region.Framework.Scenes
115 public event OnClientConnectCoreDelegate OnClientConnect; 121 public event OnClientConnectCoreDelegate OnClientConnect;
116 122
117 public delegate void OnNewClientDelegate(IClientAPI client); 123 public delegate void OnNewClientDelegate(IClientAPI client);
118 124
119 /// <summary> 125 /// <summary>
120 /// Triggered when a new client is added to the scene. 126 /// Triggered when a new client is added to the scene.
121 /// </summary> 127 /// </summary>
@@ -157,7 +163,7 @@ namespace OpenSim.Region.Framework.Scenes
157 /// <remarks> 163 /// <remarks>
158 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewAgent"/> which is used by both 164 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewAgent"/> which is used by both
159 /// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see> 165 /// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see>
160 /// 166 ///
161 /// Triggered under per-agent lock. So if you want to perform any long-running operations, please 167 /// Triggered under per-agent lock. So if you want to perform any long-running operations, please
162 /// do this on a separate thread. 168 /// do this on a separate thread.
163 /// </remarks> 169 /// </remarks>
@@ -217,7 +223,7 @@ namespace OpenSim.Region.Framework.Scenes
217 /// Triggered when the entire simulator is shutdown. 223 /// Triggered when the entire simulator is shutdown.
218 /// </summary> 224 /// </summary>
219 public event Action OnShutdown; 225 public event Action OnShutdown;
220 226
221 public delegate void ObjectDeGrabDelegate(uint localID, uint originalID, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs); 227 public delegate void ObjectDeGrabDelegate(uint localID, uint originalID, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs);
222 public delegate void ScriptResetDelegate(uint localID, UUID itemID); 228 public delegate void ScriptResetDelegate(uint localID, UUID itemID);
223 229
@@ -270,7 +276,7 @@ namespace OpenSim.Region.Framework.Scenes
270 /// </remarks> 276 /// </remarks>
271 public event ObjectGrabDelegate OnObjectGrab; 277 public event ObjectGrabDelegate OnObjectGrab;
272 public delegate void ObjectGrabDelegate(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs); 278 public delegate void ObjectGrabDelegate(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs);
273 279
274 /// <summary> 280 /// <summary>
275 /// Triggered when an object is being touched/grabbed continuously. 281 /// Triggered when an object is being touched/grabbed continuously.
276 /// </summary> 282 /// </summary>
@@ -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
@@ -500,7 +503,7 @@ namespace OpenSim.Region.Framework.Scenes
500 /// via <see cref="OpenSim.Region.ClientStack.Linden.TaskInventoryScriptUpdater.uploaderCaps"/> 503 /// via <see cref="OpenSim.Region.ClientStack.Linden.TaskInventoryScriptUpdater.uploaderCaps"/>
501 /// </remarks> 504 /// </remarks>
502 public event UpdateScript OnUpdateScript; 505 public event UpdateScript OnUpdateScript;
503 506
504 public virtual void TriggerUpdateScript(UUID clientId, UUID itemId, UUID primId, bool isScriptRunning, UUID newAssetID) 507 public virtual void TriggerUpdateScript(UUID clientId, UUID itemId, UUID primId, bool isScriptRunning, UUID newAssetID)
505 { 508 {
506 UpdateScript handlerUpdateScript = OnUpdateScript; 509 UpdateScript handlerUpdateScript = OnUpdateScript;
@@ -520,16 +523,16 @@ namespace OpenSim.Region.Framework.Scenes
520 } 523 }
521 } 524 }
522 } 525 }
523 } 526 }
524 527
525 /// <summary> 528 /// <summary>
526 /// Triggered when some scene object properties change. 529 /// Triggered when some scene object properties change.
527 /// </summary> 530 /// </summary>
528 /// <remarks> 531 /// <remarks>
529 /// ScriptChangedEvent is fired when a scene object property that a script might be interested 532 /// ScriptChangedEvent is fired when a scene object property that a script might be interested
530 /// in (such as color, scale or inventory) changes. Only enough information sent is for the LSL changed event. 533 /// in (such as color, scale or inventory) changes. Only enough information sent is for the LSL changed event.
531 /// This is not an indication that the script has changed (see OnUpdateScript for that). 534 /// This is not an indication that the script has changed (see OnUpdateScript for that).
532 /// This event is sent to a script to tell it that some property changed on 535 /// This event is sent to a script to tell it that some property changed on
533 /// the object the script is in. See http://lslwiki.net/lslwiki/wakka.php?wakka=changed . 536 /// the object the script is in. See http://lslwiki.net/lslwiki/wakka.php?wakka=changed .
534 /// Triggered by <see cref="TriggerOnScriptChangedEvent"/> 537 /// Triggered by <see cref="TriggerOnScriptChangedEvent"/>
535 /// in <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.TeleportAgentWithinRegion"/>, 538 /// in <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.TeleportAgentWithinRegion"/>,
@@ -558,7 +561,7 @@ namespace OpenSim.Region.Framework.Scenes
558 /// TODO: Should be triggered when a physics object starts moving. 561 /// TODO: Should be triggered when a physics object starts moving.
559 /// </summary> 562 /// </summary>
560 public event ScriptMovingStartEvent OnScriptMovingStartEvent; 563 public event ScriptMovingStartEvent OnScriptMovingStartEvent;
561 564
562 public delegate void ScriptMovingEndEvent(uint localID); 565 public delegate void ScriptMovingEndEvent(uint localID);
563 566
564 /// <summary> 567 /// <summary>
@@ -735,7 +738,7 @@ namespace OpenSim.Region.Framework.Scenes
735 /// and <see cref="ScenePresence.CompleteMovement"/> 738 /// and <see cref="ScenePresence.CompleteMovement"/>
736 /// </remarks> 739 /// </remarks>
737 public event Action<ScenePresence> OnMakeRootAgent; 740 public event Action<ScenePresence> OnMakeRootAgent;
738 741
739 public event OnSendNewWindlightProfileTargetedDelegate OnSendNewWindlightProfileTargeted; 742 public event OnSendNewWindlightProfileTargetedDelegate OnSendNewWindlightProfileTargeted;
740 public event OnSaveNewWindlightProfileDelegate OnSaveNewWindlightProfile; 743 public event OnSaveNewWindlightProfileDelegate OnSaveNewWindlightProfile;
741 744
@@ -745,14 +748,14 @@ namespace OpenSim.Region.Framework.Scenes
745 public event OnIncomingSceneObjectDelegate OnIncomingSceneObject; 748 public event OnIncomingSceneObjectDelegate OnIncomingSceneObject;
746 public delegate void OnIncomingSceneObjectDelegate(SceneObjectGroup so); 749 public delegate void OnIncomingSceneObjectDelegate(SceneObjectGroup so);
747 750
748 public delegate void NewInventoryItemUploadComplete(UUID avatarID, AssetType type, UUID assetID, string name, int userlevel); 751 public delegate void NewInventoryItemUploadComplete(InventoryItemBase item, int userlevel);
749 752
750 public event NewInventoryItemUploadComplete OnNewInventoryItemUploadComplete; 753 public event NewInventoryItemUploadComplete OnNewInventoryItemUploadComplete;
751 754
752 public delegate void RequestChangeWaterHeight(float height); 755 public delegate void RequestChangeWaterHeight(float height);
753 756
754 public event RequestChangeWaterHeight OnRequestChangeWaterHeight; 757 public event RequestChangeWaterHeight OnRequestChangeWaterHeight;
755 758
756 /// <summary> 759 /// <summary>
757 /// Fired if any avatar is 'killed' due to its health falling to zero 760 /// Fired if any avatar is 'killed' due to its health falling to zero
758 /// </summary> 761 /// </summary>
@@ -775,7 +778,7 @@ namespace OpenSim.Region.Framework.Scenes
775 public delegate void GetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID); 778 public delegate void GetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID);
776 779
777 public event EstateToolsSunUpdate OnEstateToolsSunUpdate; 780 public event EstateToolsSunUpdate OnEstateToolsSunUpdate;
778 781
779 /// <summary> 782 /// <summary>
780 /// Triggered when an object is added to the scene. 783 /// Triggered when an object is added to the scene.
781 /// </summary> 784 /// </summary>
@@ -786,7 +789,7 @@ namespace OpenSim.Region.Framework.Scenes
786 /// <see cref="Scene.doObjectDuplicateOnRay"/> 789 /// <see cref="Scene.doObjectDuplicateOnRay"/>
787 /// </remarks> 790 /// </remarks>
788 public event Action<SceneObjectGroup> OnObjectAddedToScene; 791 public event Action<SceneObjectGroup> OnObjectAddedToScene;
789 792
790 /// <summary> 793 /// <summary>
791 /// When a client sends a derez request for an object inworld 794 /// When a client sends a derez request for an object inworld
792 /// but before the object is deleted 795 /// but before the object is deleted
@@ -852,12 +855,16 @@ namespace OpenSim.Region.Framework.Scenes
852 /// <see cref="Scene.DeleteSceneObject"/>, 855 /// <see cref="Scene.DeleteSceneObject"/>,
853 /// <see cref="Scene.SelectPrim"/>, 856 /// <see cref="Scene.SelectPrim"/>,
854 /// <see cref="Scene.DeselectPrim"/>, 857 /// <see cref="Scene.DeselectPrim"/>,
855 /// <see cref="SceneObjectGroup.UpdatePrimFlags"/>, 858 /// <see cref="SceneObjectGroup.UpdateFlags"/>,
856 /// <see cref="SceneObjectGroup.AbsolutePosition"/> 859 /// <see cref="SceneObjectGroup.AbsolutePosition"/>
857 /// </remarks> 860 /// </remarks>
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
@@ -865,21 +872,21 @@ namespace OpenSim.Region.Framework.Scenes
865 /// </summary> 872 /// </summary>
866 public delegate void RegisterCapsEvent(UUID agentID, Caps caps); 873 public delegate void RegisterCapsEvent(UUID agentID, Caps caps);
867 public event RegisterCapsEvent OnRegisterCaps; 874 public event RegisterCapsEvent OnRegisterCaps;
868 875
869 /// <summary> 876 /// <summary>
870 /// DeregisterCapsEvent is called by Scene when the caps 877 /// DeregisterCapsEvent is called by Scene when the caps
871 /// handler for an agent are removed. 878 /// handler for an agent are removed.
872 /// </summary> 879 /// </summary>
873 public delegate void DeregisterCapsEvent(UUID agentID, Caps caps); 880 public delegate void DeregisterCapsEvent(UUID agentID, Caps caps);
874 public event DeregisterCapsEvent OnDeregisterCaps; 881 public event DeregisterCapsEvent OnDeregisterCaps;
875 882
876 /// <summary> 883 /// <summary>
877 /// ChatFromWorldEvent is called via Scene when a chat message 884 /// ChatFromWorldEvent is called via Scene when a chat message
878 /// from world comes in. 885 /// from world comes in.
879 /// </summary> 886 /// </summary>
880 public delegate void ChatFromWorldEvent(Object sender, OSChatMessage chat); 887 public delegate void ChatFromWorldEvent(Object sender, OSChatMessage chat);
881 public event ChatFromWorldEvent OnChatFromWorld; 888 public event ChatFromWorldEvent OnChatFromWorld;
882 889
883 /// <summary> 890 /// <summary>
884 /// ChatFromClientEvent is triggered via ChatModule (or 891 /// ChatFromClientEvent is triggered via ChatModule (or
885 /// substitutes thereof) when a chat message 892 /// substitutes thereof) when a chat message
@@ -887,18 +894,18 @@ namespace OpenSim.Region.Framework.Scenes
887 /// </summary> 894 /// </summary>
888 public delegate void ChatFromClientEvent(Object sender, OSChatMessage chat); 895 public delegate void ChatFromClientEvent(Object sender, OSChatMessage chat);
889 public event ChatFromClientEvent OnChatFromClient; 896 public event ChatFromClientEvent OnChatFromClient;
890 897
891 /// <summary> 898 /// <summary>
892 /// ChatToClientsEvent is triggered via ChatModule (or 899 /// ChatToClientsEvent is triggered via ChatModule (or
893 /// substitutes thereof) when a chat message is actually sent to clients. Clients will only be sent a 900 /// substitutes thereof) when a chat message is actually sent to clients. Clients will only be sent a
894 /// received chat message if they satisfy various conditions (within audible range, etc.) 901 /// received chat message if they satisfy various conditions (within audible range, etc.)
895 /// </summary> 902 /// </summary>
896 public delegate void ChatToClientsEvent( 903 public delegate void ChatToClientsEvent(
897 UUID senderID, HashSet<UUID> receiverIDs, 904 UUID senderID, HashSet<UUID> receiverIDs,
898 string message, ChatTypeEnum type, Vector3 fromPos, string fromName, 905 string message, ChatTypeEnum type, Vector3 fromPos, string fromName,
899 ChatSourceType src, ChatAudibleLevel level); 906 ChatSourceType src, ChatAudibleLevel level);
900 public event ChatToClientsEvent OnChatToClients; 907 public event ChatToClientsEvent OnChatToClients;
901 908
902 /// <summary> 909 /// <summary>
903 /// ChatBroadcastEvent is called via Scene when a broadcast chat message 910 /// ChatBroadcastEvent is called via Scene when a broadcast chat message
904 /// from world comes in 911 /// from world comes in
@@ -916,11 +923,11 @@ namespace OpenSim.Region.Framework.Scenes
916 /// </summary> 923 /// </summary>
917 public delegate void OarFileLoaded(Guid guid, List<UUID> loadedScenes, string message); 924 public delegate void OarFileLoaded(Guid guid, List<UUID> loadedScenes, string message);
918 public event OarFileLoaded OnOarFileLoaded; 925 public event OarFileLoaded OnOarFileLoaded;
919 926
920 /// <summary> 927 /// <summary>
921 /// Called when an oar file has finished saving 928 /// Called when an oar file has finished saving
922 /// Message is non empty string if there were problems saving the oar file 929 /// Message is non empty string if there were problems saving the oar file
923 /// If a guid was supplied on the original call to identify, the request, this is returned. Otherwise 930 /// If a guid was supplied on the original call to identify, the request, this is returned. Otherwise
924 /// Guid.Empty is returned. 931 /// Guid.Empty is returned.
925 /// </summary> 932 /// </summary>
926 public delegate void OarFileSaved(Guid guid, string message); 933 public delegate void OarFileSaved(Guid guid, string message);
@@ -940,14 +947,14 @@ namespace OpenSim.Region.Framework.Scenes
940 /// the avatarID is UUID.Zero (I know, this doesn't make much sense but now it's historical). 947 /// the avatarID is UUID.Zero (I know, this doesn't make much sense but now it's historical).
941 public delegate void Attach(uint localID, UUID itemID, UUID avatarID); 948 public delegate void Attach(uint localID, UUID itemID, UUID avatarID);
942 public event Attach OnAttach; 949 public event Attach OnAttach;
943 950
944 951
945 /// <summary> 952 /// <summary>
946 /// Called immediately after an object is loaded from storage. 953 /// Called immediately after an object is loaded from storage.
947 /// </summary> 954 /// </summary>
948 public event SceneObjectDelegate OnSceneObjectLoaded; 955 public event SceneObjectDelegate OnSceneObjectLoaded;
949 public delegate void SceneObjectDelegate(SceneObjectGroup so); 956 public delegate void SceneObjectDelegate(SceneObjectGroup so);
950 957
951 /// <summary> 958 /// <summary>
952 /// Called immediately before an object is saved to storage. 959 /// Called immediately before an object is saved to storage.
953 /// </summary> 960 /// </summary>
@@ -960,7 +967,7 @@ namespace OpenSim.Region.Framework.Scenes
960 /// </param> 967 /// </param>
961 public event SceneObjectPreSaveDelegate OnSceneObjectPreSave; 968 public event SceneObjectPreSaveDelegate OnSceneObjectPreSave;
962 public delegate void SceneObjectPreSaveDelegate(SceneObjectGroup persistingSo, SceneObjectGroup originalSo); 969 public delegate void SceneObjectPreSaveDelegate(SceneObjectGroup persistingSo, SceneObjectGroup originalSo);
963 970
964 /// <summary> 971 /// <summary>
965 /// Called when a scene object part is cloned within the region. 972 /// Called when a scene object part is cloned within the region.
966 /// </summary> 973 /// </summary>
@@ -994,7 +1001,7 @@ namespace OpenSim.Region.Framework.Scenes
994 /// Fired when logins to a region are enabled or disabled. 1001 /// Fired when logins to a region are enabled or disabled.
995 /// </summary> 1002 /// </summary>
996 /// <remarks> 1003 /// <remarks>
997 /// 1004 ///
998 /// </remarks> 1005 /// </remarks>
999 /// Fired 1006 /// Fired
1000 public event RegionLoginsStatusChange OnRegionLoginsStatusChange; 1007 public event RegionLoginsStatusChange OnRegionLoginsStatusChange;
@@ -1150,7 +1157,7 @@ namespace OpenSim.Region.Framework.Scenes
1150 catch (Exception e) 1157 catch (Exception e)
1151 { 1158 {
1152 m_log.ErrorFormat( 1159 m_log.ErrorFormat(
1153 "[EVENT MANAGER]: Delegate for TriggerOnAttach failed - continuing. {0} {1}", 1160 "[EVENT MANAGER]: Delegate for TriggerOnAttach failed - continuing. {0} {1}",
1154 e.Message, e.StackTrace); 1161 e.Message, e.StackTrace);
1155 } 1162 }
1156 } 1163 }
@@ -1171,7 +1178,7 @@ namespace OpenSim.Region.Framework.Scenes
1171 catch (Exception e) 1178 catch (Exception e)
1172 { 1179 {
1173 m_log.ErrorFormat( 1180 m_log.ErrorFormat(
1174 "[EVENT MANAGER]: Delegate for TriggerGetScriptRunning failed - continuing. {0} {1}", 1181 "[EVENT MANAGER]: Delegate for TriggerGetScriptRunning failed - continuing. {0} {1}",
1175 e.Message, e.StackTrace); 1182 e.Message, e.StackTrace);
1176 } 1183 }
1177 } 1184 }
@@ -1192,7 +1199,7 @@ namespace OpenSim.Region.Framework.Scenes
1192 catch (Exception e) 1199 catch (Exception e)
1193 { 1200 {
1194 m_log.ErrorFormat( 1201 m_log.ErrorFormat(
1195 "[EVENT MANAGER]: Delegate for TriggerOnScriptChangedEvent failed - continuing. {0} {1}", 1202 "[EVENT MANAGER]: Delegate for TriggerOnScriptChangedEvent failed - continuing. {0} {1}",
1196 e.Message, e.StackTrace); 1203 e.Message, e.StackTrace);
1197 } 1204 }
1198 } 1205 }
@@ -1213,7 +1220,7 @@ namespace OpenSim.Region.Framework.Scenes
1213 catch (Exception e) 1220 catch (Exception e)
1214 { 1221 {
1215 m_log.ErrorFormat( 1222 m_log.ErrorFormat(
1216 "[EVENT MANAGER]: Delegate for TriggerOnClientMovement failed - continuing. {0} {1}", 1223 "[EVENT MANAGER]: Delegate for TriggerOnClientMovement failed - continuing. {0} {1}",
1217 e.Message, e.StackTrace); 1224 e.Message, e.StackTrace);
1218 } 1225 }
1219 } 1226 }
@@ -1234,7 +1241,7 @@ namespace OpenSim.Region.Framework.Scenes
1234 catch (Exception e) 1241 catch (Exception e)
1235 { 1242 {
1236 m_log.ErrorFormat( 1243 m_log.ErrorFormat(
1237 "[EVENT MANAGER]: Delegate for TriggerPermissionError failed - continuing. {0} {1}", 1244 "[EVENT MANAGER]: Delegate for TriggerPermissionError failed - continuing. {0} {1}",
1238 e.Message, e.StackTrace); 1245 e.Message, e.StackTrace);
1239 } 1246 }
1240 } 1247 }
@@ -1255,7 +1262,7 @@ namespace OpenSim.Region.Framework.Scenes
1255 catch (Exception e) 1262 catch (Exception e)
1256 { 1263 {
1257 m_log.ErrorFormat( 1264 m_log.ErrorFormat(
1258 "[EVENT MANAGER]: Delegate for TriggerOnPluginConsole failed - continuing. {0} {1}", 1265 "[EVENT MANAGER]: Delegate for TriggerOnPluginConsole failed - continuing. {0} {1}",
1259 e.Message, e.StackTrace); 1266 e.Message, e.StackTrace);
1260 } 1267 }
1261 } 1268 }
@@ -1276,7 +1283,7 @@ namespace OpenSim.Region.Framework.Scenes
1276 catch (Exception e) 1283 catch (Exception e)
1277 { 1284 {
1278 m_log.ErrorFormat( 1285 m_log.ErrorFormat(
1279 "[EVENT MANAGER]: Delegate for TriggerOnFrame failed - continuing. {0} {1}", 1286 "[EVENT MANAGER]: Delegate for TriggerOnFrame failed - continuing. {0} {1}",
1280 e.Message, e.StackTrace); 1287 e.Message, e.StackTrace);
1281 } 1288 }
1282 } 1289 }
@@ -1297,7 +1304,7 @@ namespace OpenSim.Region.Framework.Scenes
1297 catch (Exception e) 1304 catch (Exception e)
1298 { 1305 {
1299 m_log.ErrorFormat( 1306 m_log.ErrorFormat(
1300 "[EVENT MANAGER]: Delegate for TriggerOnNewClient failed - continuing. {0} {1}", 1307 "[EVENT MANAGER]: Delegate for TriggerOnNewClient failed - continuing. {0} {1}",
1301 e.Message, e.StackTrace); 1308 e.Message, e.StackTrace);
1302 } 1309 }
1303 } 1310 }
@@ -1317,7 +1324,7 @@ namespace OpenSim.Region.Framework.Scenes
1317 catch (Exception e) 1324 catch (Exception e)
1318 { 1325 {
1319 m_log.ErrorFormat( 1326 m_log.ErrorFormat(
1320 "[EVENT MANAGER]: Delegate for TriggerOnNewClient (IClientCore) failed - continuing. {0} {1}", 1327 "[EVENT MANAGER]: Delegate for TriggerOnNewClient (IClientCore) failed - continuing. {0} {1}",
1321 e.Message, e.StackTrace); 1328 e.Message, e.StackTrace);
1322 } 1329 }
1323 } 1330 }
@@ -1361,7 +1368,7 @@ namespace OpenSim.Region.Framework.Scenes
1361 catch (Exception e) 1368 catch (Exception e)
1362 { 1369 {
1363 m_log.ErrorFormat( 1370 m_log.ErrorFormat(
1364 "[EVENT MANAGER]: Delegate for TriggerOnNewPresence failed - continuing. {0} {1}", 1371 "[EVENT MANAGER]: Delegate for TriggerOnNewPresence failed - continuing. {0} {1}",
1365 e.Message, e.StackTrace); 1372 e.Message, e.StackTrace);
1366 } 1373 }
1367 } 1374 }
@@ -1377,12 +1384,14 @@ 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 {
1384 m_log.ErrorFormat( 1393 m_log.ErrorFormat(
1385 "[EVENT MANAGER]: Delegate for TriggerOnRemovePresence failed - continuing. {0} {1}", 1394 "[EVENT MANAGER]: Delegate for TriggerOnRemovePresence failed - continuing. {0} {1}",
1386 e.Message, e.StackTrace); 1395 e.Message, e.StackTrace);
1387 } 1396 }
1388 } 1397 }
@@ -1403,7 +1412,7 @@ namespace OpenSim.Region.Framework.Scenes
1403 catch (Exception e) 1412 catch (Exception e)
1404 { 1413 {
1405 m_log.ErrorFormat( 1414 m_log.ErrorFormat(
1406 "[EVENT MANAGER]: Delegate for TriggerOnBackup failed - continuing. {0} {1}", 1415 "[EVENT MANAGER]: Delegate for TriggerOnBackup failed - continuing. {0} {1}",
1407 e.Message, e.StackTrace); 1416 e.Message, e.StackTrace);
1408 } 1417 }
1409 } 1418 }
@@ -1424,7 +1433,7 @@ namespace OpenSim.Region.Framework.Scenes
1424 catch (Exception e) 1433 catch (Exception e)
1425 { 1434 {
1426 m_log.ErrorFormat( 1435 m_log.ErrorFormat(
1427 "[EVENT MANAGER]: Delegate for TriggerParcelPrimCountUpdate failed - continuing. {0} {1}", 1436 "[EVENT MANAGER]: Delegate for TriggerParcelPrimCountUpdate failed - continuing. {0} {1}",
1428 e.Message, e.StackTrace); 1437 e.Message, e.StackTrace);
1429 } 1438 }
1430 } 1439 }
@@ -1445,7 +1454,27 @@ namespace OpenSim.Region.Framework.Scenes
1445 catch (Exception e) 1454 catch (Exception e)
1446 { 1455 {
1447 m_log.ErrorFormat( 1456 m_log.ErrorFormat(
1448 "[EVENT MANAGER]: Delegate for TriggerMoneyTransfer failed - continuing. {0} {1}", 1457 "[EVENT MANAGER]: Delegate for TriggerMoneyTransfer failed - continuing. {0} {1}",
1458 e.Message, e.StackTrace);
1459 }
1460 }
1461 }
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}",
1449 e.Message, e.StackTrace); 1478 e.Message, e.StackTrace);
1450 } 1479 }
1451 } 1480 }
@@ -1466,7 +1495,28 @@ namespace OpenSim.Region.Framework.Scenes
1466 catch (Exception e) 1495 catch (Exception e)
1467 { 1496 {
1468 m_log.ErrorFormat( 1497 m_log.ErrorFormat(
1469 "[EVENT MANAGER]: Delegate for TriggerTerrainTick failed - continuing. {0} {1}", 1498 "[EVENT MANAGER]: Delegate for TriggerTerrainTick failed - continuing. {0} {1}",
1499 e.Message, e.StackTrace);
1500 }
1501 }
1502 }
1503 }
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}",
1470 e.Message, e.StackTrace); 1520 e.Message, e.StackTrace);
1471 } 1521 }
1472 } 1522 }
@@ -1508,7 +1558,7 @@ namespace OpenSim.Region.Framework.Scenes
1508 catch (Exception e) 1558 catch (Exception e)
1509 { 1559 {
1510 m_log.ErrorFormat( 1560 m_log.ErrorFormat(
1511 "[EVENT MANAGER]: Delegate for TriggerParcelPrimCountAdd failed - continuing. {0} {1}", 1561 "[EVENT MANAGER]: Delegate for TriggerParcelPrimCountAdd failed - continuing. {0} {1}",
1512 e.Message, e.StackTrace); 1562 e.Message, e.StackTrace);
1513 } 1563 }
1514 } 1564 }
@@ -1529,7 +1579,7 @@ namespace OpenSim.Region.Framework.Scenes
1529 catch (Exception e) 1579 catch (Exception e)
1530 { 1580 {
1531 m_log.ErrorFormat( 1581 m_log.ErrorFormat(
1532 "[EVENT MANAGER]: Delegate for TriggerObjectAddedToScene failed - continuing. {0} {1}", 1582 "[EVENT MANAGER]: Delegate for TriggerObjectAddedToScene failed - continuing. {0} {1}",
1533 e.Message, e.StackTrace); 1583 e.Message, e.StackTrace);
1534 } 1584 }
1535 } 1585 }
@@ -1575,7 +1625,7 @@ namespace OpenSim.Region.Framework.Scenes
1575 catch (Exception e) 1625 catch (Exception e)
1576 { 1626 {
1577 m_log.ErrorFormat( 1627 m_log.ErrorFormat(
1578 "[EVENT MANAGER]: Delegate for TriggerObjectBeingRemovedFromScene failed - continuing. {0} {1}", 1628 "[EVENT MANAGER]: Delegate for TriggerObjectBeingRemovedFromScene failed - continuing. {0} {1}",
1579 e.Message, e.StackTrace); 1629 e.Message, e.StackTrace);
1580 } 1630 }
1581 } 1631 }
@@ -1596,7 +1646,7 @@ namespace OpenSim.Region.Framework.Scenes
1596 catch (Exception e) 1646 catch (Exception e)
1597 { 1647 {
1598 m_log.ErrorFormat( 1648 m_log.ErrorFormat(
1599 "[EVENT MANAGER]: Delegate for TriggerObjectAddedToPhysicalScene failed - continuing. {0} {1}", 1649 "[EVENT MANAGER]: Delegate for TriggerObjectAddedToPhysicalScene failed - continuing. {0} {1}",
1600 e.Message, e.StackTrace); 1650 e.Message, e.StackTrace);
1601 } 1651 }
1602 } 1652 }
@@ -1617,7 +1667,7 @@ namespace OpenSim.Region.Framework.Scenes
1617 catch (Exception e) 1667 catch (Exception e)
1618 { 1668 {
1619 m_log.ErrorFormat( 1669 m_log.ErrorFormat(
1620 "[EVENT MANAGER]: Delegate for TriggerObjectRemovedFromPhysicalScene failed - continuing. {0} {1}", 1670 "[EVENT MANAGER]: Delegate for TriggerObjectRemovedFromPhysicalScene failed - continuing. {0} {1}",
1621 e.Message, e.StackTrace); 1671 e.Message, e.StackTrace);
1622 } 1672 }
1623 } 1673 }
@@ -1638,7 +1688,7 @@ namespace OpenSim.Region.Framework.Scenes
1638 catch (Exception e) 1688 catch (Exception e)
1639 { 1689 {
1640 m_log.ErrorFormat( 1690 m_log.ErrorFormat(
1641 "[EVENT MANAGER]: Delegate for TriggerShutdown failed - continuing. {0} {1}", 1691 "[EVENT MANAGER]: Delegate for TriggerShutdown failed - continuing. {0} {1}",
1642 e.Message, e.StackTrace); 1692 e.Message, e.StackTrace);
1643 } 1693 }
1644 } 1694 }
@@ -1659,7 +1709,7 @@ namespace OpenSim.Region.Framework.Scenes
1659 catch (Exception e) 1709 catch (Exception e)
1660 { 1710 {
1661 m_log.ErrorFormat( 1711 m_log.ErrorFormat(
1662 "[EVENT MANAGER]: Delegate for TriggerObjectGrab failed - continuing. {0} {1}", 1712 "[EVENT MANAGER]: Delegate for TriggerObjectGrab failed - continuing. {0} {1}",
1663 e.Message, e.StackTrace); 1713 e.Message, e.StackTrace);
1664 } 1714 }
1665 } 1715 }
@@ -1680,7 +1730,7 @@ namespace OpenSim.Region.Framework.Scenes
1680 catch (Exception e) 1730 catch (Exception e)
1681 { 1731 {
1682 m_log.ErrorFormat( 1732 m_log.ErrorFormat(
1683 "[EVENT MANAGER]: Delegate for TriggerObjectGrabbing failed - continuing. {0} {1}", 1733 "[EVENT MANAGER]: Delegate for TriggerObjectGrabbing failed - continuing. {0} {1}",
1684 e.Message, e.StackTrace); 1734 e.Message, e.StackTrace);
1685 } 1735 }
1686 } 1736 }
@@ -1701,7 +1751,7 @@ namespace OpenSim.Region.Framework.Scenes
1701 catch (Exception e) 1751 catch (Exception e)
1702 { 1752 {
1703 m_log.ErrorFormat( 1753 m_log.ErrorFormat(
1704 "[EVENT MANAGER]: Delegate for TriggerObjectDeGrab failed - continuing. {0} {1}", 1754 "[EVENT MANAGER]: Delegate for TriggerObjectDeGrab failed - continuing. {0} {1}",
1705 e.Message, e.StackTrace); 1755 e.Message, e.StackTrace);
1706 } 1756 }
1707 } 1757 }
@@ -1722,7 +1772,7 @@ namespace OpenSim.Region.Framework.Scenes
1722 catch (Exception e) 1772 catch (Exception e)
1723 { 1773 {
1724 m_log.ErrorFormat( 1774 m_log.ErrorFormat(
1725 "[EVENT MANAGER]: Delegate for TriggerScriptReset failed - continuing. {0} {1}", 1775 "[EVENT MANAGER]: Delegate for TriggerScriptReset failed - continuing. {0} {1}",
1726 e.Message, e.StackTrace); 1776 e.Message, e.StackTrace);
1727 } 1777 }
1728 } 1778 }
@@ -1743,7 +1793,7 @@ namespace OpenSim.Region.Framework.Scenes
1743 catch (Exception e) 1793 catch (Exception e)
1744 { 1794 {
1745 m_log.ErrorFormat( 1795 m_log.ErrorFormat(
1746 "[EVENT MANAGER]: Delegate for TriggerRezScript failed - continuing. {0} {1}", 1796 "[EVENT MANAGER]: Delegate for TriggerRezScript failed - continuing. {0} {1}",
1747 e.Message, e.StackTrace); 1797 e.Message, e.StackTrace);
1748 } 1798 }
1749 } 1799 }
@@ -1764,7 +1814,7 @@ namespace OpenSim.Region.Framework.Scenes
1764 catch (Exception e) 1814 catch (Exception e)
1765 { 1815 {
1766 m_log.ErrorFormat( 1816 m_log.ErrorFormat(
1767 "[EVENT MANAGER]: Delegate for TriggerStartScript failed - continuing. {0} {1}", 1817 "[EVENT MANAGER]: Delegate for TriggerStartScript failed - continuing. {0} {1}",
1768 e.Message, e.StackTrace); 1818 e.Message, e.StackTrace);
1769 } 1819 }
1770 } 1820 }
@@ -1785,7 +1835,7 @@ namespace OpenSim.Region.Framework.Scenes
1785 catch (Exception e) 1835 catch (Exception e)
1786 { 1836 {
1787 m_log.ErrorFormat( 1837 m_log.ErrorFormat(
1788 "[EVENT MANAGER]: Delegate for TriggerStopScript failed - continuing. {0} {1}", 1838 "[EVENT MANAGER]: Delegate for TriggerStopScript failed - continuing. {0} {1}",
1789 e.Message, e.StackTrace); 1839 e.Message, e.StackTrace);
1790 } 1840 }
1791 } 1841 }
@@ -1806,8 +1856,9 @@ namespace OpenSim.Region.Framework.Scenes
1806 catch (Exception e) 1856 catch (Exception e)
1807 { 1857 {
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 }
@@ -1816,7 +1867,7 @@ namespace OpenSim.Region.Framework.Scenes
1816 public bool TriggerGroupMove(UUID groupID, Vector3 delta) 1867 public bool TriggerGroupMove(UUID groupID, Vector3 delta)
1817 { 1868 {
1818 bool result = true; 1869 bool result = true;
1819 1870
1820 SceneGroupMoved handlerSceneGroupMove = OnSceneGroupMove; 1871 SceneGroupMoved handlerSceneGroupMove = OnSceneGroupMove;
1821 if (handlerSceneGroupMove != null) 1872 if (handlerSceneGroupMove != null)
1822 { 1873 {
@@ -1830,19 +1881,19 @@ namespace OpenSim.Region.Framework.Scenes
1830 catch (Exception e) 1881 catch (Exception e)
1831 { 1882 {
1832 m_log.ErrorFormat( 1883 m_log.ErrorFormat(
1833 "[EVENT MANAGER]: Delegate for TriggerOnAttach failed - continuing. {0} {1}", 1884 "[EVENT MANAGER]: Delegate for TriggerGroupMove failed - continuing. {0} {1}",
1834 e.Message, e.StackTrace); 1885 e.Message, e.StackTrace);
1835 } 1886 }
1836 } 1887 }
1837 } 1888 }
1838 1889
1839 return result; 1890 return result;
1840 } 1891 }
1841 1892
1842 public bool TriggerGroupSpinStart(UUID groupID) 1893 public bool TriggerGroupSpinStart(UUID groupID)
1843 { 1894 {
1844 bool result = true; 1895 bool result = true;
1845 1896
1846 SceneGroupSpinStarted handlerSceneGroupSpinStarted = OnSceneGroupSpinStart; 1897 SceneGroupSpinStarted handlerSceneGroupSpinStarted = OnSceneGroupSpinStart;
1847 if (handlerSceneGroupSpinStarted != null) 1898 if (handlerSceneGroupSpinStarted != null)
1848 { 1899 {
@@ -1856,19 +1907,19 @@ namespace OpenSim.Region.Framework.Scenes
1856 catch (Exception e) 1907 catch (Exception e)
1857 { 1908 {
1858 m_log.ErrorFormat( 1909 m_log.ErrorFormat(
1859 "[EVENT MANAGER]: Delegate for TriggerGroupSpinStart failed - continuing. {0} {1}", 1910 "[EVENT MANAGER]: Delegate for TriggerGroupSpinStart failed - continuing. {0} {1}",
1860 e.Message, e.StackTrace); 1911 e.Message, e.StackTrace);
1861 } 1912 }
1862 } 1913 }
1863 } 1914 }
1864 1915
1865 return result; 1916 return result;
1866 } 1917 }
1867 1918
1868 public bool TriggerGroupSpin(UUID groupID, Quaternion rotation) 1919 public bool TriggerGroupSpin(UUID groupID, Quaternion rotation)
1869 { 1920 {
1870 bool result = true; 1921 bool result = true;
1871 1922
1872 SceneGroupSpun handlerSceneGroupSpin = OnSceneGroupSpin; 1923 SceneGroupSpun handlerSceneGroupSpin = OnSceneGroupSpin;
1873 if (handlerSceneGroupSpin != null) 1924 if (handlerSceneGroupSpin != null)
1874 { 1925 {
@@ -1882,12 +1933,12 @@ namespace OpenSim.Region.Framework.Scenes
1882 catch (Exception e) 1933 catch (Exception e)
1883 { 1934 {
1884 m_log.ErrorFormat( 1935 m_log.ErrorFormat(
1885 "[EVENT MANAGER]: Delegate for TriggerGroupSpin failed - continuing. {0} {1}", 1936 "[EVENT MANAGER]: Delegate for TriggerGroupSpin failed - continuing. {0} {1}",
1886 e.Message, e.StackTrace); 1937 e.Message, e.StackTrace);
1887 } 1938 }
1888 } 1939 }
1889 } 1940 }
1890 1941
1891 return result; 1942 return result;
1892 } 1943 }
1893 1944
@@ -1905,7 +1956,7 @@ namespace OpenSim.Region.Framework.Scenes
1905 catch (Exception e) 1956 catch (Exception e)
1906 { 1957 {
1907 m_log.ErrorFormat( 1958 m_log.ErrorFormat(
1908 "[EVENT MANAGER]: Delegate for TriggerGroupGrab failed - continuing. {0} {1}", 1959 "[EVENT MANAGER]: Delegate for TriggerGroupGrab failed - continuing. {0} {1}",
1909 e.Message, e.StackTrace); 1960 e.Message, e.StackTrace);
1910 } 1961 }
1911 } 1962 }
@@ -1926,7 +1977,7 @@ namespace OpenSim.Region.Framework.Scenes
1926 catch (Exception e) 1977 catch (Exception e)
1927 { 1978 {
1928 m_log.ErrorFormat( 1979 m_log.ErrorFormat(
1929 "[EVENT MANAGER]: Delegate for TriggerLandObjectAdded failed - continuing. {0} {1}", 1980 "[EVENT MANAGER]: Delegate for TriggerLandObjectAdded failed - continuing. {0} {1}",
1930 e.Message, e.StackTrace); 1981 e.Message, e.StackTrace);
1931 } 1982 }
1932 } 1983 }
@@ -1947,7 +1998,7 @@ namespace OpenSim.Region.Framework.Scenes
1947 catch (Exception e) 1998 catch (Exception e)
1948 { 1999 {
1949 m_log.ErrorFormat( 2000 m_log.ErrorFormat(
1950 "[EVENT MANAGER]: Delegate for TriggerLandObjectRemoved failed - continuing. {0} {1}", 2001 "[EVENT MANAGER]: Delegate for TriggerLandObjectRemoved failed - continuing. {0} {1}",
1951 e.Message, e.StackTrace); 2002 e.Message, e.StackTrace);
1952 } 2003 }
1953 } 2004 }
@@ -1973,7 +2024,7 @@ namespace OpenSim.Region.Framework.Scenes
1973 catch (Exception e) 2024 catch (Exception e)
1974 { 2025 {
1975 m_log.ErrorFormat( 2026 m_log.ErrorFormat(
1976 "[EVENT MANAGER]: Delegate for TriggerAvatarEnteringNewParcel failed - continuing. {0} {1}", 2027 "[EVENT MANAGER]: Delegate for TriggerAvatarEnteringNewParcel failed - continuing. {0} {1}",
1977 e.Message, e.StackTrace); 2028 e.Message, e.StackTrace);
1978 } 2029 }
1979 } 2030 }
@@ -1994,7 +2045,7 @@ namespace OpenSim.Region.Framework.Scenes
1994 catch (Exception e) 2045 catch (Exception e)
1995 { 2046 {
1996 m_log.ErrorFormat( 2047 m_log.ErrorFormat(
1997 "[EVENT MANAGER]: Delegate for TriggerAvatarAppearanceChanged failed - continuing. {0} {1}", 2048 "[EVENT MANAGER]: Delegate for TriggerAvatarAppearanceChanged failed - continuing. {0} {1}",
1998 e.Message, e.StackTrace); 2049 e.Message, e.StackTrace);
1999 } 2050 }
2000 } 2051 }
@@ -2036,7 +2087,7 @@ namespace OpenSim.Region.Framework.Scenes
2036 catch (Exception e) 2087 catch (Exception e)
2037 { 2088 {
2038 m_log.ErrorFormat( 2089 m_log.ErrorFormat(
2039 "[EVENT MANAGER]: Delegate for TriggerIncomingInstantMessage failed - continuing. {0} {1}", 2090 "[EVENT MANAGER]: Delegate for TriggerIncomingInstantMessage failed - continuing. {0} {1}",
2040 e.Message, e.StackTrace); 2091 e.Message, e.StackTrace);
2041 } 2092 }
2042 } 2093 }
@@ -2057,7 +2108,7 @@ namespace OpenSim.Region.Framework.Scenes
2057 catch (Exception e) 2108 catch (Exception e)
2058 { 2109 {
2059 m_log.ErrorFormat( 2110 m_log.ErrorFormat(
2060 "[EVENT MANAGER]: Delegate for TriggerOnAttach failed - continuing. {0} {1}", 2111 "[EVENT MANAGER]: Delegate for TriggerOnAttach failed - continuing. {0} {1}",
2061 e.Message, e.StackTrace); 2112 e.Message, e.StackTrace);
2062 } 2113 }
2063 } 2114 }
@@ -2073,12 +2124,15 @@ 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 {
2080 m_log.ErrorFormat( 2134 m_log.ErrorFormat(
2081 "[EVENT MANAGER]: Delegate for TriggerClientClosed failed - continuing. {0} {1}", 2135 "[EVENT MANAGER]: Delegate for TriggerClientClosed failed - continuing. {0} {1}",
2082 e.Message, e.StackTrace); 2136 e.Message, e.StackTrace);
2083 } 2137 }
2084 } 2138 }
@@ -2099,7 +2153,7 @@ namespace OpenSim.Region.Framework.Scenes
2099 catch (Exception e) 2153 catch (Exception e)
2100 { 2154 {
2101 m_log.ErrorFormat( 2155 m_log.ErrorFormat(
2102 "[EVENT MANAGER]: Delegate for TriggerOnMakeChildAgent failed - continuing. {0} {1}", 2156 "[EVENT MANAGER]: Delegate for TriggerOnMakeChildAgent failed - continuing. {0} {1}",
2103 e.Message, e.StackTrace); 2157 e.Message, e.StackTrace);
2104 } 2158 }
2105 } 2159 }
@@ -2138,7 +2192,7 @@ namespace OpenSim.Region.Framework.Scenes
2138 catch (Exception e) 2192 catch (Exception e)
2139 { 2193 {
2140 m_log.ErrorFormat( 2194 m_log.ErrorFormat(
2141 "[EVENT MANAGER]: Delegate for TriggerOnMakeRootAgent failed - continuing. {0} {1}", 2195 "[EVENT MANAGER]: Delegate for TriggerOnMakeRootAgent failed - continuing. {0} {1}",
2142 e.Message, e.StackTrace); 2196 e.Message, e.StackTrace);
2143 } 2197 }
2144 } 2198 }
@@ -2159,7 +2213,7 @@ namespace OpenSim.Region.Framework.Scenes
2159 catch (Exception e) 2213 catch (Exception e)
2160 { 2214 {
2161 m_log.ErrorFormat( 2215 m_log.ErrorFormat(
2162 "[EVENT MANAGER]: Delegate for TriggerOnIncomingSceneObject failed - continuing. {0} {1}", 2216 "[EVENT MANAGER]: Delegate for TriggerOnIncomingSceneObject failed - continuing. {0} {1}",
2163 e.Message, e.StackTrace); 2217 e.Message, e.StackTrace);
2164 } 2218 }
2165 } 2219 }
@@ -2180,7 +2234,7 @@ namespace OpenSim.Region.Framework.Scenes
2180 catch (Exception e) 2234 catch (Exception e)
2181 { 2235 {
2182 m_log.ErrorFormat( 2236 m_log.ErrorFormat(
2183 "[EVENT MANAGER]: Delegate for TriggerOnRegisterCaps failed - continuing. {0} {1}", 2237 "[EVENT MANAGER]: Delegate for TriggerOnRegisterCaps failed - continuing. {0} {1}",
2184 e.Message, e.StackTrace); 2238 e.Message, e.StackTrace);
2185 } 2239 }
2186 } 2240 }
@@ -2201,14 +2255,14 @@ namespace OpenSim.Region.Framework.Scenes
2201 catch (Exception e) 2255 catch (Exception e)
2202 { 2256 {
2203 m_log.ErrorFormat( 2257 m_log.ErrorFormat(
2204 "[EVENT MANAGER]: Delegate for TriggerOnDeregisterCaps failed - continuing. {0} {1}", 2258 "[EVENT MANAGER]: Delegate for TriggerOnDeregisterCaps failed - continuing. {0} {1}",
2205 e.Message, e.StackTrace); 2259 e.Message, e.StackTrace);
2206 } 2260 }
2207 } 2261 }
2208 } 2262 }
2209 } 2263 }
2210 2264
2211 public void TriggerOnNewInventoryItemUploadComplete(UUID agentID, AssetType type, UUID AssetID, String AssetName, int userlevel) 2265 public void TriggerOnNewInventoryItemUploadComplete(InventoryItemBase item, int userlevel)
2212 { 2266 {
2213 NewInventoryItemUploadComplete handlerNewInventoryItemUpdateComplete = OnNewInventoryItemUploadComplete; 2267 NewInventoryItemUploadComplete handlerNewInventoryItemUpdateComplete = OnNewInventoryItemUploadComplete;
2214 if (handlerNewInventoryItemUpdateComplete != null) 2268 if (handlerNewInventoryItemUpdateComplete != null)
@@ -2217,12 +2271,12 @@ namespace OpenSim.Region.Framework.Scenes
2217 { 2271 {
2218 try 2272 try
2219 { 2273 {
2220 d(agentID, type, AssetID, AssetName, userlevel); 2274 d(item, userlevel);
2221 } 2275 }
2222 catch (Exception e) 2276 catch (Exception e)
2223 { 2277 {
2224 m_log.ErrorFormat( 2278 m_log.ErrorFormat(
2225 "[EVENT MANAGER]: Delegate for TriggerOnNewInventoryItemUploadComplete failed - continuing. {0} {1}", 2279 "[EVENT MANAGER]: Delegate for TriggerOnNewInventoryItemUploadComplete failed - continuing. {0} {1}",
2226 e.Message, e.StackTrace); 2280 e.Message, e.StackTrace);
2227 } 2281 }
2228 } 2282 }
@@ -2243,7 +2297,7 @@ namespace OpenSim.Region.Framework.Scenes
2243 catch (Exception e) 2297 catch (Exception e)
2244 { 2298 {
2245 m_log.ErrorFormat( 2299 m_log.ErrorFormat(
2246 "[EVENT MANAGER]: Delegate for TriggerLandBuy failed - continuing. {0} {1}", 2300 "[EVENT MANAGER]: Delegate for TriggerLandBuy failed - continuing. {0} {1}",
2247 e.Message, e.StackTrace); 2301 e.Message, e.StackTrace);
2248 } 2302 }
2249 } 2303 }
@@ -2264,7 +2318,7 @@ namespace OpenSim.Region.Framework.Scenes
2264 catch (Exception e) 2318 catch (Exception e)
2265 { 2319 {
2266 m_log.ErrorFormat( 2320 m_log.ErrorFormat(
2267 "[EVENT MANAGER]: Delegate for TriggerValidateLandBuy failed - continuing. {0} {1}", 2321 "[EVENT MANAGER]: Delegate for TriggerValidateLandBuy failed - continuing. {0} {1}",
2268 e.Message, e.StackTrace); 2322 e.Message, e.StackTrace);
2269 } 2323 }
2270 } 2324 }
@@ -2285,7 +2339,7 @@ namespace OpenSim.Region.Framework.Scenes
2285 catch (Exception e) 2339 catch (Exception e)
2286 { 2340 {
2287 m_log.ErrorFormat( 2341 m_log.ErrorFormat(
2288 "[EVENT MANAGER]: Delegate for TriggerAtTargetEvent failed - continuing. {0} {1}", 2342 "[EVENT MANAGER]: Delegate for TriggerAtTargetEvent failed - continuing. {0} {1}",
2289 e.Message, e.StackTrace); 2343 e.Message, e.StackTrace);
2290 } 2344 }
2291 } 2345 }
@@ -2306,7 +2360,7 @@ namespace OpenSim.Region.Framework.Scenes
2306 catch (Exception e) 2360 catch (Exception e)
2307 { 2361 {
2308 m_log.ErrorFormat( 2362 m_log.ErrorFormat(
2309 "[EVENT MANAGER]: Delegate for TriggerNotAtTargetEvent failed - continuing. {0} {1}", 2363 "[EVENT MANAGER]: Delegate for TriggerNotAtTargetEvent failed - continuing. {0} {1}",
2310 e.Message, e.StackTrace); 2364 e.Message, e.StackTrace);
2311 } 2365 }
2312 } 2366 }
@@ -2327,7 +2381,7 @@ namespace OpenSim.Region.Framework.Scenes
2327 catch (Exception e) 2381 catch (Exception e)
2328 { 2382 {
2329 m_log.ErrorFormat( 2383 m_log.ErrorFormat(
2330 "[EVENT MANAGER]: Delegate for TriggerAtRotTargetEvent failed - continuing. {0} {1}", 2384 "[EVENT MANAGER]: Delegate for TriggerAtRotTargetEvent failed - continuing. {0} {1}",
2331 e.Message, e.StackTrace); 2385 e.Message, e.StackTrace);
2332 } 2386 }
2333 } 2387 }
@@ -2348,7 +2402,7 @@ namespace OpenSim.Region.Framework.Scenes
2348 catch (Exception e) 2402 catch (Exception e)
2349 { 2403 {
2350 m_log.ErrorFormat( 2404 m_log.ErrorFormat(
2351 "[EVENT MANAGER]: Delegate for TriggerNotAtRotTargetEvent failed - continuing. {0} {1}", 2405 "[EVENT MANAGER]: Delegate for TriggerNotAtRotTargetEvent failed - continuing. {0} {1}",
2352 e.Message, e.StackTrace); 2406 e.Message, e.StackTrace);
2353 } 2407 }
2354 } 2408 }
@@ -2417,7 +2471,7 @@ namespace OpenSim.Region.Framework.Scenes
2417 catch (Exception e) 2471 catch (Exception e)
2418 { 2472 {
2419 m_log.ErrorFormat( 2473 m_log.ErrorFormat(
2420 "[EVENT MANAGER]: Delegate for TriggerRequestChangeWaterHeight failed - continuing. {0} {1}", 2474 "[EVENT MANAGER]: Delegate for TriggerRequestChangeWaterHeight failed - continuing. {0} {1}",
2421 e.Message, e.StackTrace); 2475 e.Message, e.StackTrace);
2422 } 2476 }
2423 } 2477 }
@@ -2438,7 +2492,7 @@ namespace OpenSim.Region.Framework.Scenes
2438 catch (Exception e) 2492 catch (Exception e)
2439 { 2493 {
2440 m_log.ErrorFormat( 2494 m_log.ErrorFormat(
2441 "[EVENT MANAGER]: Delegate for TriggerAvatarKill failed - continuing. {0} {1}", 2495 "[EVENT MANAGER]: Delegate for TriggerAvatarKill failed - continuing. {0} {1}",
2442 e.Message, e.StackTrace); 2496 e.Message, e.StackTrace);
2443 } 2497 }
2444 } 2498 }
@@ -2459,7 +2513,7 @@ namespace OpenSim.Region.Framework.Scenes
2459 catch (Exception e) 2513 catch (Exception e)
2460 { 2514 {
2461 m_log.ErrorFormat( 2515 m_log.ErrorFormat(
2462 "[EVENT MANAGER]: Delegate for TriggerSignificantClientMovement failed - continuing. {0} {1}", 2516 "[EVENT MANAGER]: Delegate for TriggerSignificantClientMovement failed - continuing. {0} {1}",
2463 e.Message, e.StackTrace); 2517 e.Message, e.StackTrace);
2464 } 2518 }
2465 } 2519 }
@@ -2480,7 +2534,7 @@ namespace OpenSim.Region.Framework.Scenes
2480 catch (Exception e) 2534 catch (Exception e)
2481 { 2535 {
2482 m_log.ErrorFormat( 2536 m_log.ErrorFormat(
2483 "[EVENT MANAGER]: Delegate for TriggerOnChatFromWorld failed - continuing. {0} {1}", 2537 "[EVENT MANAGER]: Delegate for TriggerOnChatFromWorld failed - continuing. {0} {1}",
2484 e.Message, e.StackTrace); 2538 e.Message, e.StackTrace);
2485 } 2539 }
2486 } 2540 }
@@ -2501,16 +2555,16 @@ namespace OpenSim.Region.Framework.Scenes
2501 catch (Exception e) 2555 catch (Exception e)
2502 { 2556 {
2503 m_log.ErrorFormat( 2557 m_log.ErrorFormat(
2504 "[EVENT MANAGER]: Delegate for TriggerOnChatFromClient failed - continuing. {0} {1}", 2558 "[EVENT MANAGER]: Delegate for TriggerOnChatFromClient failed - continuing. {0} {1}",
2505 e.Message, e.StackTrace); 2559 e.Message, e.StackTrace);
2506 } 2560 }
2507 } 2561 }
2508 } 2562 }
2509 } 2563 }
2510 2564
2511 public void TriggerOnChatToClients( 2565 public void TriggerOnChatToClients(
2512 UUID senderID, HashSet<UUID> receiverIDs, 2566 UUID senderID, HashSet<UUID> receiverIDs,
2513 string message, ChatTypeEnum type, Vector3 fromPos, string fromName, 2567 string message, ChatTypeEnum type, Vector3 fromPos, string fromName,
2514 ChatSourceType src, ChatAudibleLevel level) 2568 ChatSourceType src, ChatAudibleLevel level)
2515 { 2569 {
2516 ChatToClientsEvent handler = OnChatToClients; 2570 ChatToClientsEvent handler = OnChatToClients;
@@ -2525,7 +2579,7 @@ namespace OpenSim.Region.Framework.Scenes
2525 catch (Exception e) 2579 catch (Exception e)
2526 { 2580 {
2527 m_log.ErrorFormat( 2581 m_log.ErrorFormat(
2528 "[EVENT MANAGER]: Delegate for TriggerOnChatToClients failed - continuing. {0} {1}", 2582 "[EVENT MANAGER]: Delegate for TriggerOnChatToClients failed - continuing. {0} {1}",
2529 e.Message, e.StackTrace); 2583 e.Message, e.StackTrace);
2530 } 2584 }
2531 } 2585 }
@@ -2546,7 +2600,7 @@ namespace OpenSim.Region.Framework.Scenes
2546 catch (Exception e) 2600 catch (Exception e)
2547 { 2601 {
2548 m_log.ErrorFormat( 2602 m_log.ErrorFormat(
2549 "[EVENT MANAGER]: Delegate for TriggerOnChatBroadcast failed - continuing. {0} {1}", 2603 "[EVENT MANAGER]: Delegate for TriggerOnChatBroadcast failed - continuing. {0} {1}",
2550 e.Message, e.StackTrace); 2604 e.Message, e.StackTrace);
2551 } 2605 }
2552 } 2606 }
@@ -2567,7 +2621,7 @@ namespace OpenSim.Region.Framework.Scenes
2567 catch (Exception e) 2621 catch (Exception e)
2568 { 2622 {
2569 m_log.ErrorFormat( 2623 m_log.ErrorFormat(
2570 "[EVENT MANAGER]: Delegate for TriggerControlEvent failed - continuing. {0} {1}", 2624 "[EVENT MANAGER]: Delegate for TriggerControlEvent failed - continuing. {0} {1}",
2571 e.Message, e.StackTrace); 2625 e.Message, e.StackTrace);
2572 } 2626 }
2573 } 2627 }
@@ -2588,7 +2642,7 @@ namespace OpenSim.Region.Framework.Scenes
2588 catch (Exception e) 2642 catch (Exception e)
2589 { 2643 {
2590 m_log.ErrorFormat( 2644 m_log.ErrorFormat(
2591 "[EVENT MANAGER]: Delegate for TriggerNoticeNoLandDataFromStorage failed - continuing. {0} {1}", 2645 "[EVENT MANAGER]: Delegate for TriggerNoticeNoLandDataFromStorage failed - continuing. {0} {1}",
2592 e.Message, e.StackTrace); 2646 e.Message, e.StackTrace);
2593 } 2647 }
2594 } 2648 }
@@ -2609,7 +2663,7 @@ namespace OpenSim.Region.Framework.Scenes
2609 catch (Exception e) 2663 catch (Exception e)
2610 { 2664 {
2611 m_log.ErrorFormat( 2665 m_log.ErrorFormat(
2612 "[EVENT MANAGER]: Delegate for TriggerIncomingLandDataFromStorage failed - continuing. {0} {1}", 2666 "[EVENT MANAGER]: Delegate for TriggerIncomingLandDataFromStorage failed - continuing. {0} {1}",
2613 e.Message, e.StackTrace); 2667 e.Message, e.StackTrace);
2614 } 2668 }
2615 } 2669 }
@@ -2630,7 +2684,7 @@ namespace OpenSim.Region.Framework.Scenes
2630 catch (Exception e) 2684 catch (Exception e)
2631 { 2685 {
2632 m_log.ErrorFormat( 2686 m_log.ErrorFormat(
2633 "[EVENT MANAGER]: Delegate for TriggerSetAllowForcefulBan failed - continuing. {0} {1}", 2687 "[EVENT MANAGER]: Delegate for TriggerSetAllowForcefulBan failed - continuing. {0} {1}",
2634 e.Message, e.StackTrace); 2688 e.Message, e.StackTrace);
2635 } 2689 }
2636 } 2690 }
@@ -2651,7 +2705,7 @@ namespace OpenSim.Region.Framework.Scenes
2651 catch (Exception e) 2705 catch (Exception e)
2652 { 2706 {
2653 m_log.ErrorFormat( 2707 m_log.ErrorFormat(
2654 "[EVENT MANAGER]: Delegate for TriggerRequestParcelPrimCountUpdate failed - continuing. {0} {1}", 2708 "[EVENT MANAGER]: Delegate for TriggerRequestParcelPrimCountUpdate failed - continuing. {0} {1}",
2655 e.Message, e.StackTrace); 2709 e.Message, e.StackTrace);
2656 } 2710 }
2657 } 2711 }
@@ -2672,7 +2726,7 @@ namespace OpenSim.Region.Framework.Scenes
2672 catch (Exception e) 2726 catch (Exception e)
2673 { 2727 {
2674 m_log.ErrorFormat( 2728 m_log.ErrorFormat(
2675 "[EVENT MANAGER]: Delegate for TriggerParcelPrimCountTainted failed - continuing. {0} {1}", 2729 "[EVENT MANAGER]: Delegate for TriggerParcelPrimCountTainted failed - continuing. {0} {1}",
2676 e.Message, e.StackTrace); 2730 e.Message, e.StackTrace);
2677 } 2731 }
2678 } 2732 }
@@ -2712,7 +2766,7 @@ namespace OpenSim.Region.Framework.Scenes
2712 catch (Exception e) 2766 catch (Exception e)
2713 { 2767 {
2714 m_log.ErrorFormat( 2768 m_log.ErrorFormat(
2715 "[EVENT MANAGER]: Delegate for TriggerEstateToolsSunUpdate failed - continuing. {0} {1}", 2769 "[EVENT MANAGER]: Delegate for TriggerEstateToolsSunUpdate failed - continuing. {0} {1}",
2716 e.Message, e.StackTrace); 2770 e.Message, e.StackTrace);
2717 } 2771 }
2718 } 2772 }
@@ -2733,12 +2787,12 @@ namespace OpenSim.Region.Framework.Scenes
2733 catch (Exception e) 2787 catch (Exception e)
2734 { 2788 {
2735 m_log.ErrorFormat( 2789 m_log.ErrorFormat(
2736 "[EVENT MANAGER]: Delegate for TriggerOnAttach failed - continuing. {0} {1}", 2790 "[EVENT MANAGER]: Delegate for TriggerOnAttach failed - continuing. {0} {1}",
2737 e.Message, e.StackTrace); 2791 e.Message, e.StackTrace);
2738 } 2792 }
2739 } 2793 }
2740 } 2794 }
2741 2795
2742 return 6; 2796 return 6;
2743 } 2797 }
2744 2798
@@ -2756,13 +2810,13 @@ namespace OpenSim.Region.Framework.Scenes
2756 catch (Exception e) 2810 catch (Exception e)
2757 { 2811 {
2758 m_log.ErrorFormat( 2812 m_log.ErrorFormat(
2759 "[EVENT MANAGER]: Delegate for TriggerOarFileLoaded failed - continuing. {0} {1}", 2813 "[EVENT MANAGER]: Delegate for TriggerOarFileLoaded failed - continuing. {0} {1}",
2760 e.Message, e.StackTrace); 2814 e.Message, e.StackTrace);
2761 } 2815 }
2762 } 2816 }
2763 } 2817 }
2764 } 2818 }
2765 2819
2766 public void TriggerOarFileSaved(Guid requestId, string message) 2820 public void TriggerOarFileSaved(Guid requestId, string message)
2767 { 2821 {
2768 OarFileSaved handlerOarFileSaved = OnOarFileSaved; 2822 OarFileSaved handlerOarFileSaved = OnOarFileSaved;
@@ -2777,7 +2831,7 @@ namespace OpenSim.Region.Framework.Scenes
2777 catch (Exception e) 2831 catch (Exception e)
2778 { 2832 {
2779 m_log.ErrorFormat( 2833 m_log.ErrorFormat(
2780 "[EVENT MANAGER]: Delegate for TriggerOarFileSaved failed - continuing. {0} {1}", 2834 "[EVENT MANAGER]: Delegate for TriggerOarFileSaved failed - continuing. {0} {1}",
2781 e.Message, e.StackTrace); 2835 e.Message, e.StackTrace);
2782 } 2836 }
2783 } 2837 }
@@ -2798,7 +2852,7 @@ namespace OpenSim.Region.Framework.Scenes
2798 catch (Exception e) 2852 catch (Exception e)
2799 { 2853 {
2800 m_log.ErrorFormat( 2854 m_log.ErrorFormat(
2801 "[EVENT MANAGER]: Delegate for TriggerEmptyScriptCompileQueue failed - continuing. {0} {1}", 2855 "[EVENT MANAGER]: Delegate for TriggerEmptyScriptCompileQueue failed - continuing. {0} {1}",
2802 e.Message, e.StackTrace); 2856 e.Message, e.StackTrace);
2803 } 2857 }
2804 } 2858 }
@@ -2819,7 +2873,7 @@ namespace OpenSim.Region.Framework.Scenes
2819 catch (Exception e) 2873 catch (Exception e)
2820 { 2874 {
2821 m_log.ErrorFormat( 2875 m_log.ErrorFormat(
2822 "[EVENT MANAGER]: Delegate for TriggerScriptCollidingStart failed - continuing. {0} {1}", 2876 "[EVENT MANAGER]: Delegate for TriggerScriptCollidingStart failed - continuing. {0} {1}",
2823 e.Message, e.StackTrace); 2877 e.Message, e.StackTrace);
2824 } 2878 }
2825 } 2879 }
@@ -2840,7 +2894,7 @@ namespace OpenSim.Region.Framework.Scenes
2840 catch (Exception e) 2894 catch (Exception e)
2841 { 2895 {
2842 m_log.ErrorFormat( 2896 m_log.ErrorFormat(
2843 "[EVENT MANAGER]: Delegate for TriggerScriptColliding failed - continuing. {0} {1}", 2897 "[EVENT MANAGER]: Delegate for TriggerScriptColliding failed - continuing. {0} {1}",
2844 e.Message, e.StackTrace); 2898 e.Message, e.StackTrace);
2845 } 2899 }
2846 } 2900 }
@@ -2861,7 +2915,7 @@ namespace OpenSim.Region.Framework.Scenes
2861 catch (Exception e) 2915 catch (Exception e)
2862 { 2916 {
2863 m_log.ErrorFormat( 2917 m_log.ErrorFormat(
2864 "[EVENT MANAGER]: Delegate for TriggerScriptCollidingEnd failed - continuing. {0} {1}", 2918 "[EVENT MANAGER]: Delegate for TriggerScriptCollidingEnd failed - continuing. {0} {1}",
2865 e.Message, e.StackTrace); 2919 e.Message, e.StackTrace);
2866 } 2920 }
2867 } 2921 }
@@ -2882,7 +2936,7 @@ namespace OpenSim.Region.Framework.Scenes
2882 catch (Exception e) 2936 catch (Exception e)
2883 { 2937 {
2884 m_log.ErrorFormat( 2938 m_log.ErrorFormat(
2885 "[EVENT MANAGER]: Delegate for TriggerScriptLandCollidingStart failed - continuing. {0} {1}", 2939 "[EVENT MANAGER]: Delegate for TriggerScriptLandCollidingStart failed - continuing. {0} {1}",
2886 e.Message, e.StackTrace); 2940 e.Message, e.StackTrace);
2887 } 2941 }
2888 } 2942 }
@@ -2903,7 +2957,7 @@ namespace OpenSim.Region.Framework.Scenes
2903 catch (Exception e) 2957 catch (Exception e)
2904 { 2958 {
2905 m_log.ErrorFormat( 2959 m_log.ErrorFormat(
2906 "[EVENT MANAGER]: Delegate for TriggerScriptLandColliding failed - continuing. {0} {1}", 2960 "[EVENT MANAGER]: Delegate for TriggerScriptLandColliding failed - continuing. {0} {1}",
2907 e.Message, e.StackTrace); 2961 e.Message, e.StackTrace);
2908 } 2962 }
2909 } 2963 }
@@ -2924,7 +2978,7 @@ namespace OpenSim.Region.Framework.Scenes
2924 catch (Exception e) 2978 catch (Exception e)
2925 { 2979 {
2926 m_log.ErrorFormat( 2980 m_log.ErrorFormat(
2927 "[EVENT MANAGER]: Delegate for TriggerScriptLandCollidingEnd failed - continuing. {0} {1}", 2981 "[EVENT MANAGER]: Delegate for TriggerScriptLandCollidingEnd failed - continuing. {0} {1}",
2928 e.Message, e.StackTrace); 2982 e.Message, e.StackTrace);
2929 } 2983 }
2930 } 2984 }
@@ -2945,7 +2999,7 @@ namespace OpenSim.Region.Framework.Scenes
2945 catch (Exception e) 2999 catch (Exception e)
2946 { 3000 {
2947 m_log.ErrorFormat( 3001 m_log.ErrorFormat(
2948 "[EVENT MANAGER]: Delegate for TriggerSetRootAgentScene failed - continuing. {0} {1}", 3002 "[EVENT MANAGER]: Delegate for TriggerSetRootAgentScene failed - continuing. {0} {1}",
2949 e.Message, e.StackTrace); 3003 e.Message, e.StackTrace);
2950 } 3004 }
2951 } 3005 }
@@ -2966,13 +3020,13 @@ namespace OpenSim.Region.Framework.Scenes
2966 catch (Exception e) 3020 catch (Exception e)
2967 { 3021 {
2968 m_log.ErrorFormat( 3022 m_log.ErrorFormat(
2969 "[EVENT MANAGER]: Delegate for TriggerOnRegionUp failed - continuing. {0} {1}", 3023 "[EVENT MANAGER]: Delegate for TriggerOnRegionUp failed - continuing. {0} {1}",
2970 e.Message, e.StackTrace); 3024 e.Message, e.StackTrace);
2971 } 3025 }
2972 } 3026 }
2973 } 3027 }
2974 } 3028 }
2975 3029
2976 public void TriggerOnSceneObjectLoaded(SceneObjectGroup so) 3030 public void TriggerOnSceneObjectLoaded(SceneObjectGroup so)
2977 { 3031 {
2978 SceneObjectDelegate handler = OnSceneObjectLoaded; 3032 SceneObjectDelegate handler = OnSceneObjectLoaded;
@@ -2987,13 +3041,13 @@ namespace OpenSim.Region.Framework.Scenes
2987 catch (Exception e) 3041 catch (Exception e)
2988 { 3042 {
2989 m_log.ErrorFormat( 3043 m_log.ErrorFormat(
2990 "[EVENT MANAGER]: Delegate for TriggerOnSceneObjectLoaded failed - continuing. {0} {1}", 3044 "[EVENT MANAGER]: Delegate for TriggerOnSceneObjectLoaded failed - continuing. {0} {1}",
2991 e.Message, e.StackTrace); 3045 e.Message, e.StackTrace);
2992 } 3046 }
2993 } 3047 }
2994 } 3048 }
2995 } 3049 }
2996 3050
2997 public void TriggerOnSceneObjectPreSave(SceneObjectGroup persistingSo, SceneObjectGroup originalSo) 3051 public void TriggerOnSceneObjectPreSave(SceneObjectGroup persistingSo, SceneObjectGroup originalSo)
2998 { 3052 {
2999 SceneObjectPreSaveDelegate handler = OnSceneObjectPreSave; 3053 SceneObjectPreSaveDelegate handler = OnSceneObjectPreSave;
@@ -3008,13 +3062,13 @@ namespace OpenSim.Region.Framework.Scenes
3008 catch (Exception e) 3062 catch (Exception e)
3009 { 3063 {
3010 m_log.ErrorFormat( 3064 m_log.ErrorFormat(
3011 "[EVENT MANAGER]: Delegate for TriggerOnSceneObjectPreSave failed - continuing. {0} {1}", 3065 "[EVENT MANAGER]: Delegate for TriggerOnSceneObjectPreSave failed - continuing. {0} {1}",
3012 e.Message, e.StackTrace); 3066 e.Message, e.StackTrace);
3013 } 3067 }
3014 } 3068 }
3015 } 3069 }
3016 } 3070 }
3017 3071
3018 public void TriggerOnSceneObjectPartCopy(SceneObjectPart copy, SceneObjectPart original, bool userExposed) 3072 public void TriggerOnSceneObjectPartCopy(SceneObjectPart copy, SceneObjectPart original, bool userExposed)
3019 { 3073 {
3020 SceneObjectPartCopyDelegate handler = OnSceneObjectPartCopy; 3074 SceneObjectPartCopyDelegate handler = OnSceneObjectPartCopy;
@@ -3029,7 +3083,7 @@ namespace OpenSim.Region.Framework.Scenes
3029 catch (Exception e) 3083 catch (Exception e)
3030 { 3084 {
3031 m_log.ErrorFormat( 3085 m_log.ErrorFormat(
3032 "[EVENT MANAGER]: Delegate for TriggerOnSceneObjectPartCopy failed - continuing. {0} {1}", 3086 "[EVENT MANAGER]: Delegate for TriggerOnSceneObjectPartCopy failed - continuing. {0} {1}",
3033 e.Message, e.StackTrace); 3087 e.Message, e.StackTrace);
3034 } 3088 }
3035 } 3089 }
@@ -3050,7 +3104,7 @@ namespace OpenSim.Region.Framework.Scenes
3050 catch (Exception e) 3104 catch (Exception e)
3051 { 3105 {
3052 m_log.ErrorFormat( 3106 m_log.ErrorFormat(
3053 "[EVENT MANAGER]: Delegate for TriggerSceneObjectPartUpdated failed - continuing. {0} {1}", 3107 "[EVENT MANAGER]: Delegate for TriggerSceneObjectPartUpdated failed - continuing. {0} {1}",
3054 e.Message, e.StackTrace); 3108 e.Message, e.StackTrace);
3055 } 3109 }
3056 } 3110 }
@@ -3093,7 +3147,7 @@ namespace OpenSim.Region.Framework.Scenes
3093 catch (Exception e) 3147 catch (Exception e)
3094 { 3148 {
3095 m_log.ErrorFormat( 3149 m_log.ErrorFormat(
3096 "[EVENT MANAGER]: Delegate for TriggerOnSceneObjectPartCopy failed - continuing. {0} {1}", 3150 "[EVENT MANAGER]: Delegate for TriggerOnSceneObjectPartCopy failed - continuing. {0} {1}",
3097 e.Message, e.StackTrace); 3151 e.Message, e.StackTrace);
3098 } 3152 }
3099 } 3153 }
@@ -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 invoke {0}", d.Method.Name.ToString());
3110 try 3165 try
3111 { 3166 {
3112 d(s); 3167 d(s);
@@ -3114,11 +3169,12 @@ namespace OpenSim.Region.Framework.Scenes
3114 catch (Exception e) 3169 catch (Exception e)
3115 { 3170 {
3116 m_log.ErrorFormat( 3171 m_log.ErrorFormat(
3117 "[EVENT MANAGER]: Delegate for TriggerSceneShuttingDown failed - continuing. {0} {1}", 3172 "[EVENT MANAGER]: Delegate for TriggerSceneShuttingDown failed - continuing. {0} {1}",
3118 e.Message, e.StackTrace); 3173 e.Message, e.StackTrace);
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/GodController.cs b/OpenSim/Region/Framework/Scenes/GodController.cs
new file mode 100644
index 0000000..9372366
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/GodController.cs
@@ -0,0 +1,287 @@
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 OpenMetaverse.StructuredData;
37using log4net;
38using Nini.Config;
39using OpenSim.Framework;
40using OpenSim.Framework.Client;
41using OpenSim.Framework.Monitoring;
42using OpenSim.Region.Framework.Interfaces;
43using OpenSim.Region.Framework.Scenes.Types;
44using OpenSim.Services.Interfaces;
45
46namespace OpenSim.Region.Framework.Scenes
47{
48 public class GodController
49 {
50 public enum ImplicitGodLevels : int
51 {
52 EstateManager = 210, // estate manager implicit god level
53 RegionOwner = 220 // region owner implicit god level should be >= than estate
54 }
55
56 ScenePresence m_scenePresence;
57 Scene m_scene;
58 protected bool m_allowGridGods;
59 protected bool m_forceGridGodsOnly;
60 protected bool m_regionOwnerIsGod;
61 protected bool m_regionManagerIsGod;
62 protected bool m_forceGodModeAlwaysOn;
63 protected bool m_allowGodActionsWithoutGodMode;
64
65 protected int m_userLevel = 0;
66 // the god level from local or grid user rights
67 protected int m_rightsGodLevel = 0;
68 // the level seen by viewers
69 protected int m_viewergodlevel = 0;
70 // new level that can be fixed or equal to godlevel, acording to options
71 protected int m_godlevel = 0;
72 protected int m_lastLevelToViewer = 0;
73
74 public GodController(Scene scene, ScenePresence sp, int userlevel)
75 {
76 m_scene = scene;
77 m_scenePresence = sp;
78 m_userLevel = userlevel;
79
80 IConfigSource config = scene.Config;
81
82 string[] sections = new string[] { "Startup", "Permissions" };
83
84 // God level is based on UserLevel. Gods will have that
85 // level grid-wide. Others may become god locally but grid
86 // gods are god everywhere.
87 m_allowGridGods =
88 Util.GetConfigVarFromSections<bool>(config,
89 "allow_grid_gods", sections, false);
90
91 // If grid gods are active, dont allow any other gods
92 m_forceGridGodsOnly =
93 Util.GetConfigVarFromSections<bool>(config,
94 "force_grid_gods_only", sections, false);
95
96 if(!m_forceGridGodsOnly)
97 {
98 // The owner of a region is a god in his region only.
99 m_regionOwnerIsGod =
100 Util.GetConfigVarFromSections<bool>(config,
101 "region_owner_is_god", sections, true);
102
103 // Region managers are gods in the regions they manage.
104 m_regionManagerIsGod =
105 Util.GetConfigVarFromSections<bool>(config,
106 "region_manager_is_god", sections, false);
107
108 }
109 else
110 m_allowGridGods = true; // reduce potencial user mistakes
111
112 // God mode should be turned on in the viewer whenever
113 // the user has god rights somewhere. They may choose
114 // to turn it off again, though.
115 m_forceGodModeAlwaysOn =
116 Util.GetConfigVarFromSections<bool>(config,
117 "automatic_gods", sections, false);
118
119 // The user can execute any and all god functions, as
120 // permitted by the viewer UI, without actually "godding
121 // up". This is the default state in 0.8.2.
122 m_allowGodActionsWithoutGodMode =
123 Util.GetConfigVarFromSections<bool>(config,
124 "implicit_gods", sections, false);
125
126 m_rightsGodLevel = CalcRightsGodLevel();
127
128 if(m_allowGodActionsWithoutGodMode)
129 {
130 m_godlevel = m_rightsGodLevel;
131 m_forceGodModeAlwaysOn = false;
132 }
133
134 else if(m_forceGodModeAlwaysOn)
135 {
136 m_viewergodlevel = m_rightsGodLevel;
137 m_godlevel = m_rightsGodLevel;
138 }
139
140 m_scenePresence.IsGod = (m_godlevel >= 200);
141 m_scenePresence.IsViewerUIGod = (m_viewergodlevel >= 200);
142 }
143
144 // calculates god level at sp creation from local and grid user god rights
145 // for now this is assumed static until user leaves region.
146 // later estate and gride level updates may update this
147 protected int CalcRightsGodLevel()
148 {
149 int level = 0;
150 if (m_allowGridGods && m_userLevel >= 200)
151 level = m_userLevel;
152
153 if(m_forceGridGodsOnly || level >= (int)ImplicitGodLevels.RegionOwner)
154 return level;
155
156 if (m_regionOwnerIsGod && m_scene.RegionInfo.EstateSettings.IsEstateOwner(m_scenePresence.UUID))
157 level = (int)ImplicitGodLevels.RegionOwner;
158
159 if(level >= (int)ImplicitGodLevels.EstateManager)
160 return level;
161
162 if (m_regionManagerIsGod && m_scene.Permissions.IsEstateManager(m_scenePresence.UUID))
163 level = (int)ImplicitGodLevels.EstateManager;
164
165 return level;
166 }
167
168 protected bool CanBeGod()
169 {
170 return m_rightsGodLevel >= 200;
171 }
172
173 protected void UpdateGodLevels(bool viewerState)
174 {
175 if(!CanBeGod())
176 {
177 m_viewergodlevel = 0;
178 m_godlevel = 0;
179 m_scenePresence.IsGod = false;
180 m_scenePresence.IsViewerUIGod = false;
181 return;
182 }
183
184 // legacy some are controled by viewer, others are static
185 if(m_allowGodActionsWithoutGodMode)
186 {
187 if(viewerState)
188 m_viewergodlevel = m_rightsGodLevel;
189 else
190 m_viewergodlevel = 0;
191
192 m_godlevel = m_rightsGodLevel;
193 }
194 else
195 {
196 // new all change with viewer
197 if(viewerState)
198 {
199 m_viewergodlevel = m_rightsGodLevel;
200 m_godlevel = m_rightsGodLevel;
201 }
202 else
203 {
204 m_viewergodlevel = 0;
205 m_godlevel = 0;
206 }
207 }
208 m_scenePresence.IsGod = (m_godlevel >= 200);
209 m_scenePresence.IsViewerUIGod = (m_viewergodlevel >= 200);
210 }
211
212 public void SyncViewerState()
213 {
214 if(m_lastLevelToViewer == m_viewergodlevel)
215 return;
216
217 m_lastLevelToViewer = m_viewergodlevel;
218
219 if(m_scenePresence.IsChildAgent)
220 return;
221
222 m_scenePresence.ControllingClient.SendAdminResponse(UUID.Zero, (uint)m_viewergodlevel);
223 }
224
225 public void RequestGodMode(bool god)
226 {
227 UpdateGodLevels(god);
228
229 if(m_lastLevelToViewer != m_viewergodlevel)
230 {
231 m_scenePresence.ControllingClient.SendAdminResponse(UUID.Zero, (uint)m_viewergodlevel);
232 m_lastLevelToViewer = m_viewergodlevel;
233 }
234 }
235
236 public OSD State()
237 {
238 OSDMap godMap = new OSDMap(2);
239 bool m_viewerUiIsGod = m_viewergodlevel >= 200;
240 godMap.Add("ViewerUiIsGod", OSD.FromBoolean(m_viewerUiIsGod));
241
242 return godMap;
243 }
244
245 public void SetState(OSD state)
246 {
247 bool newstate = false;
248 if(m_forceGodModeAlwaysOn)
249 newstate = m_viewergodlevel >= 200;
250 if(state != null)
251 {
252 OSDMap s = (OSDMap)state;
253
254 if (s.ContainsKey("ViewerUiIsGod"))
255 newstate = s["ViewerUiIsGod"].AsBoolean();
256 m_lastLevelToViewer = m_viewergodlevel; // we are not changing viewer level by default
257 }
258 UpdateGodLevels(newstate);
259 }
260
261 public void HasMovedAway()
262 {
263 m_lastLevelToViewer = 0;
264 if(m_forceGodModeAlwaysOn)
265 {
266 m_viewergodlevel = m_rightsGodLevel;
267 m_godlevel = m_rightsGodLevel;
268 }
269 }
270
271 public int UserLevel
272 {
273 get { return m_userLevel; }
274 set { m_userLevel = value; }
275 }
276
277 public int ViwerUIGodLevel
278 {
279 get { return m_viewergodlevel; }
280 }
281
282 public int GodLevel
283 {
284 get { return m_godlevel; }
285 }
286 }
287}
diff --git a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
index bbf3b51..80ee510 100644
--- a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
+++ b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
@@ -140,7 +140,7 @@ namespace OpenSim.Region.Framework.Scenes
140 timer.Start(); 140 timer.Start();
141 }; 141 };
142 } 142 }
143 143
144 // Check again, in case the regions were started while we were adding the event handler 144 // Check again, in case the regions were started while we were adding the event handler
145 if (SceneManager.Instance.AllRegionsReady) 145 if (SceneManager.Instance.AllRegionsReady)
146 { 146 {
@@ -292,14 +292,18 @@ 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_lasttickMS = Util.GetTimeStampMS();
299 m_timerStopped = false;
300 }
297 } 301 }
298 302
299 private void StopTimer() 303 private void StopTimer()
300 { 304 {
301 m_timerStopped = true; 305 lock (m_frames)
302 KeyframeTimer.Remove(this); 306 m_timerStopped = true;
303 } 307 }
304 308
305 public static KeyframeMotion FromData(SceneObjectGroup grp, Byte[] data) 309 public static KeyframeMotion FromData(SceneObjectGroup grp, Byte[] data)
@@ -323,8 +327,8 @@ namespace OpenSim.Region.Framework.Scenes
323 newMotion.m_selected = true; 327 newMotion.m_selected = true;
324 } 328 }
325 329
326 newMotion.m_timerStopped = false; 330// newMotion.m_timerStopped = false;
327 newMotion.m_running = true; 331// newMotion.m_running = true;
328 newMotion.m_isCrossing = false; 332 newMotion.m_isCrossing = false;
329 newMotion.m_waitingCrossing = false; 333 newMotion.m_waitingCrossing = false;
330 } 334 }
@@ -348,24 +352,26 @@ namespace OpenSim.Region.Framework.Scenes
348 m_group = grp; 352 m_group = grp;
349 m_scene = grp.Scene; 353 m_scene = grp.Scene;
350 354
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 355
357 m_basePosition += offset; 356 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 { 357 {
365 Keyframe k = m_frames[i]; 358 Vector3 grppos = grp.AbsolutePosition;
366 k.StartPosition += offset; 359 Vector3 offset = grppos - m_serializedPosition;
367 k.Position += offset; 360 // avoid doing it more than once
368 m_frames[i]=k; 361 // current this will happen draging a prim to other region
362 m_serializedPosition = grppos;
363
364 m_basePosition += offset;
365 m_currentFrame.Position += offset;
366
367 m_nextPosition += offset;
368
369 for (int i = 0; i < m_frames.Count; i++)
370 {
371 Keyframe k = m_frames[i];
372 k.Position += offset;
373 m_frames[i] = k;
374 }
369 } 375 }
370 376
371 if (m_running) 377 if (m_running)
@@ -410,25 +416,28 @@ namespace OpenSim.Region.Framework.Scenes
410 m_keyframes.CopyTo(newmotion.m_keyframes, 0); 416 m_keyframes.CopyTo(newmotion.m_keyframes, 0);
411 } 417 }
412 418
413 newmotion.m_frames = new List<Keyframe>(m_frames); 419 lock (m_frames)
420 {
421 newmotion.m_frames = new List<Keyframe>(m_frames);
414 422
415 newmotion.m_basePosition = m_basePosition; 423 newmotion.m_basePosition = m_basePosition;
416 newmotion.m_baseRotation = m_baseRotation; 424 newmotion.m_baseRotation = m_baseRotation;
417 425
418 if (m_selected) 426 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; 427 newmotion.m_serializedPosition = m_serializedPosition;
426 } 428 else
429 {
430 if (m_group != null)
431 newmotion.m_serializedPosition = m_group.AbsolutePosition;
432 else
433 newmotion.m_serializedPosition = m_serializedPosition;
434 }
427 435
428 newmotion.m_currentFrame = m_currentFrame; 436 newmotion.m_currentFrame = m_currentFrame;
429 437
430 newmotion.m_iterations = m_iterations; 438 newmotion.m_iterations = m_iterations;
431 newmotion.m_running = m_running; 439 newmotion.m_running = m_running;
440 }
432 441
433 if (m_running && !m_waitingCrossing) 442 if (m_running && !m_waitingCrossing)
434 StartTimer(); 443 StartTimer();
@@ -458,39 +467,62 @@ namespace OpenSim.Region.Framework.Scenes
458 } 467 }
459 else 468 else
460 { 469 {
461 m_running = false;
462 StopTimer(); 470 StopTimer();
471 m_running = false;
463 } 472 }
464 } 473 }
465 474
466 public void Stop() 475 public void Stop()
467 { 476 {
477 StopTimer();
468 m_running = false; 478 m_running = false;
469 m_isCrossing = false; 479 m_isCrossing = false;
470 m_waitingCrossing = false; 480 m_waitingCrossing = false;
471 481
472 StopTimer();
473
474 m_basePosition = m_group.AbsolutePosition; 482 m_basePosition = m_group.AbsolutePosition;
475 m_baseRotation = m_group.GroupRotation; 483 m_baseRotation = m_group.GroupRotation;
476 484
477 m_group.RootPart.Velocity = Vector3.Zero; 485 m_group.RootPart.Velocity = Vector3.Zero;
478 m_group.RootPart.AngularVelocity = Vector3.Zero; 486 m_group.RootPart.AngularVelocity = Vector3.Zero;
479 m_group.SendGroupRootTerseUpdate(); 487// m_group.SendGroupRootTerseUpdate();
480// m_group.RootPart.ScheduleTerseUpdate(); 488 m_group.RootPart.ScheduleTerseUpdate();
481 m_frames.Clear(); 489 m_frames.Clear();
490 m_group.Scene.EventManager.TriggerMovingEndEvent(m_group.RootPart.LocalId);
482 } 491 }
483 492
484 public void Pause() 493 public void Pause()
485 { 494 {
486 m_running = false;
487 StopTimer(); 495 StopTimer();
496 m_running = false;
488 497
489 m_group.RootPart.Velocity = Vector3.Zero; 498 m_group.RootPart.Velocity = Vector3.Zero;
490 m_group.RootPart.AngularVelocity = Vector3.Zero; 499 m_group.RootPart.AngularVelocity = Vector3.Zero;
491 m_group.SendGroupRootTerseUpdate(); 500 m_skippedUpdates = 1000;
492// m_group.RootPart.ScheduleTerseUpdate(); 501// m_group.SendGroupRootTerseUpdate();
502 m_group.RootPart.ScheduleTerseUpdate();
503 m_group.Scene.EventManager.TriggerMovingEndEvent(m_group.RootPart.LocalId);
504 }
505
506 public void Suspend()
507 {
508 lock (m_frames)
509 {
510 if (m_timerStopped)
511 return;
512 m_timerStopped = true;
513 }
514 }
493 515
516 public void Resume()
517 {
518 lock (m_frames)
519 {
520 if (!m_timerStopped)
521 return;
522 if (m_running && !m_waitingCrossing)
523 StartTimer();
524 m_skippedUpdates = 1000;
525 }
494 } 526 }
495 527
496 private void GetNextList() 528 private void GetNextList()
@@ -581,6 +613,7 @@ namespace OpenSim.Region.Framework.Scenes
581 613
582 pos = (Vector3)k.Position; 614 pos = (Vector3)k.Position;
583 rot = (Quaternion)k.Rotation; 615 rot = (Quaternion)k.Rotation;
616
584 } 617 }
585 618
586 m_basePosition = pos; 619 m_basePosition = pos;
@@ -592,15 +625,47 @@ namespace OpenSim.Region.Framework.Scenes
592 625
593 public void OnTimer(double tickDuration) 626 public void OnTimer(double tickDuration)
594 { 627 {
628 if (!Monitor.TryEnter(m_frames))
629 return;
630 if (m_timerStopped)
631 KeyframeTimer.Remove(this);
632 else
633 DoOnTimer(tickDuration);
634 Monitor.Exit(m_frames);
635 }
636
637 private void Done()
638 {
639 KeyframeTimer.Remove(this);
640 m_timerStopped = true;
641 m_running = false;
642 m_isCrossing = false;
643 m_waitingCrossing = false;
644
645 m_basePosition = m_group.AbsolutePosition;
646 m_baseRotation = m_group.GroupRotation;
647
648 m_group.RootPart.Velocity = Vector3.Zero;
649 m_group.RootPart.AngularVelocity = Vector3.Zero;
650// m_group.SendGroupRootTerseUpdate();
651 m_group.RootPart.ScheduleTerseUpdate();
652 m_frames.Clear();
653 }
654
655 [NonSerialized()] Vector3 m_lastPosUpdate;
656 [NonSerialized()] Quaternion m_lastRotationUpdate;
657 [NonSerialized()] Vector3 m_currentVel;
658 [NonSerialized()] int m_skippedUpdates;
659 [NonSerialized()] double m_lasttickMS;
660
661 private void DoOnTimer(double tickDuration)
662 {
595 if (m_skipLoops > 0) 663 if (m_skipLoops > 0)
596 { 664 {
597 m_skipLoops--; 665 m_skipLoops--;
598 return; 666 return;
599 } 667 }
600 668
601 if (m_timerStopped) // trap events still in air even after a timer.stop
602 return;
603
604 if (m_group == null) 669 if (m_group == null)
605 return; 670 return;
606 671
@@ -611,8 +676,9 @@ namespace OpenSim.Region.Framework.Scenes
611 if (m_group.RootPart.Velocity != Vector3.Zero) 676 if (m_group.RootPart.Velocity != Vector3.Zero)
612 { 677 {
613 m_group.RootPart.Velocity = Vector3.Zero; 678 m_group.RootPart.Velocity = Vector3.Zero;
614 m_group.SendGroupRootTerseUpdate(); 679 m_skippedUpdates = 1000;
615 680// m_group.SendGroupRootTerseUpdate();
681 m_group.RootPart.ScheduleTerseUpdate();
616 } 682 }
617 return; 683 return;
618 } 684 }
@@ -624,7 +690,9 @@ namespace OpenSim.Region.Framework.Scenes
624 // retry to set the position that evtually caused the outbound 690 // retry to set the position that evtually caused the outbound
625 // if still outside region this will call startCrossing below 691 // if still outside region this will call startCrossing below
626 m_isCrossing = false; 692 m_isCrossing = false;
693 m_skippedUpdates = 1000;
627 m_group.AbsolutePosition = m_nextPosition; 694 m_group.AbsolutePosition = m_nextPosition;
695
628 if (!m_isCrossing) 696 if (!m_isCrossing)
629 { 697 {
630 StopTimer(); 698 StopTimer();
@@ -633,43 +701,43 @@ namespace OpenSim.Region.Framework.Scenes
633 return; 701 return;
634 } 702 }
635 703
704 double nowMS = Util.GetTimeStampMS();
705
636 if (m_frames.Count == 0) 706 if (m_frames.Count == 0)
637 { 707 {
638 if (!m_running) return; 708 lock (m_frames)
709 {
710 GetNextList();
639 711
640 GetNextList(); 712 if (m_frames.Count == 0)
713 {
714 Done();
715 m_group.Scene.EventManager.TriggerMovingEndEvent(m_group.RootPart.LocalId);
716 return;
717 }
641 718
642 if (m_frames.Count == 0) 719 m_currentFrame = m_frames[0];
643 {
644 Stop();
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 } 720 }
721 m_nextPosition = m_group.AbsolutePosition;
722 m_currentVel = (Vector3)m_currentFrame.Position - m_nextPosition;
723 m_currentVel /= (m_currentFrame.TimeMS * 0.001f);
659 724
660 m_currentFrame = m_frames[0];
661 m_currentFrame.TimeMS += (int)tickDuration; 725 m_currentFrame.TimeMS += (int)tickDuration;
662 726 m_lasttickMS = nowMS - 50f;
663 //force a update on a keyframe transition
664 update = true; 727 update = true;
665 } 728 }
666 729
667 m_currentFrame.TimeMS -= (int)tickDuration; 730 int elapsed = (int)(nowMS - m_lasttickMS);
731 if( elapsed > 3 * tickDuration)
732 elapsed = (int)tickDuration;
733
734 m_currentFrame.TimeMS -= elapsed;
735 m_lasttickMS = nowMS;
668 736
669 // Do the frame processing 737 // Do the frame processing
670 double remainingSteps = (double)m_currentFrame.TimeMS / tickDuration; 738 double remainingSteps = (double)m_currentFrame.TimeMS / tickDuration;
671 739
672 if (remainingSteps <= 0.0) 740 if (remainingSteps <= 1.0)
673 { 741 {
674 m_group.RootPart.Velocity = Vector3.Zero; 742 m_group.RootPart.Velocity = Vector3.Zero;
675 m_group.RootPart.AngularVelocity = Vector3.Zero; 743 m_group.RootPart.AngularVelocity = Vector3.Zero;
@@ -677,111 +745,99 @@ namespace OpenSim.Region.Framework.Scenes
677 m_nextPosition = (Vector3)m_currentFrame.Position; 745 m_nextPosition = (Vector3)m_currentFrame.Position;
678 m_group.AbsolutePosition = m_nextPosition; 746 m_group.AbsolutePosition = m_nextPosition;
679 747
680 // we are sending imediate updates, no doing force a extra terseUpdate
681 // m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation);
682
683 m_group.RootPart.RotationOffset = (Quaternion)m_currentFrame.Rotation; 748 m_group.RootPart.RotationOffset = (Quaternion)m_currentFrame.Rotation;
684 m_frames.RemoveAt(0);
685 if (m_frames.Count > 0)
686 m_currentFrame = m_frames[0];
687 749
750 lock (m_frames)
751 {
752 m_frames.RemoveAt(0);
753 if (m_frames.Count > 0)
754 {
755 m_currentFrame = m_frames[0];
756 m_currentVel = (Vector3)m_currentFrame.Position - m_nextPosition;
757 m_currentVel /= (m_currentFrame.TimeMS * 0.001f);
758 m_group.RootPart.Velocity = m_currentVel;
759 m_currentFrame.TimeMS += (int)tickDuration;
760 }
761 else
762 m_group.RootPart.Velocity = Vector3.Zero;
763 }
688 update = true; 764 update = true;
689 } 765 }
690 else 766 else
691 { 767 {
692 float completed = ((float)m_currentFrame.TimeTotal - (float)m_currentFrame.TimeMS) / (float)m_currentFrame.TimeTotal; 768// bool lastSteps = remainingSteps < 4;
693 bool lastStep = m_currentFrame.TimeMS <= tickDuration; 769
694 770 Vector3 currentPosition = m_group.AbsolutePosition;
695 Vector3 positionThisStep = m_currentFrame.StartPosition + (m_currentFrame.Position.Value - m_currentFrame.StartPosition) * completed; 771 Vector3 motionThisFrame = (Vector3)m_currentFrame.Position - currentPosition;
696 Vector3 motionThisStep = positionThisStep - m_group.AbsolutePosition; 772 motionThisFrame /= (float)remainingSteps;
697 773
698 float mag = Vector3.Mag(motionThisStep); 774 m_nextPosition = currentPosition + motionThisFrame;
699 775
700 if ((mag >= 0.02f) || lastStep) 776 Quaternion currentRotation = m_group.GroupRotation;
777 if ((Quaternion)m_currentFrame.Rotation != currentRotation)
701 { 778 {
702 m_nextPosition = m_group.AbsolutePosition + motionThisStep; 779 float completed = ((float)m_currentFrame.TimeTotal - (float)m_currentFrame.TimeMS) / (float)m_currentFrame.TimeTotal;
703 m_group.AbsolutePosition = m_nextPosition;
704 update = true;
705 }
706
707 //int totalSteps = m_currentFrame.TimeTotal / (int)tickDuration;
708 //m_log.DebugFormat("KeyframeMotion.OnTimer: step {0}/{1}, curPosition={2}, finalPosition={3}, motionThisStep={4} (scene {5})",
709 // totalSteps - remainingSteps + 1, totalSteps, m_group.AbsolutePosition, m_currentFrame.Position, motionThisStep, m_scene.RegionInfo.RegionName);
710
711 if ((Quaternion)m_currentFrame.Rotation != m_group.GroupRotation)
712 {
713 Quaternion current = m_group.GroupRotation;
714
715 Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, completed); 780 Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, completed);
716 step.Normalize(); 781 step.Normalize();
717/* use simpler change detection 782 m_group.RootPart.RotationOffset = step;
718* float angle = 0; 783/*
719 784 if (Math.Abs(step.X - m_lastRotationUpdate.X) > 0.001f
720 float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W; 785 || Math.Abs(step.Y - m_lastRotationUpdate.Y) > 0.001f
721 float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W; 786 || Math.Abs(step.Z - m_lastRotationUpdate.Z) > 0.001f)
722 float aa_bb = aa * bb;
723
724 if (aa_bb == 0)
725 {
726 angle = 0;
727 }
728 else
729 {
730 float ab = current.X * step.X +
731 current.Y * step.Y +
732 current.Z * step.Z +
733 current.W * step.W;
734 float q = (ab * ab) / aa_bb;
735
736 if (q > 1.0f)
737 {
738 angle = 0;
739 }
740 else
741 {
742 angle = (float)Math.Acos(2 * q - 1);
743 }
744 }
745
746 if (angle > 0.01f)
747*/
748 if(Math.Abs(step.X - current.X) > 0.001f
749 || Math.Abs(step.Y - current.Y) > 0.001f
750 || Math.Abs(step.Z - current.Z) > 0.001f
751 || lastStep)
752 // assuming w is a dependente var
753
754 {
755// m_group.UpdateGroupRotationR(step);
756 m_group.RootPart.RotationOffset = step;
757
758 //m_group.RootPart.UpdateAngularVelocity(m_currentFrame.AngularVelocity / 2);
759 update = true; 787 update = true;
760 } 788*/
761 } 789 }
762 }
763 790
764 if (update) 791 m_group.AbsolutePosition = m_nextPosition;
765 { 792// if(lastSteps)
766 m_group.SendGroupRootTerseUpdate(); 793// m_group.RootPart.Velocity = Vector3.Zero;
794// else
795 m_group.RootPart.Velocity = m_currentVel;
796/*
797 if(!update && (
798// lastSteps ||
799 m_skippedUpdates * tickDuration > 0.5 ||
800 Math.Abs(m_nextPosition.X - currentPosition.X) > 5f ||
801 Math.Abs(m_nextPosition.Y - currentPosition.Y) > 5f ||
802 Math.Abs(m_nextPosition.Z - currentPosition.Z) > 5f
803 ))
804 {
805 update = true;
806 }
807 else
808 m_skippedUpdates++;
809*/
767 } 810 }
811// if(update)
812// {
813// m_lastPosUpdate = m_nextPosition;
814// m_lastRotationUpdate = m_group.GroupRotation;
815// m_skippedUpdates = 0;
816// m_group.SendGroupRootTerseUpdate();
817 m_group.RootPart.ScheduleTerseUpdate();
818// }
768 } 819 }
769 820
770 public Byte[] Serialize() 821 public Byte[] Serialize()
771 { 822 {
823 bool timerWasStopped;
824 lock (m_frames)
825 {
826 timerWasStopped = m_timerStopped;
827 }
772 StopTimer(); 828 StopTimer();
773 829
774 SceneObjectGroup tmp = m_group; 830 SceneObjectGroup tmp = m_group;
775 m_group = null; 831 m_group = null;
776 if (!m_selected && tmp != null)
777 m_serializedPosition = tmp.AbsolutePosition;
778 832
779 using (MemoryStream ms = new MemoryStream()) 833 using (MemoryStream ms = new MemoryStream())
780 { 834 {
781 BinaryFormatter fmt = new BinaryFormatter(); 835 BinaryFormatter fmt = new BinaryFormatter();
836 if (!m_selected && tmp != null)
837 m_serializedPosition = tmp.AbsolutePosition;
782 fmt.Serialize(ms, this); 838 fmt.Serialize(ms, this);
783 m_group = tmp; 839 m_group = tmp;
784 if (m_running && !m_waitingCrossing) 840 if (!timerWasStopped && m_running && !m_waitingCrossing)
785 StartTimer(); 841 StartTimer();
786 842
787 return ms.ToArray(); 843 return ms.ToArray();
@@ -791,10 +847,10 @@ namespace OpenSim.Region.Framework.Scenes
791 public void StartCrossingCheck() 847 public void StartCrossingCheck()
792 { 848 {
793 // timer will be restart by crossingFailure 849 // timer will be restart by crossingFailure
794 // or never since crossing worked and this 850 // or never since crossing worked and this
795 // should be deleted 851 // should be deleted
796 StopTimer(); 852 StopTimer();
797 853
798 m_isCrossing = true; 854 m_isCrossing = true;
799 m_waitingCrossing = true; 855 m_waitingCrossing = true;
800 856
@@ -802,8 +858,9 @@ namespace OpenSim.Region.Framework.Scenes
802 if (m_group.RootPart.Velocity != Vector3.Zero) 858 if (m_group.RootPart.Velocity != Vector3.Zero)
803 { 859 {
804 m_group.RootPart.Velocity = Vector3.Zero; 860 m_group.RootPart.Velocity = Vector3.Zero;
805 m_group.SendGroupRootTerseUpdate(); 861 m_skippedUpdates = 1000;
806// m_group.RootPart.ScheduleTerseUpdate(); 862// m_group.SendGroupRootTerseUpdate();
863 m_group.RootPart.ScheduleTerseUpdate();
807 } 864 }
808 } 865 }
809 866
@@ -814,8 +871,9 @@ namespace OpenSim.Region.Framework.Scenes
814 if (m_group != null) 871 if (m_group != null)
815 { 872 {
816 m_group.RootPart.Velocity = Vector3.Zero; 873 m_group.RootPart.Velocity = Vector3.Zero;
817 m_group.SendGroupRootTerseUpdate(); 874 m_skippedUpdates = 1000;
818// m_group.RootPart.ScheduleTerseUpdate(); 875// m_group.SendGroupRootTerseUpdate();
876 m_group.RootPart.ScheduleTerseUpdate();
819 877
820 if (m_running) 878 if (m_running)
821 { 879 {
diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
index ae85560..53ca849 100644
--- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs
+++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
@@ -35,7 +35,7 @@ using OpenSim.Region.PhysicsModules.SharedBase;
35 35
36/* 36/*
37 * Steps to add a new prioritization policy: 37 * Steps to add a new prioritization policy:
38 * 38 *
39 * - Add a new value to the UpdatePrioritizationSchemes enum. 39 * - Add a new value to the UpdatePrioritizationSchemes enum.
40 * - Specify this new value in the [InterestManagement] section of your 40 * - Specify this new value in the [InterestManagement] section of your
41 * OpenSim.ini. The name in the config file must match the enum value name 41 * OpenSim.ini. The name in the config file must match the enum value name
@@ -59,7 +59,7 @@ namespace OpenSim.Region.Framework.Scenes
59 public class Prioritizer 59 public class Prioritizer
60 { 60 {
61 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 61 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
62 62
63 private Scene m_scene; 63 private Scene m_scene;
64 64
65 public Prioritizer(Scene scene) 65 public Prioritizer(Scene scene)
@@ -91,9 +91,10 @@ namespace OpenSim.Region.Framework.Scenes
91 return 0; 91 return 0;
92 92
93 uint priority; 93 uint priority;
94 94
95 switch (m_scene.UpdatePrioritizationScheme) 95 switch (m_scene.UpdatePrioritizationScheme)
96 { 96 {
97/*
97 case UpdatePrioritizationSchemes.Time: 98 case UpdatePrioritizationSchemes.Time:
98 priority = GetPriorityByTime(client, entity); 99 priority = GetPriorityByTime(client, entity);
99 break; 100 break;
@@ -106,13 +107,16 @@ namespace OpenSim.Region.Framework.Scenes
106 case UpdatePrioritizationSchemes.FrontBack: 107 case UpdatePrioritizationSchemes.FrontBack:
107 priority = GetPriorityByFrontBack(client, entity); 108 priority = GetPriorityByFrontBack(client, entity);
108 break; 109 break;
110*/
111 case UpdatePrioritizationSchemes.SimpleAngularDistance:
112 priority = GetPriorityByAngularDistance(client, entity); // TODO: Reimplement SimpleAngularDistance
113 break;
109 case UpdatePrioritizationSchemes.BestAvatarResponsiveness: 114 case UpdatePrioritizationSchemes.BestAvatarResponsiveness:
115 default:
110 priority = GetPriorityByBestAvatarResponsiveness(client, entity); 116 priority = GetPriorityByBestAvatarResponsiveness(client, entity);
111 break; 117 break;
112 default:
113 throw new InvalidOperationException("UpdatePrioritizationScheme not defined.");
114 } 118 }
115 119
116 return priority; 120 return priority;
117 } 121 }
118 122
@@ -141,7 +145,7 @@ namespace OpenSim.Region.Framework.Scenes
141 145
142 return ComputeDistancePriority(client,entity,false); 146 return ComputeDistancePriority(client,entity,false);
143 } 147 }
144 148
145 private uint GetPriorityByFrontBack(IClientAPI client, ISceneEntity entity) 149 private uint GetPriorityByFrontBack(IClientAPI client, ISceneEntity entity)
146 { 150 {
147 // And anything attached to this avatar gets top priority as well 151 // And anything attached to this avatar gets top priority as well
@@ -157,30 +161,39 @@ namespace OpenSim.Region.Framework.Scenes
157 161
158 private uint GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity) 162 private uint GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity)
159 { 163 {
160 uint pqueue = ComputeDistancePriority(client,entity,true); 164 uint pqueue = 2; // keep compiler happy
161 165
162 ScenePresence presence = m_scene.GetScenePresence(client.AgentId); 166 ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
163 if (presence != null) 167 if (presence != null)
164 { 168 {
165 if (!presence.IsChildAgent) 169 // All avatars other than our own go into pqueue 1
170 if (entity is ScenePresence)
171 return 1;
172
173 if (entity is SceneObjectPart)
166 { 174 {
167 // All avatars other than our own go into pqueue 1 175 SceneObjectGroup sog = ((SceneObjectPart)entity).ParentGroup;
168 if (entity is ScenePresence) 176 // Attachments are high priority,
169 return 1; 177 if (sog.IsAttachment)
178 return 2;
170 179
171 if (entity is SceneObjectPart) 180
181 if(presence.ParentPart != null)
172 { 182 {
173 // Attachments are high priority, 183 if(presence.ParentPart.ParentGroup == sog)
174 if (((SceneObjectPart)entity).ParentGroup.IsAttachment) 184 return 2;
175 return 1;
176
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 } 185 }
186
187 pqueue = ComputeDistancePriority(client, entity, false);
188
189 // Non physical prims are lower priority than physical prims
190 PhysicsActor physActor = sog.RootPart.PhysActor;
191 if (physActor == null || !physActor.IsPhysical)
192 pqueue++;
182 } 193 }
183 } 194 }
195 else
196 pqueue = ComputeDistancePriority(client, entity, false);
184 197
185 return pqueue; 198 return pqueue;
186 } 199 }
@@ -191,7 +204,7 @@ namespace OpenSim.Region.Framework.Scenes
191 ScenePresence presence = m_scene.GetScenePresence(client.AgentId); 204 ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
192 if (presence == null) 205 if (presence == null)
193 { 206 {
194 // this shouldn't happen, it basically means that we are prioritizing 207 // this shouldn't happen, it basically means that we are prioritizing
195 // updates to send to a client that doesn't have a presence in the scene 208 // updates to send to a client that doesn't have a presence in the scene
196 // seems like there's race condition here... 209 // seems like there's race condition here...
197 210
@@ -199,7 +212,7 @@ namespace OpenSim.Region.Framework.Scenes
199 // throw new InvalidOperationException("Prioritization agent not defined"); 212 // throw new InvalidOperationException("Prioritization agent not defined");
200 return PriorityQueue.NumberOfQueues - 1; 213 return PriorityQueue.NumberOfQueues - 1;
201 } 214 }
202 215
203 // Use group position for child prims, since we are putting child prims in 216 // Use group position for child prims, since we are putting child prims in
204 // the same queue with the root of the group, the root prim (which goes into 217 // the same queue with the root of the group, the root prim (which goes into
205 // the queue first) should always be sent first, no need to adjust child prim 218 // the queue first) should always be sent first, no need to adjust child prim
@@ -212,25 +225,43 @@ namespace OpenSim.Region.Framework.Scenes
212 } 225 }
213 226
214 // Use the camera position for local agents and avatar position for remote agents 227 // Use the camera position for local agents and avatar position for remote agents
215 Vector3 presencePos = (presence.IsChildAgent) ? 228 // Why would I want that? They could be camming but I still see them at the
216 presence.AbsolutePosition : 229 // avatar position, so why should I update them as if they were at their
217 presence.CameraPosition; 230 // camera positions? Makes no sense!
231 // TODO: Fix this mess
232 //Vector3 presencePos = (presence.IsChildAgent) ?
233 // presence.AbsolutePosition :
234 // presence.CameraPosition;
235
236 Vector3 presencePos = presence.AbsolutePosition;
218 237
219 // Compute the distance... 238 // Compute the distance...
220 double distance = Vector3.Distance(presencePos, entityPos); 239 double distance = Vector3.Distance(presencePos, entityPos);
221 240
222 // And convert the distance to a priority queue, this computation gives queues 241 // And convert the distance to a priority queue, this computation gives queues
223 // at 10, 20, 40, 80, 160, 320, 640, and 1280m 242 // at 10, 20, 40, 80, 160, 320, 640, and 1280m
224 uint pqueue = PriorityQueue.NumberOfImmediateQueues; 243 uint pqueue = PriorityQueue.NumberOfImmediateQueues + 1; // reserve attachments queue
225 uint queues = PriorityQueue.NumberOfQueues - PriorityQueue.NumberOfImmediateQueues; 244 uint queues = PriorityQueue.NumberOfQueues - PriorityQueue.NumberOfImmediateQueues;
226 245/*
227 for (int i = 0; i < queues - 1; i++) 246 for (int i = 0; i < queues - 1; i++)
228 { 247 {
229 if (distance < 10 * Math.Pow(2.0,i)) 248 if (distance < 30 * Math.Pow(2.0,i))
230 break; 249 break;
231 pqueue++; 250 pqueue++;
232 } 251 }
233 252*/
253 if (distance > 10f)
254 {
255 float tmp = (float)Math.Log((double)distance) * 1.442695f - 3.321928f;
256 // for a map identical to original:
257 // now
258 // 1st constant is 1/(log(2)) (natural log) so we get log2(distance)
259 // 2st constant makes it be log2(distance/10)
260 pqueue += (uint)tmp;
261 if (pqueue > queues - 1)
262 pqueue = queues - 1;
263 }
264
234 // If this is a root agent, then determine front & back 265 // 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 266 // Bump up the priority queue (drop the priority) for any objects behind the avatar
236 if (useFrontBack && ! presence.IsChildAgent) 267 if (useFrontBack && ! presence.IsChildAgent)
@@ -242,12 +273,81 @@ namespace OpenSim.Region.Framework.Scenes
242 // Plane equation 273 // Plane equation
243 float d = -Vector3.Dot(camPosition, camAtAxis); 274 float d = -Vector3.Dot(camPosition, camAtAxis);
244 float p = Vector3.Dot(camAtAxis, entityPos) + d; 275 float p = Vector3.Dot(camAtAxis, entityPos) + d;
245 if (p < 0.0f) 276 if (p < 0.0f)
246 pqueue++; 277 pqueue++;
247 } 278 }
248 279
249 return pqueue; 280 return pqueue;
250 } 281 }
251 282
283 private uint GetPriorityByAngularDistance(IClientAPI client, ISceneEntity entity)
284 {
285 ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
286 if (presence == null)
287 return PriorityQueue.NumberOfQueues - 1;
288
289 uint pqueue = ComputeAngleDistancePriority(presence, entity);
290 return pqueue;
291 }
292
293 private uint ComputeAngleDistancePriority(ScenePresence presence, ISceneEntity entity)
294 {
295 // And convert the distance to a priority queue, this computation gives queues
296 // at 10, 20, 40, 80, 160, 320, 640, and 1280m
297// uint minpqueue = PriorityQueue.NumberOfImmediateQueues;
298 uint maxqueue = PriorityQueue.NumberOfQueues - PriorityQueue.NumberOfImmediateQueues -1;
299// uint pqueue = minpqueue;
300 uint pqueue = PriorityQueue.NumberOfImmediateQueues;
301 float distance;
302
303 Vector3 presencePos = presence.AbsolutePosition;
304 if(entity is ScenePresence)
305 {
306 ScenePresence sp = entity as ScenePresence;
307 distance = Vector3.Distance(presencePos, sp.AbsolutePosition);
308 distance *= 0.5f;
309 }
310 else
311 {
312 SceneObjectGroup group = (entity as SceneObjectPart).ParentGroup;
313 if(presence.ParentPart != null)
314 {
315 if(presence.ParentPart.ParentGroup == group)
316 return pqueue;
317 }
318 if(group.IsAttachment)
319 {
320 if(group.RootPart.LocalId == presence.LocalId)
321 return pqueue;
322 }
323
324 float bradius = group.GetBoundsRadius();
325 Vector3 grppos = group.AbsolutePosition + group.getBoundsCenter();
326 distance = Vector3.Distance(presencePos, grppos);
327 distance -= bradius;
328 distance *= group.getAreaFactor();
329 if(group.IsAttachment)
330 distance *= 0.5f;
331 else if(group.UsesPhysics)
332 distance *= 0.6f;
333 else if(group.GetSittingAvatarsCount() > 0)
334 distance *= 0.5f;
335 }
336
337 if (distance > 10f)
338 {
339 float tmp = (float)Math.Log(distance) * 1.442695f - 3.321928f;
340 // for a map identical to original:
341 // now
342 // 1st constant is 1/(log(2)) (natural log) so we get log2(distance)
343 // 2st constant makes it be log2(distance/10)
344
345 pqueue += (uint)tmp;
346 if (pqueue > maxqueue)
347 pqueue = maxqueue;
348 }
349
350 return pqueue;
351 }
252 } 352 }
253} 353}
diff --git a/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs b/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs
index 3b31281..bf58885 100644
--- a/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs
+++ b/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs
@@ -55,13 +55,13 @@ namespace OpenSim.Region.Framework.Scenes
55 public string localZone = TimeZone.CurrentTimeZone.StandardName; 55 public string localZone = TimeZone.CurrentTimeZone.StandardName;
56 public TimeSpan utcOffset = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now); 56 public TimeSpan utcOffset = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now);
57 57
58 public RegionStatsHandler(RegionInfo region_info) 58 public RegionStatsHandler(RegionInfo region_info)
59 : base("GET", "/" + Util.SHA1Hash(region_info.regionSecret), "RegionStats", "Region Statistics") 59 : base("GET", "/" + Util.SHA1Hash(region_info.regionSecret), "RegionStats", "Region Statistics")
60 { 60 {
61 regionInfo = region_info; 61 regionInfo = region_info;
62 osXStatsURI = Util.SHA1Hash(regionInfo.osSecret); 62 osXStatsURI = Util.SHA1Hash(regionInfo.osSecret);
63 } 63 }
64 64
65 protected override byte[] ProcessRequest( 65 protected override byte[] ProcessRequest(
66 string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 66 string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
67 { 67 {
@@ -72,7 +72,7 @@ namespace OpenSim.Region.Framework.Scenes
72 { 72 {
73 get { return "text/plain"; } 73 get { return "text/plain"; }
74 } 74 }
75 75
76 private string Report() 76 private string Report()
77 { 77 {
78 OSDMap args = new OSDMap(30); 78 OSDMap args = new OSDMap(30);
@@ -83,7 +83,7 @@ namespace OpenSim.Region.Framework.Scenes
83 args["UxTime"] = OSD.FromInteger(Util.ToUnixTime(DateTime.Now)); 83 args["UxTime"] = OSD.FromInteger(Util.ToUnixTime(DateTime.Now));
84 args["Memory"] = OSD.FromReal(Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0)); 84 args["Memory"] = OSD.FromReal(Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0));
85 args["Version"] = OSD.FromString(VersionInfo.Version); 85 args["Version"] = OSD.FromString(VersionInfo.Version);
86 86
87 string strBuffer = ""; 87 string strBuffer = "";
88 strBuffer = OSDParser.SerializeJsonString(args); 88 strBuffer = OSDParser.SerializeJsonString(args);
89 89
diff --git a/OpenSim/Region/Framework/Scenes/SOPMaterial.cs b/OpenSim/Region/Framework/Scenes/SOPMaterial.cs
new file mode 100644
index 0000000..d38ef61
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/SOPMaterial.cs
@@ -0,0 +1,177 @@
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 OpenMetaverse.StructuredData;
32using OpenSim.Framework;
33
34namespace OpenSim.Region.Framework.Scenes
35{
36 public static class SOPMaterialData
37 {
38 public enum SopMaterial : int // redundante and not in use for now
39 {
40 Stone = 0,
41 Metal = 1,
42 Glass = 2,
43 Wood = 3,
44 Flesh = 4,
45 Plastic = 5,
46 Rubber = 6,
47 light = 7 // compatibility with old viewers
48 }
49
50 private struct MaterialData
51 {
52 public float friction;
53 public float bounce;
54 public MaterialData(float f, float b)
55 {
56 friction = f;
57 bounce = b;
58 }
59 }
60
61 private static MaterialData[] m_materialdata = {
62 new MaterialData(0.8f,0.4f), // Stone
63 new MaterialData(0.3f,0.4f), // Metal
64 new MaterialData(0.2f,0.7f), // Glass
65 new MaterialData(0.6f,0.5f), // Wood
66 new MaterialData(0.9f,0.3f), // Flesh
67 new MaterialData(0.4f,0.7f), // Plastic
68 new MaterialData(0.9f,0.95f), // Rubber
69 new MaterialData(0.0f,0.0f) // light ??
70 };
71
72 public static Material MaxMaterial
73 {
74 get { return (Material)(m_materialdata.Length - 1); }
75 }
76
77 public static float friction(Material material)
78 {
79 int indx = (int)material;
80 if (indx < m_materialdata.Length)
81 return (m_materialdata[indx].friction);
82 else
83 return 0;
84 }
85
86 public static float bounce(Material material)
87 {
88 int indx = (int)material;
89 if (indx < m_materialdata.Length)
90 return (m_materialdata[indx].bounce);
91 else
92 return 0;
93 }
94 }
95
96 public class FaceMaterial
97 {
98 public UUID ID;
99 public UUID NormalMapID = UUID.Zero;
100 public float NormalOffsetX = 0.0f;
101 public float NormalOffsetY = 0.0f;
102 public float NormalRepeatX = 1.0f;
103 public float NormalRepeatY = 1.0f;
104 public float NormalRotation = 0.0f;
105
106 public UUID SpecularMapID = UUID.Zero;
107 public float SpecularOffsetX = 0.0f;
108 public float SpecularOffsetY = 0.0f;
109 public float SpecularRepeatX = 1.0f;
110 public float SpecularRepeatY = 1.0f;
111 public float SpecularRotation = 0.0f;
112
113 public Color4 SpecularLightColor = new Color4(255,255,255,255);
114 public Byte SpecularLightExponent = 51;
115 public Byte EnvironmentIntensity = 0;
116 public Byte DiffuseAlphaMode = 1;
117 public Byte AlphaMaskCutoff = 0;
118
119 public FaceMaterial()
120 { }
121
122 public FaceMaterial(UUID pID, OSDMap mat)
123 {
124 ID = pID;
125 if(mat == null)
126 return;
127 float scale = 0.0001f;
128 NormalMapID = mat["NormMap"].AsUUID();
129 NormalOffsetX = scale * (float)mat["NormOffsetX"].AsReal();
130 NormalOffsetY = scale * (float)mat["NormOffsetY"].AsReal();
131 NormalRepeatX = scale * (float)mat["NormRepeatX"].AsReal();
132 NormalRepeatY = scale * (float)mat["NormRepeatY"].AsReal();
133 NormalRotation = scale * (float)mat["NormRotation"].AsReal();
134
135 SpecularMapID = mat["SpecMap"].AsUUID();
136 SpecularOffsetX = scale * (float)mat["SpecOffsetX"].AsReal();
137 SpecularOffsetY = scale * (float)mat["SpecOffsetY"].AsReal();
138 SpecularRepeatX = scale * (float)mat["SpecRepeatX"].AsReal();
139 SpecularRepeatY = scale * (float)mat["SpecRepeatY"].AsReal();
140 SpecularRotation = scale * (float)mat["SpecRotation"].AsReal();
141
142 SpecularLightColor = mat["SpecColor"].AsColor4();
143 SpecularLightExponent = (Byte)mat["SpecExp"].AsUInteger();
144 EnvironmentIntensity = (Byte)mat["EnvIntensity"].AsUInteger();
145 DiffuseAlphaMode = (Byte)mat["DiffuseAlphaMode"].AsUInteger();
146 AlphaMaskCutoff = (Byte)mat["AlphaMaskCutoff"].AsUInteger();
147 }
148
149 public OSDMap toOSD()
150 {
151 OSDMap mat = new OSDMap();
152 float scale = 10000f;
153
154 mat["NormMap"] = NormalMapID;
155 mat["NormOffsetX"] = (int) (scale * NormalOffsetX);
156 mat["NormOffsetY"] = (int) (scale * NormalOffsetY);
157 mat["NormRepeatX"] = (int) (scale * NormalRepeatX);
158 mat["NormRepeatY"] = (int) (scale * NormalRepeatY);
159 mat["NormRotation"] = (int) (scale * NormalRotation);
160
161 mat["SpecMap"] = SpecularMapID;
162 mat["SpecOffsetX"] = (int) (scale * SpecularOffsetX);
163 mat["SpecOffsetY"] = (int) (scale * SpecularOffsetY);
164 mat["SpecRepeatX"] = (int) (scale * SpecularRepeatX);
165 mat["SpecRepeatY"] = (int) (scale * SpecularRepeatY);
166 mat["SpecRotation"] = (int) (scale * SpecularRotation);
167
168 mat["SpecColor"] = SpecularLightColor;
169 mat["SpecExp"] = SpecularLightExponent;
170 mat["EnvIntensity"] = EnvironmentIntensity;
171 mat["DiffuseAlphaMode"] = DiffuseAlphaMode;
172 mat["AlphaMaskCutoff"] = AlphaMaskCutoff;
173
174 return mat;
175 }
176 }
177} \ 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..6683614
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/SOPVehicle.cs
@@ -0,0 +1,803 @@
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.PhysicsModules.SharedBase;
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 public bool CameraDecoupled
410 {
411 get
412 {
413 if((vd.m_flags & VehicleFlag.CAMERA_DECOUPLED) != 0)
414 return true;
415 return false;
416 }
417 }
418
419 private XmlTextWriter writer;
420
421 private void XWint(string name, int i)
422 {
423 writer.WriteElementString(name, i.ToString());
424 }
425
426 private void XWfloat(string name, float f)
427 {
428 writer.WriteElementString(name, f.ToString(Culture.FormatProvider));
429 }
430
431 private void XWVector(string name, Vector3 vec)
432 {
433 writer.WriteStartElement(name);
434 writer.WriteElementString("X", vec.X.ToString(Culture.FormatProvider));
435 writer.WriteElementString("Y", vec.Y.ToString(Culture.FormatProvider));
436 writer.WriteElementString("Z", vec.Z.ToString(Culture.FormatProvider));
437 writer.WriteEndElement();
438 }
439
440 private void XWQuat(string name, Quaternion quat)
441 {
442 writer.WriteStartElement(name);
443 writer.WriteElementString("X", quat.X.ToString(Culture.FormatProvider));
444 writer.WriteElementString("Y", quat.Y.ToString(Culture.FormatProvider));
445 writer.WriteElementString("Z", quat.Z.ToString(Culture.FormatProvider));
446 writer.WriteElementString("W", quat.W.ToString(Culture.FormatProvider));
447 writer.WriteEndElement();
448 }
449
450 public void ToXml2(XmlTextWriter twriter)
451 {
452 writer = twriter;
453 writer.WriteStartElement("Vehicle");
454
455 XWint("TYPE", (int)vd.m_type);
456 XWint("FLAGS", (int)vd.m_flags);
457
458 // Linear properties
459 XWVector("LMDIR", vd.m_linearMotorDirection);
460 XWVector("LMFTIME", vd.m_linearFrictionTimescale);
461 XWfloat("LMDTIME", vd.m_linearMotorDecayTimescale);
462 XWfloat("LMTIME", vd.m_linearMotorTimescale);
463 XWVector("LMOFF", vd.m_linearMotorOffset);
464
465 //Angular properties
466 XWVector("AMDIR", vd.m_angularMotorDirection);
467 XWfloat("AMTIME", vd.m_angularMotorTimescale);
468 XWfloat("AMDTIME", vd.m_angularMotorDecayTimescale);
469 XWVector("AMFTIME", vd.m_angularFrictionTimescale);
470
471 //Deflection properties
472 XWfloat("ADEFF", vd.m_angularDeflectionEfficiency);
473 XWfloat("ADTIME", vd.m_angularDeflectionTimescale);
474 XWfloat("LDEFF", vd.m_linearDeflectionEfficiency);
475 XWfloat("LDTIME", vd.m_linearDeflectionTimescale);
476
477 //Banking properties
478 XWfloat("BEFF", vd.m_bankingEfficiency);
479 XWfloat("BMIX", vd.m_bankingMix);
480 XWfloat("BTIME", vd.m_bankingTimescale);
481
482 //Hover and Buoyancy properties
483 XWfloat("HHEI", vd.m_VhoverHeight);
484 XWfloat("HEFF", vd.m_VhoverEfficiency);
485 XWfloat("HTIME", vd.m_VhoverTimescale);
486 XWfloat("VBUO", vd.m_VehicleBuoyancy);
487
488 //Attractor properties
489 XWfloat("VAEFF", vd.m_verticalAttractionEfficiency);
490 XWfloat("VATIME", vd.m_verticalAttractionTimescale);
491
492 XWQuat("REF_FRAME", vd.m_referenceFrame);
493
494 writer.WriteEndElement();
495 writer = null;
496 }
497
498
499
500 XmlReader reader;
501
502 private int XRint()
503 {
504 return reader.ReadElementContentAsInt();
505 }
506
507 private float XRfloat()
508 {
509 return reader.ReadElementContentAsFloat();
510 }
511
512 public Vector3 XRvector()
513 {
514 Vector3 vec;
515 reader.ReadStartElement();
516 vec.X = reader.ReadElementContentAsFloat();
517 vec.Y = reader.ReadElementContentAsFloat();
518 vec.Z = reader.ReadElementContentAsFloat();
519 reader.ReadEndElement();
520 return vec;
521 }
522
523 public Quaternion XRquat()
524 {
525 Quaternion q;
526 reader.ReadStartElement();
527 q.X = reader.ReadElementContentAsFloat();
528 q.Y = reader.ReadElementContentAsFloat();
529 q.Z = reader.ReadElementContentAsFloat();
530 q.W = reader.ReadElementContentAsFloat();
531 reader.ReadEndElement();
532 return q;
533 }
534
535 public static bool EReadProcessors(
536 Dictionary<string, Action> processors,
537 XmlReader xtr)
538 {
539 bool errors = false;
540
541 string nodeName = string.Empty;
542 while (xtr.NodeType != XmlNodeType.EndElement)
543 {
544 nodeName = xtr.Name;
545
546 // m_log.DebugFormat("[ExternalRepresentationUtils]: Processing: {0}", nodeName);
547
548 Action p = null;
549 if (processors.TryGetValue(xtr.Name, out p))
550 {
551 // m_log.DebugFormat("[ExternalRepresentationUtils]: Found {0} processor, nodeName);
552
553 try
554 {
555 p();
556 }
557 catch
558 {
559 errors = true;
560 if (xtr.NodeType == XmlNodeType.EndElement)
561 xtr.Read();
562 }
563 }
564 else
565 {
566 // m_log.DebugFormat("[LandDataSerializer]: caught unknown element {0}", nodeName);
567 xtr.ReadOuterXml(); // ignore
568 }
569 }
570
571 return errors;
572 }
573
574
575 public string ToXml2()
576 {
577 using (StringWriter sw = new StringWriter())
578 {
579 using (XmlTextWriter xwriter = new XmlTextWriter(sw))
580 {
581 ToXml2(xwriter);
582 }
583
584 return sw.ToString();
585 }
586 }
587
588 public static SOPVehicle FromXml2(string text)
589 {
590 if (text == String.Empty)
591 return null;
592
593 UTF8Encoding enc = new UTF8Encoding();
594 MemoryStream ms = new MemoryStream(enc.GetBytes(text));
595 XmlTextReader xreader = new XmlTextReader(ms);
596 xreader.ProhibitDtd = true;
597
598 SOPVehicle v = new SOPVehicle();
599 bool error;
600
601 v.FromXml2(xreader, out error);
602
603 xreader.Close();
604
605 if (error)
606 {
607 v = null;
608 return null;
609 }
610 return v;
611 }
612
613 public static SOPVehicle FromXml2(XmlReader reader)
614 {
615 SOPVehicle vehicle = new SOPVehicle();
616
617 bool errors = false;
618
619 vehicle.FromXml2(reader, out errors);
620 if (errors)
621 return null;
622
623 return vehicle;
624 }
625
626 private void FromXml2(XmlReader _reader, out bool errors)
627 {
628 errors = false;
629 reader = _reader;
630
631 Dictionary<string, Action> m_VehicleXmlProcessors
632 = new Dictionary<string, Action>();
633
634 m_VehicleXmlProcessors.Add("TYPE", ProcessXR_type);
635 m_VehicleXmlProcessors.Add("FLAGS", ProcessXR_flags);
636
637 // Linear properties
638 m_VehicleXmlProcessors.Add("LMDIR", ProcessXR_linearMotorDirection);
639 m_VehicleXmlProcessors.Add("LMFTIME", ProcessXR_linearFrictionTimescale);
640 m_VehicleXmlProcessors.Add("LMDTIME", ProcessXR_linearMotorDecayTimescale);
641 m_VehicleXmlProcessors.Add("LMTIME", ProcessXR_linearMotorTimescale);
642 m_VehicleXmlProcessors.Add("LMOFF", ProcessXR_linearMotorOffset);
643
644 //Angular properties
645 m_VehicleXmlProcessors.Add("AMDIR", ProcessXR_angularMotorDirection);
646 m_VehicleXmlProcessors.Add("AMTIME", ProcessXR_angularMotorTimescale);
647 m_VehicleXmlProcessors.Add("AMDTIME", ProcessXR_angularMotorDecayTimescale);
648 m_VehicleXmlProcessors.Add("AMFTIME", ProcessXR_angularFrictionTimescale);
649
650 //Deflection properties
651 m_VehicleXmlProcessors.Add("ADEFF", ProcessXR_angularDeflectionEfficiency);
652 m_VehicleXmlProcessors.Add("ADTIME", ProcessXR_angularDeflectionTimescale);
653 m_VehicleXmlProcessors.Add("LDEFF", ProcessXR_linearDeflectionEfficiency);
654 m_VehicleXmlProcessors.Add("LDTIME", ProcessXR_linearDeflectionTimescale);
655
656 //Banking properties
657 m_VehicleXmlProcessors.Add("BEFF", ProcessXR_bankingEfficiency);
658 m_VehicleXmlProcessors.Add("BMIX", ProcessXR_bankingMix);
659 m_VehicleXmlProcessors.Add("BTIME", ProcessXR_bankingTimescale);
660
661 //Hover and Buoyancy properties
662 m_VehicleXmlProcessors.Add("HHEI", ProcessXR_VhoverHeight);
663 m_VehicleXmlProcessors.Add("HEFF", ProcessXR_VhoverEfficiency);
664 m_VehicleXmlProcessors.Add("HTIME", ProcessXR_VhoverTimescale);
665
666 m_VehicleXmlProcessors.Add("VBUO", ProcessXR_VehicleBuoyancy);
667
668 //Attractor properties
669 m_VehicleXmlProcessors.Add("VAEFF", ProcessXR_verticalAttractionEfficiency);
670 m_VehicleXmlProcessors.Add("VATIME", ProcessXR_verticalAttractionTimescale);
671
672 m_VehicleXmlProcessors.Add("REF_FRAME", ProcessXR_referenceFrame);
673
674 vd = new VehicleData();
675
676 reader.ReadStartElement("Vehicle", String.Empty);
677
678 errors = EReadProcessors(
679 m_VehicleXmlProcessors,
680 reader);
681
682 reader.ReadEndElement();
683 reader = null;
684 }
685
686 private void ProcessXR_type()
687 {
688 vd.m_type = (Vehicle)XRint();
689 }
690 private void ProcessXR_flags()
691 {
692 vd.m_flags = (VehicleFlag)XRint();
693 }
694 // Linear properties
695 private void ProcessXR_linearMotorDirection()
696 {
697 vd.m_linearMotorDirection = XRvector();
698 }
699
700 private void ProcessXR_linearFrictionTimescale()
701 {
702 vd.m_linearFrictionTimescale = XRvector();
703 }
704
705 private void ProcessXR_linearMotorDecayTimescale()
706 {
707 vd.m_linearMotorDecayTimescale = XRfloat();
708 }
709 private void ProcessXR_linearMotorTimescale()
710 {
711 vd.m_linearMotorTimescale = XRfloat();
712 }
713 private void ProcessXR_linearMotorOffset()
714 {
715 vd.m_linearMotorOffset = XRvector();
716 }
717
718
719 //Angular properties
720 private void ProcessXR_angularMotorDirection()
721 {
722 vd.m_angularMotorDirection = XRvector();
723 }
724 private void ProcessXR_angularMotorTimescale()
725 {
726 vd.m_angularMotorTimescale = XRfloat();
727 }
728 private void ProcessXR_angularMotorDecayTimescale()
729 {
730 vd.m_angularMotorDecayTimescale = XRfloat();
731 }
732 private void ProcessXR_angularFrictionTimescale()
733 {
734 vd.m_angularFrictionTimescale = XRvector();
735 }
736
737 //Deflection properties
738 private void ProcessXR_angularDeflectionEfficiency()
739 {
740 vd.m_angularDeflectionEfficiency = XRfloat();
741 }
742 private void ProcessXR_angularDeflectionTimescale()
743 {
744 vd.m_angularDeflectionTimescale = XRfloat();
745 }
746 private void ProcessXR_linearDeflectionEfficiency()
747 {
748 vd.m_linearDeflectionEfficiency = XRfloat();
749 }
750 private void ProcessXR_linearDeflectionTimescale()
751 {
752 vd.m_linearDeflectionTimescale = XRfloat();
753 }
754
755 //Banking properties
756 private void ProcessXR_bankingEfficiency()
757 {
758 vd.m_bankingEfficiency = XRfloat();
759 }
760 private void ProcessXR_bankingMix()
761 {
762 vd.m_bankingMix = XRfloat();
763 }
764 private void ProcessXR_bankingTimescale()
765 {
766 vd.m_bankingTimescale = XRfloat();
767 }
768
769 //Hover and Buoyancy properties
770 private void ProcessXR_VhoverHeight()
771 {
772 vd.m_VhoverHeight = XRfloat();
773 }
774 private void ProcessXR_VhoverEfficiency()
775 {
776 vd.m_VhoverEfficiency = XRfloat();
777 }
778 private void ProcessXR_VhoverTimescale()
779 {
780 vd.m_VhoverTimescale = XRfloat();
781 }
782
783 private void ProcessXR_VehicleBuoyancy()
784 {
785 vd.m_VehicleBuoyancy = XRfloat();
786 }
787
788 //Attractor properties
789 private void ProcessXR_verticalAttractionEfficiency()
790 {
791 vd.m_verticalAttractionEfficiency = XRfloat();
792 }
793 private void ProcessXR_verticalAttractionTimescale()
794 {
795 vd.m_verticalAttractionTimescale = XRfloat();
796 }
797
798 private void ProcessXR_referenceFrame()
799 {
800 vd.m_referenceFrame = XRquat();
801 }
802 }
803}
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index e384632..b3303a0 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);
@@ -149,7 +149,7 @@ namespace OpenSim.Region.Framework.Scenes
149 userlevel = 1; 149 userlevel = 1;
150 } 150 }
151 if (trigger) 151 if (trigger)
152 EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, (AssetType)item.AssetType, item.AssetID, item.Name, userlevel); 152 EventManager.TriggerOnNewInventoryItemUploadComplete(item, userlevel);
153 153
154 return true; 154 return true;
155 } 155 }
@@ -164,7 +164,7 @@ namespace OpenSim.Region.Framework.Scenes
164 m_log.DebugFormat( 164 m_log.DebugFormat(
165 "[AGENT INVENTORY]: Found folder {0} type {1} for item {2}", 165 "[AGENT INVENTORY]: Found folder {0} type {1} for item {2}",
166 f.Name, (AssetType)f.Type, item.Name); 166 f.Name, (AssetType)f.Type, item.Name);
167 167
168 item.Folder = f.ID; 168 item.Folder = f.ID;
169 } 169 }
170 else 170 else
@@ -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;
@@ -191,7 +191,7 @@ namespace OpenSim.Region.Framework.Scenes
191 userlevel = 1; 191 userlevel = 1;
192 } 192 }
193 if (trigger) 193 if (trigger)
194 EventManager.TriggerOnNewInventoryItemUploadComplete(item.Owner, (AssetType)item.AssetType, item.AssetID, item.Name, userlevel); 194 EventManager.TriggerOnNewInventoryItemUploadComplete(item, userlevel);
195 195
196 if (originalFolder != UUID.Zero) 196 if (originalFolder != UUID.Zero)
197 { 197 {
@@ -223,8 +223,7 @@ namespace OpenSim.Region.Framework.Scenes
223 223
224 if (core.TryGet<IClientInventory>(out inv)) 224 if (core.TryGet<IClientInventory>(out inv))
225 { 225 {
226 InventoryFolderBase parent = new InventoryFolderBase(f.ParentID, f.Owner); 226 InventoryFolderBase parent = InventoryService.GetFolder(f.Owner, f.ParentID);
227 parent = InventoryService.GetFolder(parent);
228 inv.SendRemoveInventoryItems(new UUID[] { item.ID }); 227 inv.SendRemoveInventoryItems(new UUID[] { item.ID });
229 inv.SendBulkUpdateInventory(new InventoryFolderBase[0], new InventoryItemBase[] { item }); 228 inv.SendBulkUpdateInventory(new InventoryFolderBase[0], new InventoryItemBase[] { item });
230 string message = "The item was placed in folder " + f.Name; 229 string message = "The item was placed in folder " + f.Name;
@@ -338,9 +337,9 @@ namespace OpenSim.Region.Framework.Scenes
338 337
339 // Update item with new asset 338 // Update item with new asset
340 item.AssetID = asset.FullID; 339 item.AssetID = asset.FullID;
341 if (group.UpdateInventoryItem(item)) 340 group.UpdateInventoryItem(item);
342 remoteClient.SendAlertMessage("Script saved"); 341 group.InvalidateEffectivePerms();
343 342
344 part.SendPropertiesToClient(remoteClient); 343 part.SendPropertiesToClient(remoteClient);
345 344
346 // Trigger rerunning of script (use TriggerRezScript event, see RezScript) 345 // Trigger rerunning of script (use TriggerRezScript event, see RezScript)
@@ -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
@@ -413,14 +407,14 @@ namespace OpenSim.Region.Framework.Scenes
413 // inventory. Rut-Roh. Whatever. Make this secure. Yeah. 407 // inventory. Rut-Roh. Whatever. Make this secure. Yeah.
414 // 408 //
415 // Passing something to another avatar or a an object will already 409 // Passing something to another avatar or a an object will already
416 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); 410 InventoryItemBase item = InventoryService.GetItem(remoteClient.AgentId, itemID);
417 item = InventoryService.GetItem(item);
418 411
419 if (item != null) 412 if (item != null)
420 { 413 {
421 if (item.Owner != remoteClient.AgentId) 414 if (item.Owner != remoteClient.AgentId)
422 return; 415 return;
423 416
417 item.Flags = (item.Flags & ~(uint)255) | (itemUpd.Flags & (uint)255);
424 item.Name = itemUpd.Name; 418 item.Name = itemUpd.Name;
425 item.Description = itemUpd.Description; 419 item.Description = itemUpd.Description;
426 420
@@ -526,7 +520,7 @@ namespace OpenSim.Region.Framework.Scenes
526 // needs to be found. If inventory item flags are updated 520 // needs to be found. If inventory item flags are updated
527 // the viewer's notion of the item needs to be refreshed. 521 // the viewer's notion of the item needs to be refreshed.
528 // 522 //
529 // In other situations we cannot send out a bulk update here, since this will cause editing of clothing to start 523 // In other situations we cannot send out a bulk update here, since this will cause editing of clothing to start
530 // failing frequently. Possibly this is a race with a separate transaction that uploads the asset. 524 // failing frequently. Possibly this is a race with a separate transaction that uploads the asset.
531 if (sendUpdate) 525 if (sendUpdate)
532 remoteClient.SendBulkUpdateInventory(item); 526 remoteClient.SendBulkUpdateInventory(item);
@@ -590,8 +584,7 @@ namespace OpenSim.Region.Framework.Scenes
590 return null; 584 return null;
591 } 585 }
592 586
593 InventoryItemBase item = new InventoryItemBase(itemId, senderId); 587 InventoryItemBase item = InventoryService.GetItem(senderId, itemId);
594 item = InventoryService.GetItem(item);
595 588
596 if (item == null) 589 if (item == null)
597 { 590 {
@@ -635,6 +628,7 @@ namespace OpenSim.Region.Framework.Scenes
635 itemCopy.AssetType = item.AssetType; 628 itemCopy.AssetType = item.AssetType;
636 itemCopy.InvType = item.InvType; 629 itemCopy.InvType = item.InvType;
637 itemCopy.Folder = recipientFolderId; 630 itemCopy.Folder = recipientFolderId;
631 itemCopy.Flags = item.Flags;
638 632
639 if (Permissions.PropagatePermissions() && recipient != senderId) 633 if (Permissions.PropagatePermissions() && recipient != senderId)
640 { 634 {
@@ -651,10 +645,11 @@ namespace OpenSim.Region.Framework.Scenes
651 // 645 //
652 // Transfer 646 // Transfer
653 // Copy 647 // Copy
654 // Modufy 648 // Modify
655 uint permsMask = ~ ((uint)PermissionMask.Copy | 649 uint permsMask = ~ ((uint)PermissionMask.Copy |
656 (uint)PermissionMask.Transfer | 650 (uint)PermissionMask.Transfer |
657 (uint)PermissionMask.Modify); 651 (uint)PermissionMask.Modify |
652 (uint)PermissionMask.Export);
658 653
659 // Now, reduce the next perms to the mask bits 654 // Now, reduce the next perms to the mask bits
660 // relevant to the operation 655 // relevant to the operation
@@ -684,18 +679,40 @@ namespace OpenSim.Region.Framework.Scenes
684 (uint)PermissionMask.Move; 679 (uint)PermissionMask.Move;
685 uint ownerPerms = item.CurrentPermissions; 680 uint ownerPerms = item.CurrentPermissions;
686 681
682 // These will be applied to the root prim at next rez.
683 // The legacy slam bit (bit 3) and folded permission (bits 0-2)
684 // are preserved due to the above mangling
685// ownerPerms &= nextPerms;
686
687 // Mask the base permissions. This is a conservative
688 // approach altering only the three main perms
689// basePerms &= nextPerms;
690
691 // Mask out the folded portion of the base mask.
692 // While the owner mask carries the actual folded
693 // permissions, the base mask carries the original
694 // base mask, before masking with the folded perms.
695 // We need this later for rezzing.
696// basePerms &= ~(uint)PermissionMask.FoldedMask;
697// basePerms |= ((basePerms >> 13) & 7) | (((basePerms & (uint)PermissionMask.Export) != 0) ? (uint)PermissionMask.FoldedExport : 0);
698
687 // If this is an object, root prim perms may be more 699 // If this is an object, root prim perms may be more
688 // permissive than folded perms. Use folded perms as 700 // permissive than folded perms. Use folded perms as
689 // a mask 701 // a mask
690 if (item.InvType == (int)InventoryType.Object) 702 uint foldedPerms = (item.CurrentPermissions & (uint)PermissionMask.FoldedMask) << (int)PermissionMask.FoldingShift;
703 if (foldedPerms != 0 && item.InvType == (int)InventoryType.Object)
691 { 704 {
705 foldedPerms |= permsMask;
706
692 bool isRootMod = (item.CurrentPermissions & 707 bool isRootMod = (item.CurrentPermissions &
693 (uint)PermissionMask.Modify) != 0 ? 708 (uint)PermissionMask.Modify) != 0 ?
694 true : false; 709 true : false;
695 710
696 // Mask the owner perms to the folded perms 711 // Mask the owner perms to the folded perms
697 PermissionsUtil.ApplyFoldedPermissions(item.CurrentPermissions, ref ownerPerms); 712 // Note that this is only to satisfy the viewer.
698 PermissionsUtil.ApplyFoldedPermissions(item.CurrentPermissions, ref basePerms); 713 // The effect of this will be reversed on rez.
714 ownerPerms &= foldedPerms;
715 basePerms &= foldedPerms;
699 716
700 // If the root was mod, let the mask reflect that 717 // If the root was mod, let the mask reflect that
701 // We also need to adjust the base here, because 718 // We also need to adjust the base here, because
@@ -708,20 +725,20 @@ namespace OpenSim.Region.Framework.Scenes
708 } 725 }
709 } 726 }
710 727
711 // These will be applied to the root prim at next rez. 728 // move here so nextperms are mandatory
712 // The slam bit (bit 3) and folded permission (bits 0-2)
713 // are preserved due to the above mangling
714 ownerPerms &= nextPerms; 729 ownerPerms &= nextPerms;
715
716 // Mask the base permissions. This is a conservative
717 // approach altering only the three main perms
718 basePerms &= nextPerms; 730 basePerms &= nextPerms;
719 731 basePerms &= ~(uint)PermissionMask.FoldedMask;
732 basePerms |= ((basePerms >> 13) & 7) | (((basePerms & (uint)PermissionMask.Export) != 0) ? (uint)PermissionMask.FoldedExport : 0);
720 // Assign to the actual item. Make sure the slam bit is 733 // Assign to the actual item. Make sure the slam bit is
721 // set, if it wasn't set before. 734 // set, if it wasn't set before.
722 itemCopy.BasePermissions = basePerms; 735 itemCopy.BasePermissions = basePerms;
723 itemCopy.CurrentPermissions = ownerPerms; 736 itemCopy.CurrentPermissions = ownerPerms;
724 itemCopy.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm; 737 itemCopy.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm;
738 // Need to clear the other inventory slam options.
739 // That is so we can handle the case where the recipient
740 // changes the bits in inventory before rezzing
741 itemCopy.Flags &= ~(uint)(InventoryItemFlags.ObjectOverwriteBase | InventoryItemFlags.ObjectOverwriteOwner | InventoryItemFlags.ObjectOverwriteGroup | InventoryItemFlags.ObjectOverwriteEveryone | InventoryItemFlags.ObjectOverwriteNextOwner);
725 742
726 itemCopy.NextPermissions = item.NextPermissions; 743 itemCopy.NextPermissions = item.NextPermissions;
727 744
@@ -742,7 +759,7 @@ namespace OpenSim.Region.Framework.Scenes
742 itemCopy.GroupPermissions = item.GroupPermissions & item.NextPermissions; 759 itemCopy.GroupPermissions = item.GroupPermissions & item.NextPermissions;
743 itemCopy.BasePermissions = item.BasePermissions; 760 itemCopy.BasePermissions = item.BasePermissions;
744 } 761 }
745 762
746 if (itemCopy.Folder == UUID.Zero) 763 if (itemCopy.Folder == UUID.Zero)
747 { 764 {
748 InventoryFolderBase folder = null; 765 InventoryFolderBase folder = null;
@@ -771,9 +788,8 @@ namespace OpenSim.Region.Framework.Scenes
771 788
772 itemCopy.GroupID = UUID.Zero; 789 itemCopy.GroupID = UUID.Zero;
773 itemCopy.GroupOwned = false; 790 itemCopy.GroupOwned = false;
774 itemCopy.Flags = item.Flags; 791 itemCopy.SalePrice = 0; //item.SalePrice;
775 itemCopy.SalePrice = item.SalePrice; 792 itemCopy.SaleType = 0; //item.SaleType;
776 itemCopy.SaleType = item.SaleType;
777 793
778 IInventoryAccessModule invAccess = RequestModuleInterface<IInventoryAccessModule>(); 794 IInventoryAccessModule invAccess = RequestModuleInterface<IInventoryAccessModule>();
779 if (invAccess != null) 795 if (invAccess != null)
@@ -812,7 +828,7 @@ namespace OpenSim.Region.Framework.Scenes
812 UUID recipientId, UUID senderId, UUID folderId, UUID recipientParentFolderId) 828 UUID recipientId, UUID senderId, UUID folderId, UUID recipientParentFolderId)
813 { 829 {
814 //// Retrieve the folder from the sender 830 //// Retrieve the folder from the sender
815 InventoryFolderBase folder = InventoryService.GetFolder(new InventoryFolderBase(folderId, senderId)); 831 InventoryFolderBase folder = InventoryService.GetFolder(senderId, folderId);
816 if (null == folder) 832 if (null == folder)
817 { 833 {
818 m_log.ErrorFormat( 834 m_log.ErrorFormat(
@@ -834,7 +850,7 @@ namespace OpenSim.Region.Framework.Scenes
834 } 850 }
835 851
836 UUID newFolderId = UUID.Random(); 852 UUID newFolderId = UUID.Random();
837 InventoryFolderBase newFolder 853 InventoryFolderBase newFolder
838 = new InventoryFolderBase( 854 = new InventoryFolderBase(
839 newFolderId, folder.Name, recipientId, folder.Type, recipientParentFolderId, folder.Version); 855 newFolderId, folder.Name, recipientId, folder.Type, recipientParentFolderId, folder.Version);
840 InventoryService.AddFolder(newFolder); 856 InventoryService.AddFolder(newFolder);
@@ -873,8 +889,7 @@ namespace OpenSim.Region.Framework.Scenes
873 889
874 if (item == null) 890 if (item == null)
875 { 891 {
876 item = new InventoryItemBase(oldItemID, remoteClient.AgentId); 892 item = InventoryService.GetItem(remoteClient.AgentId, oldItemID);
877 item = InventoryService.GetItem(item);
878 893
879 if (item == null) 894 if (item == null)
880 { 895 {
@@ -889,6 +904,20 @@ namespace OpenSim.Region.Framework.Scenes
889 if (newName == String.Empty) 904 if (newName == String.Empty)
890 newName = item.Name; 905 newName = item.Name;
891 906
907 AssetBase asset = AssetService.Get(item.AssetID.ToString());
908
909 if (asset != null)
910 {
911 if (newName != String.Empty)
912 {
913 asset.Name = newName;
914 }
915 else
916 {
917 newName = item.Name;
918 }
919
920
892 if (remoteClient.AgentId == oldAgentID 921 if (remoteClient.AgentId == oldAgentID
893 || (LibraryService != null 922 || (LibraryService != null
894 && LibraryService.LibraryRootFolder != null 923 && LibraryService.LibraryRootFolder != null
@@ -901,7 +930,7 @@ namespace OpenSim.Region.Framework.Scenes
901 item.NextPermissions, item.GroupPermissions, Util.UnixTimeSinceEpoch(), false); 930 item.NextPermissions, item.GroupPermissions, Util.UnixTimeSinceEpoch(), false);
902 } 931 }
903 else 932 else
904 { 933 {
905 // If item is transfer or permissions are off or calling agent is allowed to copy item owner's inventory item. 934 // If item is transfer or permissions are off or calling agent is allowed to copy item owner's inventory item.
906 if (((item.CurrentPermissions & (uint)PermissionMask.Transfer) != 0) 935 if (((item.CurrentPermissions & (uint)PermissionMask.Transfer) != 0)
907 && (m_permissions.BypassPermissions() 936 && (m_permissions.BypassPermissions()
@@ -915,6 +944,13 @@ namespace OpenSim.Region.Framework.Scenes
915 } 944 }
916 } 945 }
917 } 946 }
947 else
948 {
949 m_log.ErrorFormat(
950 "[AGENT INVENTORY]: Could not copy item {0} since asset {1} could not be found",
951 item.Name, item.AssetID);
952 }
953 }
918 954
919 /// <summary> 955 /// <summary>
920 /// Create a new asset data structure. 956 /// Create a new asset data structure.
@@ -929,6 +965,24 @@ namespace OpenSim.Region.Framework.Scenes
929 } 965 }
930 966
931 /// <summary> 967 /// <summary>
968 /// Move an item within the agent's inventory, and leave a copy (used in making a new outfit)
969 /// </summary>
970 public void MoveInventoryItemsLeaveCopy(IClientAPI remoteClient, List<InventoryItemBase> items, UUID destfolder)
971 {
972 List<InventoryItemBase> moveitems = new List<InventoryItemBase>();
973 foreach (InventoryItemBase b in items)
974 {
975 CopyInventoryItem(remoteClient, 0, remoteClient.AgentId, b.ID, b.Folder, null);
976 InventoryItemBase n = InventoryService.GetItem(b.Owner, b.ID);
977 n.Folder = destfolder;
978 moveitems.Add(n);
979 remoteClient.SendInventoryItemCreateUpdate(n, 0);
980 }
981
982 MoveInventoryItem(remoteClient, moveitems);
983 }
984
985 /// <summary>
932 /// Move an item within the agent's inventory. 986 /// Move an item within the agent's inventory.
933 /// </summary> 987 /// </summary>
934 /// <param name="remoteClient"></param> 988 /// <param name="remoteClient"></param>
@@ -946,32 +1000,6 @@ namespace OpenSim.Region.Framework.Scenes
946 } 1000 }
947 1001
948 /// <summary> 1002 /// <summary>
949 /// Create a new inventory item.
950 /// </summary>
951 /// <param name="remoteClient">Client creating this inventory item.</param>
952 /// <param name="creatorID"></param>
953 /// <param name="creatorData"></param>
954 /// <param name="folderID">UUID of folder in which this item should be placed.</param>
955 /// <param name="name">Item name.</para>
956 /// <param name="description">Item description.</param>
957 /// <param name="flags">Item flags</param>
958 /// <param name="callbackID">Generated by the client.</para>
959 /// <param name="asset">Asset to which this item refers.</param>
960 /// <param name="invType">Type of inventory item.</param>
961 /// <param name="nextOwnerMask">Next owner pemrissions mask.</param>
962 /// <param name="creationDate">Unix timestamp at which this item was created.</param>
963 public void CreateNewInventoryItem(
964 IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID,
965 string name, string description, uint flags, uint callbackID,
966 UUID assetID, sbyte assetType, sbyte invType, uint nextOwnerMask, int creationDate)
967 {
968 CreateNewInventoryItem(
969 remoteClient, creatorID, creatorData, folderID, name, description, flags, callbackID, assetID, assetType, invType,
970 (uint)PermissionMask.All | (uint)PermissionMask.Export, (uint)PermissionMask.All | (uint)PermissionMask.Export, 0, nextOwnerMask, 0,
971 creationDate, true);
972 }
973
974 /// <summary>
975 /// Create a new Inventory Item 1003 /// Create a new Inventory Item
976 /// </summary> 1004 /// </summary>
977 /// <param name="remoteClient">Client creating this inventory item.</param> 1005 /// <param name="remoteClient">Client creating this inventory item.</param>
@@ -990,7 +1018,7 @@ namespace OpenSim.Region.Framework.Scenes
990 /// <param name="nextOwnerMask">Next owner pemrissions mask.</param> 1018 /// <param name="nextOwnerMask">Next owner pemrissions mask.</param>
991 /// <param name="groupMask">Group permissions mask.</param> 1019 /// <param name="groupMask">Group permissions mask.</param>
992 /// <param name="creationDate">Unix timestamp at which this item was created.</param> 1020 /// <param name="creationDate">Unix timestamp at which this item was created.</param>
993 private void CreateNewInventoryItem( 1021 public void CreateNewInventoryItem(
994 IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID, 1022 IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID,
995 string name, string description, uint flags, uint callbackID, UUID assetID, sbyte assetType, sbyte invType, 1023 string name, string description, uint flags, uint callbackID, UUID assetID, sbyte assetType, sbyte invType,
996 uint baseMask, uint currentMask, uint everyoneMask, uint nextOwnerMask, uint groupMask, int creationDate, 1024 uint baseMask, uint currentMask, uint everyoneMask, uint nextOwnerMask, uint groupMask, int creationDate,
@@ -1015,7 +1043,11 @@ namespace OpenSim.Region.Framework.Scenes
1015 item.BasePermissions = baseMask; 1043 item.BasePermissions = baseMask;
1016 item.CreationDate = creationDate; 1044 item.CreationDate = creationDate;
1017 1045
1018 if (AddInventoryItem(item, assetUpload)) 1046 // special AnimationSet case
1047 if (item.InvType == (int)CustomInventoryType.AnimationSet)
1048 AnimationSet.enforceItemPermitions(item,true);
1049
1050 if (AddInventoryItem(item))
1019 { 1051 {
1020 remoteClient.SendInventoryItemCreateUpdate(item, callbackID); 1052 remoteClient.SendInventoryItemCreateUpdate(item, callbackID);
1021 } 1053 }
@@ -1177,13 +1209,14 @@ namespace OpenSim.Region.Framework.Scenes
1177 1209
1178 if (group.GetInventoryItem(localID, itemID) != null) 1210 if (group.GetInventoryItem(localID, itemID) != null)
1179 { 1211 {
1180 if (item.Type == 10) 1212 if (item.Type == (int)InventoryType.LSL)
1181 { 1213 {
1182 part.RemoveScriptEvents(itemID); 1214 part.RemoveScriptEvents(itemID);
1183 EventManager.TriggerRemoveScript(localID, itemID); 1215 part.ParentGroup.AddActiveScriptCount(-1);
1184 } 1216 }
1185 1217
1186 group.RemoveInventoryItem(localID, itemID); 1218 group.RemoveInventoryItem(localID, itemID);
1219 group.InvalidateEffectivePerms();
1187 } 1220 }
1188 1221
1189 part.SendPropertiesToClient(remoteClient); 1222 part.SendPropertiesToClient(remoteClient);
@@ -1228,30 +1261,32 @@ namespace OpenSim.Region.Framework.Scenes
1228 agentItem.InvType = taskItem.InvType; 1261 agentItem.InvType = taskItem.InvType;
1229 agentItem.Flags = taskItem.Flags; 1262 agentItem.Flags = taskItem.Flags;
1230 1263
1264 // The code below isn't OK. It doesn't account for flags being changed
1265 // in the object inventory, so it will break when you do it. That
1266 // is the previous behaviour, so no matter at this moment. However, there is a lot
1267 // TODO: Fix this after the inventory fixer exists and has beenr run
1231 if ((part.OwnerID != destAgent) && Permissions.PropagatePermissions()) 1268 if ((part.OwnerID != destAgent) && Permissions.PropagatePermissions())
1232 { 1269 {
1233 agentItem.BasePermissions = taskItem.BasePermissions & (taskItem.NextPermissions | (uint)PermissionMask.Move); 1270 uint perms = taskItem.BasePermissions & taskItem.NextPermissions;
1234 if (taskItem.InvType == (int)InventoryType.Object) 1271 if (taskItem.InvType == (int)InventoryType.Object)
1235 { 1272 {
1236 // Bake the new base permissions from folded permissions 1273 PermissionsUtil.ApplyFoldedPermissions(taskItem.CurrentPermissions, ref perms );
1237 // The folded perms are in the lowest 3 bits of the current perms 1274 perms = PermissionsUtil.FixAndFoldPermissions(perms);
1238 // We use base permissions here to avoid baking the "Locked" status
1239 // into the item as it is passed.
1240 uint perms = taskItem.BasePermissions & taskItem.NextPermissions;
1241 PermissionsUtil.ApplyFoldedPermissions(taskItem.CurrentPermissions, ref perms);
1242 // Avoid the "lock trap" - move must always be enabled but the above may remove it
1243 // Add it back here.
1244 agentItem.BasePermissions = perms | (uint)PermissionMask.Move;
1245 // Newly given items cannot be "locked" on rez. Make sure by
1246 // setting current equal to base.
1247 } 1275 }
1276 else
1277 perms &= taskItem.CurrentPermissions;
1248 1278
1249 agentItem.CurrentPermissions = agentItem.BasePermissions; 1279 // always unlock
1250 1280 perms |= (uint)PermissionMask.Move;
1281
1282 agentItem.BasePermissions = perms;
1283 agentItem.CurrentPermissions = perms;
1284 agentItem.NextPermissions = perms & taskItem.NextPermissions;
1285 agentItem.EveryOnePermissions = perms & taskItem.EveryonePermissions;
1286 agentItem.GroupPermissions = perms & taskItem.GroupPermissions;
1287
1251 agentItem.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm; 1288 agentItem.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm;
1252 agentItem.NextPermissions = taskItem.NextPermissions; 1289 agentItem.Flags &= ~(uint)(InventoryItemFlags.ObjectOverwriteBase | InventoryItemFlags.ObjectOverwriteOwner | InventoryItemFlags.ObjectOverwriteGroup | InventoryItemFlags.ObjectOverwriteEveryone | InventoryItemFlags.ObjectOverwriteNextOwner);
1253 agentItem.EveryOnePermissions = taskItem.EveryonePermissions & (taskItem.NextPermissions | (uint)PermissionMask.Move);
1254 agentItem.GroupPermissions = taskItem.GroupPermissions & taskItem.NextPermissions;
1255 } 1290 }
1256 else 1291 else
1257 { 1292 {
@@ -1282,7 +1317,7 @@ namespace OpenSim.Region.Framework.Scenes
1282 if (taskItem.Type == (int)AssetType.LSLText) 1317 if (taskItem.Type == (int)AssetType.LSLText)
1283 { 1318 {
1284 part.RemoveScriptEvents(itemId); 1319 part.RemoveScriptEvents(itemId);
1285 EventManager.TriggerRemoveScript(part.LocalId, itemId); 1320 part.ParentGroup.AddActiveScriptCount(-1);
1286 } 1321 }
1287 1322
1288 part.Inventory.RemoveInventoryItem(itemId); 1323 part.Inventory.RemoveInventoryItem(itemId);
@@ -1300,9 +1335,9 @@ namespace OpenSim.Region.Framework.Scenes
1300 public InventoryItemBase MoveTaskInventoryItem(IClientAPI remoteClient, UUID folderId, SceneObjectPart part, UUID itemId, out string message) 1335 public InventoryItemBase MoveTaskInventoryItem(IClientAPI remoteClient, UUID folderId, SceneObjectPart part, UUID itemId, out string message)
1301 { 1336 {
1302 m_log.DebugFormat( 1337 m_log.DebugFormat(
1303 "[PRIM INVENTORY]: Adding item {0} from {1} to folder {2} for {3}", 1338 "[PRIM INVENTORY]: Adding item {0} from {1} to folder {2} for {3}",
1304 itemId, part.Name, folderId, remoteClient.Name); 1339 itemId, part.Name, folderId, remoteClient.Name);
1305 1340
1306 InventoryItemBase agentItem = CreateAgentInventoryItemFromTask(remoteClient.AgentId, part, itemId, out message); 1341 InventoryItemBase agentItem = CreateAgentInventoryItemFromTask(remoteClient.AgentId, part, itemId, out message);
1307 if (agentItem == null) 1342 if (agentItem == null)
1308 return null; 1343 return null;
@@ -1327,6 +1362,10 @@ namespace OpenSim.Region.Framework.Scenes
1327 { 1362 {
1328 SceneObjectPart part = GetSceneObjectPart(primLocalId); 1363 SceneObjectPart part = GetSceneObjectPart(primLocalId);
1329 1364
1365 // Can't move a null item
1366 if (itemId == UUID.Zero)
1367 return;
1368
1330 if (null == part) 1369 if (null == part)
1331 { 1370 {
1332 m_log.WarnFormat( 1371 m_log.WarnFormat(
@@ -1348,24 +1387,12 @@ namespace OpenSim.Region.Framework.Scenes
1348 return; 1387 return;
1349 } 1388 }
1350 1389
1351 if ((taskItem.CurrentPermissions & (uint)PermissionMask.Copy) == 0) 1390 if (!Permissions.CanCopyObjectInventory(itemId, part.UUID, remoteClient.AgentId))
1352 { 1391 return;
1353 // If the item to be moved is no copy, we need to be able to
1354 // edit the prim.
1355 if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId))
1356 return;
1357 }
1358 else
1359 {
1360 // If the item is copiable, then we just need to have perms
1361 // on it. The delete check is a pure rights check
1362 if (!Permissions.CanDeleteObject(part.UUID, remoteClient.AgentId))
1363 return;
1364 }
1365 1392
1366 string message; 1393 string message;
1367 InventoryItemBase item = MoveTaskInventoryItem(remoteClient, folderId, part, itemId, out message); 1394 InventoryItemBase item = MoveTaskInventoryItem(remoteClient, folderId, part, itemId, out message);
1368 1395
1369 if (item == null) 1396 if (item == null)
1370 remoteClient.SendAgentAlertMessage(message, false); 1397 remoteClient.SendAgentAlertMessage(message, false);
1371 } 1398 }
@@ -1437,20 +1464,7 @@ namespace OpenSim.Region.Framework.Scenes
1437 return; 1464 return;
1438 } 1465 }
1439 1466
1440 if (part.OwnerID != destPart.OwnerID) 1467 if(!Permissions.CanDoObjectInvToObjectInv(srcTaskItem, part, destPart))
1441 {
1442 // Source must have transfer permissions
1443 if ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1444 return;
1445
1446 // Object cannot copy items to an object owned by a different owner
1447 // unless llAllowInventoryDrop has been called on the destination
1448 if ((destPart.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0)
1449 return;
1450 }
1451
1452 // 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)
1454 return; 1468 return;
1455 1469
1456 TaskInventoryItem destTaskItem = new TaskInventoryItem(); 1470 TaskInventoryItem destTaskItem = new TaskInventoryItem();
@@ -1493,9 +1507,10 @@ namespace OpenSim.Region.Framework.Scenes
1493 destTaskItem.Type = srcTaskItem.Type; 1507 destTaskItem.Type = srcTaskItem.Type;
1494 1508
1495 destPart.Inventory.AddInventoryItem(destTaskItem, part.OwnerID != destPart.OwnerID); 1509 destPart.Inventory.AddInventoryItem(destTaskItem, part.OwnerID != destPart.OwnerID);
1496
1497 if ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Copy) == 0) 1510 if ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1511 {
1498 part.Inventory.RemoveInventoryItem(itemId); 1512 part.Inventory.RemoveInventoryItem(itemId);
1513 }
1499 1514
1500 ScenePresence avatar; 1515 ScenePresence avatar;
1501 1516
@@ -1507,10 +1522,20 @@ namespace OpenSim.Region.Framework.Scenes
1507 1522
1508 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items) 1523 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items)
1509 { 1524 {
1525
1510 ScenePresence avatar; 1526 ScenePresence avatar;
1511 IClientAPI remoteClient = null; 1527 IClientAPI remoteClient = null;
1512 if (TryGetScenePresence(destID, out avatar)) 1528 if (TryGetScenePresence(destID, out avatar))
1513 remoteClient = avatar.ControllingClient; 1529 remoteClient = avatar.ControllingClient;
1530// ????
1531 SceneObjectPart destPart = GetSceneObjectPart(destID);
1532 if (destPart != null) // Move into a prim
1533 {
1534 foreach(UUID itemID in items)
1535 MoveTaskInventoryItem(destID, host, itemID);
1536 return destID; // Prim folder ID == prim ID
1537 }
1538// /????
1514 1539
1515 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID); 1540 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID);
1516 1541
@@ -1572,8 +1597,7 @@ namespace OpenSim.Region.Framework.Scenes
1572 InventoryCollection contents = InventoryService.GetFolderContent(client.AgentId, folder.ID); 1597 InventoryCollection contents = InventoryService.GetFolderContent(client.AgentId, folder.ID);
1573 1598
1574 // Fetch the folder itself to get its current version 1599 // Fetch the folder itself to get its current version
1575 InventoryFolderBase containingFolder = new InventoryFolderBase(folder.ID, client.AgentId); 1600 InventoryFolderBase containingFolder = InventoryService.GetFolder(client.AgentId, folder.ID);
1576 containingFolder = InventoryService.GetFolder(containingFolder);
1577 1601
1578// m_log.DebugFormat("[AGENT INVENTORY]: Sending inventory folder contents ({0} nodes) for \"{1}\" to {2} {3}", 1602// m_log.DebugFormat("[AGENT INVENTORY]: Sending inventory folder contents ({0} nodes) for \"{1}\" to {2} {3}",
1579// contents.Folders.Count + contents.Items.Count, containingFolder.Name, client.FirstName, client.LastName); 1603// contents.Folders.Count + contents.Items.Count, containingFolder.Name, client.FirstName, client.LastName);
@@ -1587,7 +1611,7 @@ namespace OpenSim.Region.Framework.Scenes
1587 { 1611 {
1588 if (item.AssetType == (int)AssetType.Link) 1612 if (item.AssetType == (int)AssetType.Link)
1589 { 1613 {
1590 InventoryItemBase linkedItem = InventoryService.GetItem(new InventoryItemBase(item.AssetID)); 1614 InventoryItemBase linkedItem = InventoryService.GetItem(client.AgentId, item.AssetID);
1591 1615
1592 // Take care of genuinely broken links where the target doesn't exist 1616 // Take care of genuinely broken links where the target doesn't exist
1593 // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate, 1617 // HACK: Also, don't follow up links that just point to other links. In theory this is legitimate,
@@ -1624,127 +1648,127 @@ namespace OpenSim.Region.Framework.Scenes
1624 uint primLocalID) 1648 uint primLocalID)
1625 { 1649 {
1626 UUID itemID = itemInfo.ItemID; 1650 UUID itemID = itemInfo.ItemID;
1651 if (itemID == UUID.Zero)
1652 {
1653 m_log.ErrorFormat(
1654 "[PRIM INVENTORY]: UpdateTaskInventory called with item ID Zero on update for {1}!",
1655 remoteClient.Name);
1656 return;
1657 }
1627 1658
1628 // Find the prim we're dealing with 1659 // Find the prim we're dealing with
1629 SceneObjectPart part = GetSceneObjectPart(primLocalID); 1660 SceneObjectPart part = GetSceneObjectPart(primLocalID);
1661 if(part == null)
1662 {
1663 m_log.WarnFormat(
1664 "[PRIM INVENTORY]: " +
1665 "Update with item {0} requested of prim {1} for {2} but this prim does not exist",
1666 itemID, primLocalID, remoteClient.Name);
1667 return;
1668 }
1630 1669
1631 if (part != null) 1670 TaskInventoryItem currentItem = part.Inventory.GetInventoryItem(itemID);
1671
1672 if (currentItem == null)
1632 { 1673 {
1633 TaskInventoryItem currentItem = part.Inventory.GetInventoryItem(itemID); 1674 InventoryItemBase item = InventoryService.GetItem(remoteClient.AgentId, itemID);
1634 bool allowInventoryDrop = (part.GetEffectiveObjectFlags()
1635 & (uint)PrimFlags.AllowInventoryDrop) != 0;
1636 1675
1637 // Explicity allow anyone to add to the inventory if the 1676 // if not found Try library
1638 // AllowInventoryDrop flag has been set. Don't however let 1677 if (item == null && LibraryService != null && LibraryService.LibraryRootFolder != null)
1639 // them update an item unless they pass the external checks 1678 item = LibraryService.LibraryRootFolder.FindItem(itemID);
1640 //
1641 if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId)
1642 && (currentItem != null || !allowInventoryDrop))
1643 return;
1644 1679
1645 if (currentItem == null) 1680 if(item == null)
1646 { 1681 {
1647 UUID copyID = UUID.Random(); 1682 m_log.ErrorFormat(
1648 if (itemID != UUID.Zero) 1683 "[PRIM INVENTORY]: Could not find inventory item {0} to update for {1}!",
1649 { 1684 itemID, remoteClient.Name);
1650 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); 1685 return;
1651 item = InventoryService.GetItem(item); 1686 }
1652 1687
1653 // Try library 1688 if (!Permissions.CanDropInObjectInv(item, remoteClient, part))
1654 if (null == item && LibraryService != null && LibraryService.LibraryRootFolder != null) 1689 return;
1655 {
1656 item = LibraryService.LibraryRootFolder.FindItem(itemID);
1657 }
1658 1690
1659 // If we've found the item in the user's inventory or in the library 1691 UUID copyID = UUID.Random();
1660 if (item != null) 1692 bool modrights = Permissions.CanEditObject(part.ParentGroup, remoteClient);
1661 { 1693 part.ParentGroup.AddInventoryItem(remoteClient.AgentId, primLocalID, item, copyID, modrights);
1662 part.ParentGroup.AddInventoryItem(remoteClient.AgentId, primLocalID, item, copyID); 1694 m_log.InfoFormat(
1663//// m_log.InfoFormat( 1695 "[PRIM INVENTORY]: Update with item {0} requested of prim {1} for {2}",
1664//// "[PRIM INVENTORY]: Update with item {0} requested of prim {1} for {2}", 1696 item.Name, primLocalID, remoteClient.Name);
1665//// item.Name, primLocalID, remoteClient.Name); 1697 part.SendPropertiesToClient(remoteClient);
1666 part.SendPropertiesToClient(remoteClient); 1698 if (!Permissions.BypassPermissions())
1667 if (!Permissions.BypassPermissions()) 1699 {
1668 { 1700 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1669 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) 1701 {
1670 { 1702 List<UUID> uuids = new List<UUID>();
1671 List<UUID> uuids = new List<UUID>(); 1703 uuids.Add(itemID);
1672 uuids.Add(itemID); 1704 RemoveInventoryItem(remoteClient, uuids);
1673 RemoveInventoryItem(remoteClient, uuids);
1674 }
1675 }
1676 }
1677 else
1678 {
1679 m_log.ErrorFormat(
1680 "[PRIM INVENTORY]: Could not find inventory item {0} to update for {1}!",
1681 itemID, remoteClient.Name);
1682 }
1683 } 1705 }
1684 } 1706 }
1685 else // Updating existing item with new perms etc 1707 }
1686 { 1708 else // Updating existing item with new perms etc
1709 {
1687// m_log.DebugFormat( 1710// m_log.DebugFormat(
1688// "[PRIM INVENTORY]: Updating item {0} in {1} for UpdateTaskInventory()", 1711// "[PRIM INVENTORY]: Updating item {0} in {1} for UpdateTaskInventory()",
1689// currentItem.Name, part.Name); 1712// currentItem.Name, part.Name);
1690 1713
1691 // Only look for an uploaded updated asset if we are passed a transaction ID. This is only the 1714 if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId))
1692 // case for updates uploded through UDP. Updates uploaded via a capability (e.g. a script update) 1715 return;
1693 // will not pass in a transaction ID in the update message.
1694 if (transactionID != UUID.Zero && AgentTransactionsModule != null)
1695 {
1696 AgentTransactionsModule.HandleTaskItemUpdateFromTransaction(
1697 remoteClient, part, transactionID, currentItem);
1698 1716
1699 if ((InventoryType)itemInfo.InvType == InventoryType.Notecard) 1717 // Only look for an uploaded updated asset if we are passed a transaction ID. This is only the
1700 remoteClient.SendAlertMessage("Notecard saved"); 1718 // case for updates uploded through UDP. Updates uploaded via a capability (e.g. a script update)
1701 else if ((InventoryType)itemInfo.InvType == InventoryType.LSL) 1719 // will not pass in a transaction ID in the update message.
1702 remoteClient.SendAlertMessage("Script saved"); 1720 if (transactionID != UUID.Zero && AgentTransactionsModule != null)
1703 else 1721 {
1704 remoteClient.SendAlertMessage("Item saved"); 1722 AgentTransactionsModule.HandleTaskItemUpdateFromTransaction(
1705 } 1723 remoteClient, part, transactionID, currentItem);
1724
1725// if ((InventoryType)itemInfo.InvType == InventoryType.Notecard)
1726// remoteClient.SendAgentAlertMessage("Notecard saved", false);
1727// else if ((InventoryType)itemInfo.InvType == InventoryType.LSL)
1728// remoteClient.SendAgentAlertMessage("Script saved", false);
1729// else
1730// remoteClient.SendAgentAlertMessage("Item saved", false);
1731 }
1706 1732
1707 // Base ALWAYS has move 1733 // Base ALWAYS has move
1708 currentItem.BasePermissions |= (uint)PermissionMask.Move; 1734 currentItem.BasePermissions |= (uint)PermissionMask.Move;
1709 1735
1710 itemInfo.Flags = currentItem.Flags; 1736 itemInfo.Flags = currentItem.Flags;
1711 1737
1712 // Check if we're allowed to mess with permissions 1738 // Check if we're allowed to mess with permissions
1713 if (!Permissions.IsGod(remoteClient.AgentId)) // Not a god 1739 if (!Permissions.IsGod(remoteClient.AgentId)) // Not a god
1740 {
1741 bool noChange;
1742 if (remoteClient.AgentId != part.OwnerID) // Not owner
1714 { 1743 {
1715 if (remoteClient.AgentId != part.OwnerID) // Not owner 1744 noChange = true;
1716 { 1745 if(itemInfo.OwnerID == UUID.Zero && itemInfo.GroupID != UUID.Zero)
1717 // Friends and group members can't change any perms
1718 itemInfo.BasePermissions = currentItem.BasePermissions;
1719 itemInfo.EveryonePermissions = currentItem.EveryonePermissions;
1720 itemInfo.GroupPermissions = currentItem.GroupPermissions;
1721 itemInfo.NextPermissions = currentItem.NextPermissions;
1722 itemInfo.CurrentPermissions = currentItem.CurrentPermissions;
1723 }
1724 else
1725 { 1746 {
1726 // Owner can't change base, and can change other 1747 if(remoteClient.IsGroupMember(itemInfo.GroupID))
1727 // only up to base 1748 {
1728 itemInfo.BasePermissions = currentItem.BasePermissions; 1749 ulong powers = remoteClient.GetGroupPowers(itemInfo.GroupID);
1729 if (itemInfo.EveryonePermissions != currentItem.EveryonePermissions) 1750 if((powers & (ulong)GroupPowers.ObjectManipulate) != 0)
1730 itemInfo.Flags |= (uint)InventoryItemFlags.ObjectOverwriteEveryone; 1751 noChange = false;
1731 if (itemInfo.GroupPermissions != currentItem.GroupPermissions) 1752 }
1732 itemInfo.Flags |= (uint)InventoryItemFlags.ObjectOverwriteGroup;
1733 if (itemInfo.CurrentPermissions != currentItem.CurrentPermissions)
1734 itemInfo.Flags |= (uint)InventoryItemFlags.ObjectOverwriteOwner;
1735 if (itemInfo.NextPermissions != currentItem.NextPermissions)
1736 itemInfo.Flags |= (uint)InventoryItemFlags.ObjectOverwriteNextOwner;
1737 itemInfo.EveryonePermissions &= currentItem.BasePermissions;
1738 itemInfo.GroupPermissions &= currentItem.BasePermissions;
1739 itemInfo.CurrentPermissions &= currentItem.BasePermissions;
1740 itemInfo.NextPermissions &= currentItem.BasePermissions;
1741 } 1753 }
1754 }
1755 else
1756 noChange = false;
1742 1757
1758 if(noChange)
1759 {
1760 // Friends and group members can't change any perms
1761 itemInfo.BasePermissions = currentItem.BasePermissions;
1762 itemInfo.EveryonePermissions = currentItem.EveryonePermissions;
1763 itemInfo.GroupPermissions = currentItem.GroupPermissions;
1764 itemInfo.NextPermissions = currentItem.NextPermissions;
1765 itemInfo.CurrentPermissions = currentItem.CurrentPermissions;
1743 } 1766 }
1744 else 1767 else
1745 { 1768 {
1746 if (itemInfo.BasePermissions != currentItem.BasePermissions) 1769 // Owner can't change base, and can change other
1747 itemInfo.Flags |= (uint)InventoryItemFlags.ObjectOverwriteBase; 1770 // only up to base
1771 itemInfo.BasePermissions = currentItem.BasePermissions;
1748 if (itemInfo.EveryonePermissions != currentItem.EveryonePermissions) 1772 if (itemInfo.EveryonePermissions != currentItem.EveryonePermissions)
1749 itemInfo.Flags |= (uint)InventoryItemFlags.ObjectOverwriteEveryone; 1773 itemInfo.Flags |= (uint)InventoryItemFlags.ObjectOverwriteEveryone;
1750 if (itemInfo.GroupPermissions != currentItem.GroupPermissions) 1774 if (itemInfo.GroupPermissions != currentItem.GroupPermissions)
@@ -1753,24 +1777,34 @@ namespace OpenSim.Region.Framework.Scenes
1753 itemInfo.Flags |= (uint)InventoryItemFlags.ObjectOverwriteOwner; 1777 itemInfo.Flags |= (uint)InventoryItemFlags.ObjectOverwriteOwner;
1754 if (itemInfo.NextPermissions != currentItem.NextPermissions) 1778 if (itemInfo.NextPermissions != currentItem.NextPermissions)
1755 itemInfo.Flags |= (uint)InventoryItemFlags.ObjectOverwriteNextOwner; 1779 itemInfo.Flags |= (uint)InventoryItemFlags.ObjectOverwriteNextOwner;
1780 itemInfo.EveryonePermissions &= currentItem.BasePermissions;
1781 itemInfo.GroupPermissions &= currentItem.BasePermissions;
1782 itemInfo.CurrentPermissions &= currentItem.BasePermissions;
1783 itemInfo.NextPermissions &= currentItem.BasePermissions;
1756 } 1784 }
1785 }
1786 else
1787 {
1788 if (itemInfo.BasePermissions != currentItem.BasePermissions)
1789 itemInfo.Flags |= (uint)InventoryItemFlags.ObjectOverwriteBase;
1790 if (itemInfo.EveryonePermissions != currentItem.EveryonePermissions)
1791 itemInfo.Flags |= (uint)InventoryItemFlags.ObjectOverwriteEveryone;
1792 if (itemInfo.GroupPermissions != currentItem.GroupPermissions)
1793 itemInfo.Flags |= (uint)InventoryItemFlags.ObjectOverwriteGroup;
1794 if (itemInfo.CurrentPermissions != currentItem.CurrentPermissions)
1795 itemInfo.Flags |= (uint)InventoryItemFlags.ObjectOverwriteOwner;
1796 if (itemInfo.NextPermissions != currentItem.NextPermissions)
1797 itemInfo.Flags |= (uint)InventoryItemFlags.ObjectOverwriteNextOwner;
1798 }
1757 1799
1758 // Next ALWAYS has move 1800 // Next ALWAYS has move
1759 itemInfo.NextPermissions |= (uint)PermissionMask.Move; 1801 itemInfo.NextPermissions |= (uint)PermissionMask.Move;
1760 1802
1761 if (part.Inventory.UpdateInventoryItem(itemInfo)) 1803 if (part.Inventory.UpdateInventoryItem(itemInfo))
1762 { 1804 {
1763 part.SendPropertiesToClient(remoteClient); 1805 part.SendPropertiesToClient(remoteClient);
1764 }
1765 } 1806 }
1766 } 1807 }
1767 else
1768 {
1769 m_log.WarnFormat(
1770 "[PRIM INVENTORY]: " +
1771 "Update with item {0} requested of prim {1} for {2} but this prim does not exist",
1772 itemID, primLocalID, remoteClient.Name);
1773 }
1774 } 1808 }
1775 1809
1776 /// <summary> 1810 /// <summary>
@@ -1803,8 +1837,7 @@ namespace OpenSim.Region.Framework.Scenes
1803 public SceneObjectPart RezScriptFromAgentInventory(UUID agentID, UUID fromItemID, uint localID) 1837 public SceneObjectPart RezScriptFromAgentInventory(UUID agentID, UUID fromItemID, uint localID)
1804 { 1838 {
1805 UUID copyID = UUID.Random(); 1839 UUID copyID = UUID.Random();
1806 InventoryItemBase item = new InventoryItemBase(fromItemID, agentID); 1840 InventoryItemBase item = InventoryService.GetItem(agentID, fromItemID);
1807 item = InventoryService.GetItem(item);
1808 1841
1809 // Try library 1842 // Try library
1810 // XXX clumsy, possibly should be one call 1843 // XXX clumsy, possibly should be one call
@@ -1898,12 +1931,12 @@ namespace OpenSim.Region.Framework.Scenes
1898 return null; 1931 return null;
1899 } 1932 }
1900 1933
1901 AssetBase asset 1934 AssetBase asset
1902 = CreateAsset( 1935 = CreateAsset(
1903 itemBase.Name, 1936 itemBase.Name,
1904 itemBase.Description, 1937 itemBase.Description,
1905 (sbyte)itemBase.AssetType, 1938 (sbyte)itemBase.AssetType,
1906 Encoding.ASCII.GetBytes(scriptText), 1939 Encoding.ASCII.GetBytes(scriptText),
1907 agentID); 1940 agentID);
1908 1941
1909 AssetService.Store(asset); 1942 AssetService.Store(asset);
@@ -1934,6 +1967,8 @@ namespace OpenSim.Region.Framework.Scenes
1934 part.Inventory.AddInventoryItem(taskItem, false); 1967 part.Inventory.AddInventoryItem(taskItem, false);
1935 part.Inventory.CreateScriptInstance(taskItem, 0, false, DefaultScriptEngine, 0); 1968 part.Inventory.CreateScriptInstance(taskItem, 0, false, DefaultScriptEngine, 0);
1936 1969
1970 part.ParentGroup.InvalidateEffectivePerms();
1971
1937 // tell anyone managing scripts that a new script exists 1972 // tell anyone managing scripts that a new script exists
1938 EventManager.TriggerNewScript(agentID, part, taskItem.ItemID); 1973 EventManager.TriggerNewScript(agentID, part, taskItem.ItemID);
1939 1974
@@ -1982,8 +2017,8 @@ namespace OpenSim.Region.Framework.Scenes
1982 if ((destPart.GroupID == UUID.Zero) || (destPart.GroupID != srcPart.GroupID) || 2017 if ((destPart.GroupID == UUID.Zero) || (destPart.GroupID != srcPart.GroupID) ||
1983 ((destPart.GroupMask & (uint)PermissionMask.Modify) == 0)) 2018 ((destPart.GroupMask & (uint)PermissionMask.Modify) == 0))
1984 return; 2019 return;
1985 } 2020 }
1986 else 2021 else
1987 { 2022 {
1988 if ((destPart.OwnerMask & (uint)PermissionMask.Modify) == 0) 2023 if ((destPart.OwnerMask & (uint)PermissionMask.Modify) == 0)
1989 return; 2024 return;
@@ -2069,12 +2104,20 @@ namespace OpenSim.Region.Framework.Scenes
2069 /// <param name='action'>DeRezAction</param> 2104 /// <param name='action'>DeRezAction</param>
2070 /// <param name='destinationID'>User folder ID to place derezzed object</param> 2105 /// <param name='destinationID'>User folder ID to place derezzed object</param>
2071 public virtual void DeRezObjects( 2106 public virtual void DeRezObjects(
2072 IClientAPI remoteClient, List<uint> localIDs, UUID groupID, DeRezAction action, UUID destinationID) 2107 IClientAPI remoteClient, List<uint> localIDs, UUID groupID, DeRezAction action, UUID destinationID, bool AddToReturns = true)
2073 { 2108 {
2074 // First, see of we can perform the requested action and 2109 // First, see of we can perform the requested action and
2075 // build a list of eligible objects 2110 // build a list of eligible objects
2076 List<uint> deleteIDs = new List<uint>(); 2111 List<uint> deleteIDs = new List<uint>();
2077 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>(); 2112 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>();
2113 List<SceneObjectGroup> takeGroups = new List<SceneObjectGroup>();
2114 List<SceneObjectGroup> takeDeleteGroups = new List<SceneObjectGroup>();
2115
2116 ScenePresence sp = null;
2117 if(remoteClient != null)
2118 sp = remoteClient.SceneAgent as ScenePresence;
2119 else if(action != DeRezAction.Return)
2120 return; // only Return can be called without a client
2078 2121
2079 // Start with true for both, then remove the flags if objects 2122 // Start with true for both, then remove the flags if objects
2080 // that we can't derez are part of the selection 2123 // that we can't derez are part of the selection
@@ -2087,20 +2130,27 @@ namespace OpenSim.Region.Framework.Scenes
2087 // Invalid id 2130 // Invalid id
2088 SceneObjectPart part = GetSceneObjectPart(localID); 2131 SceneObjectPart part = GetSceneObjectPart(localID);
2089 if (part == null) 2132 if (part == null)
2133 {
2134 //Client still thinks the object exists, kill it
2135 deleteIDs.Add(localID);
2090 continue; 2136 continue;
2137 }
2091 2138
2092 // Already deleted by someone else 2139 // Already deleted by someone else
2093 if (part.ParentGroup.IsDeleted) 2140 if (part.ParentGroup.IsDeleted)
2141 {
2142 //Client still thinks the object exists, kill it
2143 deleteIDs.Add(localID);
2094 continue; 2144 continue;
2145 }
2095 2146
2096 // Can't delete child prims 2147 // Can't delete child prims
2097 if (part != part.ParentGroup.RootPart) 2148 if (part != part.ParentGroup.RootPart)
2098 continue; 2149 continue;
2099 2150
2100 SceneObjectGroup grp = part.ParentGroup; 2151 SceneObjectGroup grp = part.ParentGroup;
2101 2152 if (grp.IsAttachment)
2102 deleteIDs.Add(localID); 2153 continue;
2103 deleteGroups.Add(grp);
2104 2154
2105 // If child prims have invalid perms, fix them 2155 // If child prims have invalid perms, fix them
2106 grp.AdjustChildPrimPermissions(false); 2156 grp.AdjustChildPrimPermissions(false);
@@ -2112,7 +2162,7 @@ namespace OpenSim.Region.Framework.Scenes
2112 if (action != DeRezAction.Return) 2162 if (action != DeRezAction.Return)
2113 { 2163 {
2114 m_log.WarnFormat( 2164 m_log.WarnFormat(
2115 "[AGENT INVENTORY]: Ignoring attempt to {0} {1} {2} without a client", 2165 "[AGENT INVENTORY]: Ignoring attempt to {0} {1} {2} without a client",
2116 action, grp.Name, grp.UUID); 2166 action, grp.Name, grp.UUID);
2117 return; 2167 return;
2118 } 2168 }
@@ -2121,87 +2171,190 @@ namespace OpenSim.Region.Framework.Scenes
2121 } 2171 }
2122 else 2172 else
2123 { 2173 {
2124 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) 2174 if (action == DeRezAction.TakeCopy)
2175 {
2176 if (!Permissions.CanTakeCopyObject(grp, sp))
2177 permissionToTakeCopy = false;
2178 }
2179 else
2180 {
2125 permissionToTakeCopy = false; 2181 permissionToTakeCopy = false;
2126 2182 }
2127 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) 2183 if (!Permissions.CanTakeObject(grp, sp))
2128 permissionToTake = false; 2184 permissionToTake = false;
2129 2185
2130 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) 2186 if (!Permissions.CanDeleteObject(grp, remoteClient))
2131 permissionToDelete = false; 2187 permissionToDelete = false;
2132 } 2188 }
2133 }
2134 2189
2135 // Handle god perms 2190 // Handle god perms
2136 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId)) 2191 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 { 2192 {
2157 remoteClient.SendAlertMessage("You don't have permission to take the object"); 2193 permissionToTake = true;
2158 return; 2194 permissionToTakeCopy = true;
2195 permissionToDelete = true;
2159 } 2196 }
2160 2197
2161 permissionToTake = true; 2198 // If we're re-saving, we don't even want to delete
2162 // Don't delete 2199 if (action == DeRezAction.SaveToExistingUserInventoryItem)
2163 permissionToDelete = false; 2200 permissionToDelete = false;
2164 }
2165 2201
2166 if (action == DeRezAction.Return) 2202 // if we want to take a copy, we also don't want to delete
2167 { 2203 // Note: after this point, the permissionToTakeCopy flag
2168 if (remoteClient != null) 2204 // becomes irrelevant. It already includes the permissionToTake
2205 // permission and after excluding no copy items here, we can
2206 // just use that.
2207 if (action == DeRezAction.TakeCopy)
2169 { 2208 {
2170 if (Permissions.CanReturnObjects( 2209 // If we don't have permission, stop right here
2171 null, 2210 if (!permissionToTakeCopy)
2172 remoteClient.AgentId,
2173 deleteGroups))
2174 { 2211 {
2175 permissionToTake = true; 2212 remoteClient.SendAlertMessage("You don't have permission to take the object");
2176 permissionToDelete = true; 2213 return;
2214 }
2215
2216 permissionToTake = true;
2217 // Don't delete
2218 permissionToDelete = false;
2219 }
2177 2220
2178 foreach (SceneObjectGroup g in deleteGroups) 2221 if (action == DeRezAction.Return)
2222 {
2223 if (remoteClient != null)
2224 {
2225 if (Permissions.CanReturnObjects(
2226 null,
2227 remoteClient,
2228 new List<SceneObjectGroup>() {grp}))
2179 { 2229 {
2180 AddReturn(g.OwnerID == g.GroupID ? g.LastOwnerID : g.OwnerID, g.Name, g.AbsolutePosition, "parcel owner return"); 2230 permissionToTake = true;
2231 permissionToDelete = true;
2232 if(AddToReturns)
2233 AddReturn(grp.OwnerID == grp.GroupID ? grp.LastOwnerID : grp.OwnerID, grp.Name, grp.AbsolutePosition,
2234 "parcel owner return");
2181 } 2235 }
2182 } 2236 }
2237 else // Auto return passes through here with null agent
2238 {
2239 permissionToTake = true;
2240 permissionToDelete = true;
2241 }
2183 } 2242 }
2184 else // Auto return passes through here with null agent 2243
2244 if (permissionToDelete)
2185 { 2245 {
2186 permissionToTake = true; 2246 if (permissionToTake)
2187 permissionToDelete = true; 2247 takeDeleteGroups.Add(grp);
2248 else
2249 deleteGroups.Add(grp);
2250 deleteIDs.Add(grp.LocalId);
2188 } 2251 }
2252 else if(permissionToTake)
2253 takeGroups.Add(grp);
2189 } 2254 }
2190 2255
2191 // OK, we're done with permissions. Let's check if any part of the code prevents the objects from being deleted 2256 SendKillObject(deleteIDs);
2192 bool canDelete = EventManager.TriggerDeRezRequested(remoteClient, deleteGroups, action);
2193 2257
2194 if (permissionToTake && (action != DeRezAction.Delete || this.m_useTrashOnDelete)) 2258 if (takeDeleteGroups.Count > 0)
2259 {
2260 m_asyncSceneObjectDeleter.DeleteToInventory(
2261 action, destinationID, takeDeleteGroups, remoteClient,
2262 true);
2263 }
2264 if (takeGroups.Count > 0)
2195 { 2265 {
2196 m_asyncSceneObjectDeleter.DeleteToInventory( 2266 m_asyncSceneObjectDeleter.DeleteToInventory(
2197 action, destinationID, deleteGroups, remoteClient, 2267 action, destinationID, takeGroups, remoteClient,
2198 permissionToDelete && canDelete); 2268 false);
2199 } 2269 }
2200 else if (permissionToDelete && canDelete) 2270 if (deleteGroups.Count > 0)
2201 { 2271 {
2202 foreach (SceneObjectGroup g in deleteGroups) 2272 foreach (SceneObjectGroup g in deleteGroups)
2203 DeleteSceneObject(g, false); 2273 DeleteSceneObject(g, true);
2274 }
2275 }
2276
2277 public UUID attachObjectAssetStore(IClientAPI remoteClient, SceneObjectGroup grp, UUID AgentId, out UUID itemID)
2278 {
2279 itemID = UUID.Zero;
2280 if (grp != null)
2281 {
2282 Vector3 inventoryStoredPosition = new Vector3(
2283 Math.Min(grp.AbsolutePosition.X, RegionInfo.RegionSizeX - 6),
2284 Math.Min(grp.AbsolutePosition.Y, RegionInfo.RegionSizeY - 6),
2285 grp.AbsolutePosition.Z);
2286
2287 Vector3 originalPosition = grp.AbsolutePosition;
2288
2289 grp.AbsolutePosition = inventoryStoredPosition;
2290
2291 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp);
2292
2293 grp.AbsolutePosition = originalPosition;
2294
2295 AssetBase asset = CreateAsset(
2296 grp.GetPartName(grp.LocalId),
2297 grp.GetPartDescription(grp.LocalId),
2298 (sbyte)AssetType.Object,
2299 Utils.StringToBytes(sceneObjectXml),
2300 remoteClient.AgentId);
2301 AssetService.Store(asset);
2302
2303 InventoryItemBase item = new InventoryItemBase();
2304 item.CreatorId = grp.RootPart.CreatorID.ToString();
2305 item.CreatorData = grp.RootPart.CreatorData;
2306 item.Owner = remoteClient.AgentId;
2307 item.ID = UUID.Random();
2308 item.AssetID = asset.FullID;
2309 item.Description = asset.Description;
2310 item.Name = asset.Name;
2311 item.AssetType = asset.Type;
2312 item.InvType = (int)InventoryType.Object;
2313
2314 InventoryFolderBase folder = InventoryService.GetFolderForType(remoteClient.AgentId, FolderType.Object);
2315 if (folder != null)
2316 item.Folder = folder.ID;
2317 else // oopsies
2318 item.Folder = UUID.Zero;
2319
2320 // Set up base perms properly
2321 uint permsBase = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify);
2322 permsBase &= grp.RootPart.BaseMask;
2323 permsBase |= (uint)PermissionMask.Move;
2324
2325 // Make sure we don't lock it
2326 grp.RootPart.NextOwnerMask |= (uint)PermissionMask.Move;
2327
2328 if ((remoteClient.AgentId != grp.RootPart.OwnerID) && Permissions.PropagatePermissions())
2329 {
2330 item.BasePermissions = permsBase & grp.RootPart.NextOwnerMask;
2331 item.CurrentPermissions = permsBase & grp.RootPart.NextOwnerMask;
2332 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
2333 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask;
2334 item.GroupPermissions = permsBase & grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask;
2335 }
2336 else
2337 {
2338 item.BasePermissions = permsBase;
2339 item.CurrentPermissions = permsBase & grp.RootPart.OwnerMask;
2340 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
2341 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask;
2342 item.GroupPermissions = permsBase & grp.RootPart.GroupMask;
2343 }
2344 item.CreationDate = Util.UnixTimeSinceEpoch();
2345
2346 // sets itemID so client can show item as 'attached' in inventory
2347 grp.FromItemID = item.ID;
2348
2349 if (AddInventoryItem(item))
2350 remoteClient.SendInventoryItemCreateUpdate(item, 0);
2351 else
2352 m_dialogModule.SendAlertToUser(remoteClient, "Operation failed");
2353
2354 itemID = item.ID;
2355 return item.AssetID;
2204 } 2356 }
2357 return UUID.Zero;
2205 } 2358 }
2206 2359
2207 /// <summary> 2360 /// <summary>
@@ -2236,7 +2389,7 @@ namespace OpenSim.Region.Framework.Scenes
2236 { 2389 {
2237 using (XmlTextReader wrappedReader = new XmlTextReader(xmlData, XmlNodeType.Element, null)) 2390 using (XmlTextReader wrappedReader = new XmlTextReader(xmlData, XmlNodeType.Element, null))
2238 { 2391 {
2239 using (XmlReader reader = XmlReader.Create(wrappedReader, new XmlReaderSettings() { IgnoreWhitespace = true, ConformanceLevel = ConformanceLevel.Fragment })) 2392 using (XmlReader reader = XmlReader.Create(wrappedReader, new XmlReaderSettings() { IgnoreWhitespace = true, ConformanceLevel = ConformanceLevel.Fragment, ProhibitDtd = true }))
2240 { 2393 {
2241 reader.Read(); 2394 reader.Read();
2242 bool isSingleObject = reader.Name != "CoalescedObject"; 2395 bool isSingleObject = reader.Name != "CoalescedObject";
@@ -2254,7 +2407,7 @@ namespace OpenSim.Region.Framework.Scenes
2254 Util.LogFailedXML("[AGENT INVENTORY]:", xmlData); 2407 Util.LogFailedXML("[AGENT INVENTORY]:", xmlData);
2255 g = null; 2408 g = null;
2256 } 2409 }
2257 2410
2258 if (g != null) 2411 if (g != null)
2259 { 2412 {
2260 objlist.Add(g); 2413 objlist.Add(g);
@@ -2265,8 +2418,9 @@ namespace OpenSim.Region.Framework.Scenes
2265 return true; 2418 return true;
2266 } 2419 }
2267 else 2420 else
2268 { 2421 {
2269 XmlDocument doc = new XmlDocument(); 2422 XmlDocument doc = new XmlDocument();
2423 doc.XmlResolver=null;
2270 doc.LoadXml(xmlData); 2424 doc.LoadXml(xmlData);
2271 XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject"); 2425 XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject");
2272 XmlElement coll = (XmlElement)e; 2426 XmlElement coll = (XmlElement)e;
@@ -2316,6 +2470,7 @@ namespace OpenSim.Region.Framework.Scenes
2316 /// </summary> 2470 /// </summary>
2317 /// <param name="remoteClient"></param> 2471 /// <param name="remoteClient"></param>
2318 /// <param name="itemID"></param> 2472 /// <param name="itemID"></param>
2473 /// <param name="rezGroupID"></param>
2319 /// <param name="RayEnd"></param> 2474 /// <param name="RayEnd"></param>
2320 /// <param name="RayStart"></param> 2475 /// <param name="RayStart"></param>
2321 /// <param name="RayTargetID"></param> 2476 /// <param name="RayTargetID"></param>
@@ -2326,55 +2481,55 @@ namespace OpenSim.Region.Framework.Scenes
2326 /// <param name="RezSelected"></param> 2481 /// <param name="RezSelected"></param>
2327 /// <param name="RemoveItem"></param> 2482 /// <param name="RemoveItem"></param>
2328 /// <param name="fromTaskID"></param> 2483 /// <param name="fromTaskID"></param>
2329 public virtual void RezObject(IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart, 2484 public virtual void RezObject(IClientAPI remoteClient, UUID itemID, UUID rezGroupID,
2485 Vector3 RayEnd, Vector3 RayStart,
2330 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, 2486 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
2331 bool RezSelected, bool RemoveItem, UUID fromTaskID) 2487 bool RezSelected, bool RemoveItem, UUID fromTaskID)
2332 { 2488 {
2333// m_log.DebugFormat( 2489// m_log.DebugFormat(
2334// "[PRIM INVENTORY]: RezObject from {0} for item {1} from task id {2}", 2490// "[PRIM INVENTORY]: RezObject from {0} for item {1} from task id {2}",
2335// remoteClient.Name, itemID, fromTaskID); 2491// remoteClient.Name, itemID, fromTaskID);
2336 2492
2337 if (fromTaskID == UUID.Zero) 2493 if (fromTaskID == UUID.Zero)
2338 { 2494 {
2339 IInventoryAccessModule invAccess = RequestModuleInterface<IInventoryAccessModule>(); 2495 IInventoryAccessModule invAccess = RequestModuleInterface<IInventoryAccessModule>();
2340 if (invAccess != null) 2496 if (invAccess != null)
2341 invAccess.RezObject( 2497 invAccess.RezObject(
2342 remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection, 2498 remoteClient, itemID, rezGroupID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection,
2343 RezSelected, RemoveItem, fromTaskID, false); 2499 RezSelected, RemoveItem, fromTaskID, false);
2344 } 2500 }
2345 else 2501 else
2346 { 2502 {
2347 SceneObjectPart part = GetSceneObjectPart(fromTaskID); 2503 SceneObjectPart part = GetSceneObjectPart(fromTaskID);
2348 if (part == null) 2504 if (part == null)
2349 { 2505 {
2350 m_log.ErrorFormat( 2506 m_log.ErrorFormat(
2351 "[TASK INVENTORY]: {0} tried to rez item id {1} from object id {2} but there is no such scene object", 2507 "[TASK INVENTORY]: {0} tried to rez item id {1} from object id {2} but there is no such scene object",
2352 remoteClient.Name, itemID, fromTaskID); 2508 remoteClient.Name, itemID, fromTaskID);
2353 2509
2354 return; 2510 return;
2355 } 2511 }
2356 2512
2357 TaskInventoryItem item = part.Inventory.GetInventoryItem(itemID); 2513 TaskInventoryItem item = part.Inventory.GetInventoryItem(itemID);
2358 if (item == null) 2514 if (item == null)
2359 { 2515 {
2360 m_log.ErrorFormat( 2516 m_log.ErrorFormat(
2361 "[TASK INVENTORY]: {0} tried to rez item id {1} from object id {2} but there is no such item", 2517 "[TASK INVENTORY]: {0} tried to rez item id {1} from object id {2} but there is no such item",
2362 remoteClient.Name, itemID, fromTaskID); 2518 remoteClient.Name, itemID, fromTaskID);
2363 2519
2364 return; 2520 return;
2365 } 2521 }
2366 2522
2367 byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0); 2523 byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0);
2368 Vector3 scale = new Vector3(0.5f, 0.5f, 0.5f); 2524 Vector3 scale = new Vector3(0.5f, 0.5f, 0.5f);
2369 Vector3 pos 2525 Vector3 pos = GetNewRezLocation(
2370 = GetNewRezLocation(
2371 RayStart, RayEnd, RayTargetID, Quaternion.Identity, 2526 RayStart, RayEnd, RayTargetID, Quaternion.Identity,
2372 BypassRayCast, bRayEndIsIntersection, true, scale, false); 2527 BypassRayCast, bRayEndIsIntersection, true, scale, false);
2373 2528
2374 RezObject(part, item, pos, null, Vector3.Zero, 0); 2529 RezObject(part, item, pos, null, Vector3.Zero, 0, false);
2375 } 2530 }
2376 } 2531 }
2377 2532
2378 /// <summary> 2533 /// <summary>
2379 /// Rez an object into the scene from a prim's inventory. 2534 /// Rez an object into the scene from a prim's inventory.
2380 /// </summary> 2535 /// </summary>
@@ -2387,15 +2542,18 @@ namespace OpenSim.Region.Framework.Scenes
2387 /// <param name="param"></param> 2542 /// <param name="param"></param>
2388 /// <returns>The SceneObjectGroup(s) rezzed, or null if rez was unsuccessful</returns> 2543 /// <returns>The SceneObjectGroup(s) rezzed, or null if rez was unsuccessful</returns>
2389 public virtual List<SceneObjectGroup> RezObject( 2544 public virtual List<SceneObjectGroup> RezObject(
2390 SceneObjectPart sourcePart, TaskInventoryItem item, Vector3 pos, Quaternion? rot, Vector3 vel, int param) 2545 SceneObjectPart sourcePart, TaskInventoryItem item, Vector3 pos, Quaternion? rot, Vector3 vel, int param, bool atRoot)
2391 { 2546 {
2392 if (null == item) 2547 if (null == item)
2393 return null; 2548 return null;
2394 2549
2395 List<SceneObjectGroup> objlist; 2550 List<SceneObjectGroup> objlist;
2396 List<Vector3> veclist; 2551 List<Vector3> veclist;
2397 2552 Vector3 bbox;
2398 bool success = sourcePart.Inventory.GetRezReadySceneObjects(item, out objlist, out veclist); 2553 float offsetHeight;
2554
2555 bool success = sourcePart.Inventory.GetRezReadySceneObjects(item, out objlist, out veclist,out bbox, out offsetHeight);
2556
2399 if (!success) 2557 if (!success)
2400 return null; 2558 return null;
2401 2559
@@ -2412,10 +2570,69 @@ namespace OpenSim.Region.Framework.Scenes
2412 sourcePart.Inventory.RemoveInventoryItem(item.ItemID); 2570 sourcePart.Inventory.RemoveInventoryItem(item.ItemID);
2413 } 2571 }
2414 2572
2573 SceneObjectGroup sog;
2574
2575 bool fixrot = false;
2576 Quaternion netRot = Quaternion.Identity;
2577
2578 // position adjust
2579 if (totalPrims > 1) // nothing to do on a single prim
2580 {
2581 if (objlist.Count == 1)
2582 {
2583 // current object position is root position
2584 if(!atRoot)
2585 {
2586 sog = objlist[0];
2587 Quaternion orot;
2588 if (rot == null)
2589 orot = sog.RootPart.GetWorldRotation();
2590 else
2591 orot = rot.Value;
2592 // possible should be bbox, but geometric center looks better
2593 Vector3 off = sog.GetGeometricCenter();
2594// Vector3 off = bbox * 0.5f;
2595 off *= orot;
2596 pos -= off;
2597 }
2598 }
2599 else
2600 {
2601 //veclist[] are relative to bbox corner with min X,Y and Z
2602 // rez at root, and rot will be referenced to first object in list
2603 if (rot == null)
2604 {
2605 // use original rotations
2606 if (atRoot)
2607 pos -= veclist[0];
2608 else
2609 pos -= bbox / 2;
2610 }
2611 else
2612 {
2613 fixrot = true;
2614 sog = objlist[0];
2615 netRot = Quaternion.Conjugate(sog.RootPart.GetWorldRotation());
2616 netRot = netRot * rot.Value;
2617 Vector3 off;
2618 if (atRoot)
2619 off = veclist[0];
2620 else
2621 off = bbox / 2;
2622 off *= netRot;
2623 pos -= off;
2624 }
2625 }
2626 }
2627
2415 for (int i = 0; i < objlist.Count; i++) 2628 for (int i = 0; i < objlist.Count; i++)
2416 { 2629 {
2417 SceneObjectGroup group = objlist[i]; 2630 SceneObjectGroup group = objlist[i];
2418 Vector3 curpos = pos + veclist[i]; 2631 Vector3 curpos;
2632 if(fixrot)
2633 curpos = pos + veclist[i] * netRot;
2634 else
2635 curpos = pos + veclist[i];
2419 2636
2420 if (group.IsAttachment == false && group.RootPart.Shape.State != 0) 2637 if (group.IsAttachment == false && group.RootPart.Shape.State != 0)
2421 { 2638 {
@@ -2423,11 +2640,23 @@ namespace OpenSim.Region.Framework.Scenes
2423 group.RootPart.Shape.LastAttachPoint = (byte)group.AttachmentPoint; 2640 group.RootPart.Shape.LastAttachPoint = (byte)group.AttachmentPoint;
2424 } 2641 }
2425 2642
2426 group.FromPartID = sourcePart.UUID; 2643 group.RezzerID = sourcePart.UUID;
2427 AddNewSceneObject(group, true, curpos, rot, vel); 2644
2645 if( i == 0)
2646 AddNewSceneObject(group, true, curpos, rot, vel);
2647 else
2648 {
2649 Quaternion crot = objlist[i].RootPart.GetWorldRotation();
2650 if (fixrot)
2651 {
2652 crot *= netRot;
2653 }
2654 AddNewSceneObject(group, true, curpos, crot, vel);
2655 }
2428 2656
2429 // We can only call this after adding the scene object, since the scene object references the scene 2657 // 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. 2658 // to find out if scripts should be activated at all.
2659 group.InvalidateEffectivePerms();
2431 group.CreateScriptInstances(param, true, DefaultScriptEngine, 3); 2660 group.CreateScriptInstances(param, true, DefaultScriptEngine, 3);
2432 2661
2433 group.ScheduleGroupForFullUpdate(); 2662 group.ScheduleGroupForFullUpdate();
@@ -2437,7 +2666,7 @@ namespace OpenSim.Region.Framework.Scenes
2437 } 2666 }
2438 2667
2439 public virtual bool returnObjects(SceneObjectGroup[] returnobjects, 2668 public virtual bool returnObjects(SceneObjectGroup[] returnobjects,
2440 UUID AgentId) 2669 IClientAPI client)
2441 { 2670 {
2442 List<uint> localIDs = new List<uint>(); 2671 List<uint> localIDs = new List<uint>();
2443 2672
@@ -2447,14 +2676,17 @@ namespace OpenSim.Region.Framework.Scenes
2447 "parcel owner return"); 2676 "parcel owner return");
2448 localIDs.Add(grp.RootPart.LocalId); 2677 localIDs.Add(grp.RootPart.LocalId);
2449 } 2678 }
2450 DeRezObjects(null, localIDs, UUID.Zero, DeRezAction.Return, 2679 DeRezObjects(client, localIDs, UUID.Zero, DeRezAction.Return,
2451 UUID.Zero); 2680 UUID.Zero, false);
2452 2681
2453 return true; 2682 return true;
2454 } 2683 }
2455 2684
2456 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running) 2685 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running)
2457 { 2686 {
2687 if (!Permissions.CanEditScript(itemID, objectID, controllingClient.AgentId))
2688 return;
2689
2458 SceneObjectPart part = GetSceneObjectPart(objectID); 2690 SceneObjectPart part = GetSceneObjectPart(objectID);
2459 if (part == null) 2691 if (part == null)
2460 return; 2692 return;
@@ -2476,9 +2708,6 @@ namespace OpenSim.Region.Framework.Scenes
2476 { 2708 {
2477 if (ownerID != UUID.Zero) 2709 if (ownerID != UUID.Zero)
2478 return; 2710 return;
2479
2480 if (!Permissions.CanDeedObject(remoteClient.AgentId, groupID))
2481 return;
2482 } 2711 }
2483 2712
2484 List<SceneObjectGroup> groups = new List<SceneObjectGroup>(); 2713 List<SceneObjectGroup> groups = new List<SceneObjectGroup>();
@@ -2486,8 +2715,8 @@ namespace OpenSim.Region.Framework.Scenes
2486 foreach (uint localID in localIDs) 2715 foreach (uint localID in localIDs)
2487 { 2716 {
2488 SceneObjectPart part = GetSceneObjectPart(localID); 2717 SceneObjectPart part = GetSceneObjectPart(localID);
2489 if (part == null) 2718 if (part == null)
2490 continue; 2719 continue;
2491 2720
2492 if (!groups.Contains(part.ParentGroup)) 2721 if (!groups.Contains(part.ParentGroup))
2493 groups.Add(part.ParentGroup); 2722 groups.Add(part.ParentGroup);
@@ -2502,40 +2731,46 @@ namespace OpenSim.Region.Framework.Scenes
2502 sog.ScheduleGroupForFullUpdate(); 2731 sog.ScheduleGroupForFullUpdate();
2503 2732
2504 SceneObjectPart[] partList = sog.Parts; 2733 SceneObjectPart[] partList = sog.Parts;
2505 2734
2506 foreach (SceneObjectPart child in partList) 2735 foreach (SceneObjectPart child in partList)
2507 { 2736 {
2508 child.Inventory.ChangeInventoryOwner(ownerID); 2737 child.Inventory.ChangeInventoryOwner(ownerID);
2509 child.TriggerScriptChangedEvent(Changed.OWNER); 2738 child.TriggerScriptChangedEvent(Changed.OWNER);
2510 } 2739 }
2511 } 2740 }
2512 else 2741 else // The object deeded to the group
2513 { 2742 {
2514 if (!Permissions.CanEditObject(sog.UUID, remoteClient.AgentId)) 2743 if (!Permissions.CanDeedObject(remoteClient, sog, groupID))
2515 continue; 2744 continue;
2516 2745
2517 if (sog.GroupID != groupID) 2746 sog.SetOwnerId(groupID);
2518 continue; 2747
2519 2748 // this is wrong, GroupMask is used for group sharing, still possible to set
2520 SceneObjectPart[] partList = sog.Parts; 2749 // this whould give owner rights to users that are member of group but don't have role powers to edit
2750// sog.RootPart.GroupMask = sog.RootPart.OwnerMask;
2751
2752 // we should keep all permissions on deed to group
2753 // and with this comented code, if user does not set next permissions on the object
2754 // and on ALL contents of ALL prims, he may loose rights, making the object useless
2755 sog.ApplyNextOwnerPermissions();
2756 sog.InvalidateEffectivePerms();
2757
2758 sog.ScheduleGroupForFullUpdate();
2521 2759
2760 SceneObjectPart[] partList = sog.Parts;
2522 foreach (SceneObjectPart child in partList) 2761 foreach (SceneObjectPart child in partList)
2523 { 2762 {
2524 child.LastOwnerID = child.OwnerID;
2525 child.Inventory.ChangeInventoryOwner(groupID); 2763 child.Inventory.ChangeInventoryOwner(groupID);
2526 child.TriggerScriptChangedEvent(Changed.OWNER); 2764 child.TriggerScriptChangedEvent(Changed.OWNER);
2527 } 2765 }
2528
2529 sog.SetOwnerId(groupID);
2530 sog.ApplyNextOwnerPermissions();
2531 } 2766 }
2532 } 2767 }
2533 2768
2534 foreach (uint localID in localIDs) 2769 foreach (uint localID in localIDs)
2535 { 2770 {
2536 SceneObjectPart part = GetSceneObjectPart(localID); 2771 SceneObjectPart part = GetSceneObjectPart(localID);
2537 if (part == null) 2772 if (part == null)
2538 continue; 2773 continue;
2539 part.SendPropertiesToClient(remoteClient); 2774 part.SendPropertiesToClient(remoteClient);
2540 } 2775 }
2541 } 2776 }
@@ -2622,7 +2857,18 @@ namespace OpenSim.Region.Framework.Scenes
2622 return; 2857 return;
2623 } 2858 }
2624 2859
2860 bool oldUsePhysics = (root.Flags & PrimFlags.Physics) != 0;
2625 m_sceneGraph.LinkObjects(root, children); 2861 m_sceneGraph.LinkObjects(root, children);
2862
2863 ScenePresence sp;
2864 if (TryGetScenePresence(agentId, out sp))
2865 {
2866 root.SendPropertiesToClient(sp.ControllingClient);
2867 if (oldUsePhysics && (root.Flags & PrimFlags.Physics) == 0)
2868 {
2869 sp.ControllingClient.SendAlertMessage("Object physics cancelled");
2870 }
2871 }
2626 } 2872 }
2627 2873
2628 private string PermissionString(uint permissions) 2874 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..84bad25 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}",
@@ -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 ///
@@ -176,29 +164,34 @@ namespace OpenSim.Region.Framework.Scenes
176 /// </summary> 164 /// </summary>
177 /// <param name="primLocalID"></param> 165 /// <param name="primLocalID"></param>
178 /// <param name="remoteClient"></param> 166 /// <param name="remoteClient"></param>
179 public void SelectPrim(uint primLocalID, IClientAPI remoteClient) 167 public void SelectPrim(List<uint> primIDs, IClientAPI remoteClient)
180 { 168 {
181 SceneObjectPart part = GetSceneObjectPart(primLocalID); 169 foreach(uint primLocalID in primIDs)
170 {
171 SceneObjectPart part = GetSceneObjectPart(primLocalID);
182 172
183 if (null == part) 173 if (part == null)
184 return; 174 continue;
185 175
186 if (part.IsRoot)
187 {
188 SceneObjectGroup sog = part.ParentGroup; 176 SceneObjectGroup sog = part.ParentGroup;
189 sog.SendPropertiesToClient(remoteClient); 177 if (sog == null)
190 sog.IsSelected = true; 178 continue;
179
180 // waste of time because properties do not send prim flags as they should
181 // if a friend got or lost edit rights after login, a full update is needed
182 if(sog.OwnerID != remoteClient.AgentId)
183 part.SendFullUpdate(remoteClient);
191 184
192 // A prim is only tainted if it's allowed to be edited by the person clicking it. 185 // A prim is only tainted if it's allowed to be edited by the person clicking it.
193 if (Permissions.CanEditObject(sog.UUID, remoteClient.AgentId) 186 if (Permissions.CanChangeSelectedState(part, (ScenePresence)remoteClient.SceneAgent))
194 || Permissions.CanMoveObject(sog.UUID, remoteClient.AgentId))
195 { 187 {
196 EventManager.TriggerParcelPrimCountTainted(); 188 bool oldsel = part.IsSelected;
189 part.IsSelected = true;
190 if(!oldsel)
191 EventManager.TriggerParcelPrimCountTainted();
197 } 192 }
198 } 193
199 else 194 part.SendPropertiesToClient(remoteClient);
200 {
201 part.SendPropertiesToClient(remoteClient);
202 } 195 }
203 } 196 }
204 197
@@ -220,13 +213,13 @@ namespace OpenSim.Region.Framework.Scenes
220 if (groupID != UUID.Zero) 213 if (groupID != UUID.Zero)
221 { 214 {
222 GroupMembershipData gmd = m_groupsModule.GetMembershipData(groupID, remoteClient.AgentId); 215 GroupMembershipData gmd = m_groupsModule.GetMembershipData(groupID, remoteClient.AgentId);
223 216
224 if (gmd == null) 217 if (gmd == null)
225 { 218 {
226// m_log.WarnFormat( 219// m_log.WarnFormat(
227// "[GROUPS]: User {0} is not a member of group {1} so they can't update {2} to this group", 220// "[GROUPS]: User {0} is not a member of group {1} so they can't update {2} to this group",
228// remoteClient.Name, GroupID, objectLocalID); 221// remoteClient.Name, GroupID, objectLocalID);
229 222
230 return; 223 return;
231 } 224 }
232 } 225 }
@@ -237,6 +230,7 @@ namespace OpenSim.Region.Framework.Scenes
237 if (so.OwnerID == remoteClient.AgentId) 230 if (so.OwnerID == remoteClient.AgentId)
238 { 231 {
239 so.SetGroup(groupID, remoteClient); 232 so.SetGroup(groupID, remoteClient);
233 EventManager.TriggerParcelPrimCountTainted();
240 } 234 }
241 } 235 }
242 } 236 }
@@ -251,40 +245,29 @@ namespace OpenSim.Region.Framework.Scenes
251 SceneObjectPart part = GetSceneObjectPart(primLocalID); 245 SceneObjectPart part = GetSceneObjectPart(primLocalID);
252 if (part == null) 246 if (part == null)
253 return; 247 return;
254 248
255 // A deselect packet contains all the local prims being deselected. However, since selection is still 249 bool oldgprSelect = part.ParentGroup.IsSelected;
256 // 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
258 if (part.ParentGroup.RootPart.LocalId != part.LocalId)
259 return;
260 250
261 // This is wrong, wrong, wrong. Selection should not be 251 // This is wrong, wrong, wrong. Selection should not be
262 // handled by group, but by prim. Legacy cruft. 252 // handled by group, but by prim. Legacy cruft.
263 // TODO: Make selection flagging per prim! 253 // TODO: Make selection flagging per prim!
264 // 254 //
265 part.ParentGroup.IsSelected = false; 255 if (Permissions.CanChangeSelectedState(part, (ScenePresence)remoteClient.SceneAgent))
266
267 part.ParentGroup.ScheduleGroupForFullUpdate();
268
269 // If it's not an attachment, and we are allowed to move it,
270 // then we might have done so. If we moved across a parcel
271 // boundary, we will need to recount prims on the parcels.
272 // For attachments, that makes no sense.
273 //
274 if (!part.ParentGroup.IsAttachment)
275 { 256 {
276 if (Permissions.CanEditObject( 257 part.IsSelected = false;
277 part.UUID, remoteClient.AgentId) 258 if (!part.ParentGroup.IsAttachment && oldgprSelect != part.ParentGroup.IsSelected)
278 || Permissions.CanMoveObject(
279 part.UUID, remoteClient.AgentId))
280 EventManager.TriggerParcelPrimCountTainted(); 259 EventManager.TriggerParcelPrimCountTainted();
260
261 // restore targetOmega
262 if (part.AngularVelocity != Vector3.Zero)
263 part.ScheduleTerseUpdate();
281 } 264 }
282 } 265 }
283 266
284 public virtual void ProcessMoneyTransferRequest(UUID source, UUID destination, int amount, 267 public virtual void ProcessMoneyTransferRequest(UUID source, UUID destination, int amount,
285 int transactiontype, string description) 268 int transactiontype, string description)
286 { 269 {
287 EventManager.MoneyTransferArgs args = new EventManager.MoneyTransferArgs(source, destination, amount, 270 EventManager.MoneyTransferArgs args = new EventManager.MoneyTransferArgs(source, destination, amount,
288 transactiontype, description); 271 transactiontype, description);
289 272
290 EventManager.TriggerMoneyTransfer(this, args); 273 EventManager.TriggerMoneyTransfer(this, args);
@@ -293,8 +276,8 @@ namespace OpenSim.Region.Framework.Scenes
293 public virtual void ProcessParcelBuy(UUID agentId, UUID groupId, bool final, bool groupOwned, 276 public virtual void ProcessParcelBuy(UUID agentId, UUID groupId, bool final, bool groupOwned,
294 bool removeContribution, int parcelLocalID, int parcelArea, int parcelPrice, bool authenticated) 277 bool removeContribution, int parcelLocalID, int parcelArea, int parcelPrice, bool authenticated)
295 { 278 {
296 EventManager.LandBuyArgs args = new EventManager.LandBuyArgs(agentId, groupId, final, groupOwned, 279 EventManager.LandBuyArgs args = new EventManager.LandBuyArgs(agentId, groupId, final, groupOwned,
297 removeContribution, parcelLocalID, parcelArea, 280 removeContribution, parcelLocalID, parcelArea,
298 parcelPrice, authenticated); 281 parcelPrice, authenticated);
299 282
300 // First, allow all validators a stab at it 283 // First, allow all validators a stab at it
@@ -307,7 +290,7 @@ namespace OpenSim.Region.Framework.Scenes
307 public virtual void ProcessObjectGrab(uint localID, Vector3 offsetPos, IClientAPI remoteClient, List<SurfaceTouchEventArgs> surfaceArgs) 290 public virtual void ProcessObjectGrab(uint localID, Vector3 offsetPos, IClientAPI remoteClient, List<SurfaceTouchEventArgs> surfaceArgs)
308 { 291 {
309 SceneObjectPart part = GetSceneObjectPart(localID); 292 SceneObjectPart part = GetSceneObjectPart(localID);
310 293
311 if (part == null) 294 if (part == null)
312 return; 295 return;
313 296
@@ -320,19 +303,17 @@ namespace OpenSim.Region.Framework.Scenes
320 // Currently only grab/touch for the single prim 303 // Currently only grab/touch for the single prim
321 // the client handles rez correctly 304 // the client handles rez correctly
322 obj.ObjectGrabHandler(localID, offsetPos, remoteClient); 305 obj.ObjectGrabHandler(localID, offsetPos, remoteClient);
323 306
324 // If the touched prim handles touches, deliver it 307 // If the touched prim handles touches, deliver it
325 // If not, deliver to root prim
326 if ((part.ScriptEvents & scriptEvents.touch_start) != 0) 308 if ((part.ScriptEvents & scriptEvents.touch_start) != 0)
327 EventManager.TriggerObjectGrab(part.LocalId, 0, part.OffsetPosition, remoteClient, surfaceArg); 309 EventManager.TriggerObjectGrab(part.LocalId, 0, offsetPos, remoteClient, surfaceArg);
328 310
329 // Deliver to the root prim if the touched prim doesn't handle touches 311 // Deliver to the root prim if the touched prim doesn't handle touches
330 // or if we're meant to pass on touches anyway. Don't send to root prim 312 // or if we're meant to pass on touches anyway.
331 // if prim touched is the root prim as we just did it
332 if (((part.ScriptEvents & scriptEvents.touch_start) == 0) || 313 if (((part.ScriptEvents & scriptEvents.touch_start) == 0) ||
333 (part.PassTouches && (part.LocalId != obj.RootPart.LocalId))) 314 (part.PassTouches && (part.LocalId != obj.RootPart.LocalId)))
334 { 315 {
335 EventManager.TriggerObjectGrab(obj.RootPart.LocalId, part.LocalId, part.OffsetPosition, remoteClient, surfaceArg); 316 EventManager.TriggerObjectGrab(obj.RootPart.LocalId, part.LocalId, offsetPos, remoteClient, surfaceArg);
336 } 317 }
337 } 318 }
338 319
@@ -343,23 +324,37 @@ namespace OpenSim.Region.Framework.Scenes
343 if (part == null) 324 if (part == null)
344 return; 325 return;
345 326
346 SceneObjectGroup obj = part.ParentGroup; 327 SceneObjectGroup group = part.ParentGroup;
328 if(group == null || group.IsDeleted)
329 return;
330
331 if (Permissions.CanMoveObject(group, remoteClient))// && PermissionsMngr.)
332 {
333 group.GrabMovement(objectID, offset, pos, remoteClient);
334 }
335
336 // This is outside the above permissions condition
337 // so that if the object is locked the client moving the object
338 // get's it's position on the simulator even if it was the same as before
339 // This keeps the moving user's client in sync with the rest of the world.
340 group.SendGroupTerseUpdate();
347 341
348 SurfaceTouchEventArgs surfaceArg = null; 342 SurfaceTouchEventArgs surfaceArg = null;
349 if (surfaceArgs != null && surfaceArgs.Count > 0) 343 if (surfaceArgs != null && surfaceArgs.Count > 0)
350 surfaceArg = surfaceArgs[0]; 344 surfaceArg = surfaceArgs[0];
351 345
346 Vector3 grabOffset = pos - part.AbsolutePosition;
352 // If the touched prim handles touches, deliver it 347 // If the touched prim handles touches, deliver it
353 // If not, deliver to root prim
354 if ((part.ScriptEvents & scriptEvents.touch) != 0) 348 if ((part.ScriptEvents & scriptEvents.touch) != 0)
355 EventManager.TriggerObjectGrabbing(part.LocalId, 0, part.OffsetPosition, remoteClient, surfaceArg); 349// EventManager.TriggerObjectGrabbing(part.LocalId, 0, part.OffsetPosition, remoteClient, surfaceArg);
350 EventManager.TriggerObjectGrabbing(part.LocalId, 0, grabOffset, remoteClient, surfaceArg);
356 // Deliver to the root prim if the touched prim doesn't handle touches 351 // Deliver to the root prim if the touched prim doesn't handle touches
357 // or if we're meant to pass on touches anyway. Don't send to root prim 352 // or if we're meant to pass on touches anyway.
358 // if prim touched is the root prim as we just did it
359 if (((part.ScriptEvents & scriptEvents.touch) == 0) || 353 if (((part.ScriptEvents & scriptEvents.touch) == 0) ||
360 (part.PassTouches && (part.LocalId != obj.RootPart.LocalId))) 354 (part.PassTouches && (part.LocalId != group.RootPart.LocalId)))
361 { 355 {
362 EventManager.TriggerObjectGrabbing(obj.RootPart.LocalId, part.LocalId, part.OffsetPosition, remoteClient, surfaceArg); 356// EventManager.TriggerObjectGrabbing(group.RootPart.LocalId, part.LocalId, part.OffsetPosition, remoteClient, surfaceArg);
357 EventManager.TriggerObjectGrabbing(group.RootPart.LocalId, part.LocalId, grabOffset, remoteClient, surfaceArg);
363 } 358 }
364 } 359 }
365 360
@@ -369,18 +364,77 @@ namespace OpenSim.Region.Framework.Scenes
369 if (part == null) 364 if (part == null)
370 return; 365 return;
371 366
372 SceneObjectGroup obj = part.ParentGroup; 367 SceneObjectGroup grp = part.ParentGroup;
373 368
374 SurfaceTouchEventArgs surfaceArg = null; 369 SurfaceTouchEventArgs surfaceArg = null;
375 if (surfaceArgs != null && surfaceArgs.Count > 0) 370 if (surfaceArgs != null && surfaceArgs.Count > 0)
376 surfaceArg = surfaceArgs[0]; 371 surfaceArg = surfaceArgs[0];
377 372
378 // If the touched prim handles touches, deliver it 373 // If the touched prim handles touches, deliver it
379 // If not, deliver to root prim
380 if ((part.ScriptEvents & scriptEvents.touch_end) != 0) 374 if ((part.ScriptEvents & scriptEvents.touch_end) != 0)
381 EventManager.TriggerObjectDeGrab(part.LocalId, 0, remoteClient, surfaceArg); 375 EventManager.TriggerObjectDeGrab(part.LocalId, 0, remoteClient, surfaceArg);
382 else 376 // if not or PassTouchs, send it also to root.
383 EventManager.TriggerObjectDeGrab(obj.RootPart.LocalId, part.LocalId, remoteClient, surfaceArg); 377 if (((part.ScriptEvents & scriptEvents.touch_end) == 0) ||
378 (part.PassTouches && (part.LocalId != grp.RootPart.LocalId)))
379 {
380 EventManager.TriggerObjectDeGrab(grp.RootPart.LocalId, part.LocalId, remoteClient, surfaceArg);
381 }
382 }
383
384 /// <summary>
385 /// Start spinning the given object
386 /// </summary>
387 /// <param name="objectID"></param>
388 /// <param name="rotation"></param>
389 /// <param name="remoteClient"></param>
390 public virtual void ProcessSpinStart(UUID objectID, IClientAPI remoteClient)
391 {
392 SceneObjectGroup group = GetGroupByPrim(objectID);
393 if (group != null)
394 {
395 if (Permissions.CanMoveObject(group, remoteClient))// && PermissionsMngr.)
396 {
397 group.SpinStart(remoteClient);
398 }
399 }
400 }
401
402 /// <summary>
403 /// Spin the given object
404 /// </summary>
405 /// <param name="objectID"></param>
406 /// <param name="rotation"></param>
407 /// <param name="remoteClient"></param>
408 public virtual void ProcessSpinObject(UUID objectID, Quaternion rotation, IClientAPI remoteClient)
409 {
410 SceneObjectGroup group = GetGroupByPrim(objectID);
411 if (group != null)
412 {
413 if (Permissions.CanMoveObject(group, remoteClient))// && PermissionsMngr.)
414 {
415 group.SpinMovement(rotation, remoteClient);
416 }
417 // This is outside the above permissions condition
418 // so that if the object is locked the client moving the object
419 // get's it's position on the simulator even if it was the same as before
420 // This keeps the moving user's client in sync with the rest of the world.
421 group.SendGroupTerseUpdate();
422 }
423 }
424
425 public virtual void ProcessSpinObjectStop(UUID objectID, IClientAPI remoteClient)
426 {
427/* no op for now
428 SceneObjectGroup group = GetGroupByPrim(objectID);
429 if (group != null)
430 {
431 if (Permissions.CanMoveObject(group.UUID, remoteClient.AgentId))// && PermissionsMngr.)
432 {
433// group.SpinMovement(rotation, remoteClient);
434 }
435 group.SendGroupTerseUpdate();
436 }
437*/
384 } 438 }
385 439
386 public void ProcessScriptReset(IClientAPI remoteClient, UUID objectID, 440 public void ProcessScriptReset(IClientAPI remoteClient, UUID objectID,
@@ -439,6 +493,20 @@ namespace OpenSim.Region.Framework.Scenes
439 return Vector3.Distance(other.CameraPosition, thisClient.SceneAgent.AbsolutePosition) < 10; 493 return Vector3.Distance(other.CameraPosition, thisClient.SceneAgent.AbsolutePosition) < 10;
440 } 494 }
441 495
496 private class DescendentsRequestData
497 {
498 public IClientAPI RemoteClient;
499 public UUID FolderID;
500 public UUID OwnerID;
501 public bool FetchFolders;
502 public bool FetchItems;
503 public int SortOrder;
504 }
505
506 private Queue<DescendentsRequestData> m_descendentsRequestQueue = new Queue<DescendentsRequestData>();
507 private Object m_descendentsRequestLock = new Object();
508 private bool m_descendentsRequestProcessing = false;
509
442 /// <summary> 510 /// <summary>
443 /// Tell the client about the various child items and folders contained in the requested folder. 511 /// Tell the client about the various child items and folders contained in the requested folder.
444 /// </summary> 512 /// </summary>
@@ -475,11 +543,31 @@ namespace OpenSim.Region.Framework.Scenes
475 } 543 }
476 } 544 }
477 545
478 // We're going to send the reply async, because there may be 546 lock (m_descendentsRequestLock)
479 // an enormous quantity of packets -- basically the entire inventory! 547 {
480 // We don't want to block the client thread while all that is happening. 548 if (!m_descendentsRequestProcessing)
481 SendInventoryDelegate d = SendInventoryAsync; 549 {
482 d.BeginInvoke(remoteClient, folderID, ownerID, fetchFolders, fetchItems, sortOrder, SendInventoryComplete, d); 550 m_descendentsRequestProcessing = true;
551
552 // We're going to send the reply async, because there may be
553 // an enormous quantity of packets -- basically the entire inventory!
554 // We don't want to block the client thread while all that is happening.
555 SendInventoryDelegate d = SendInventoryAsync;
556 d.BeginInvoke(remoteClient, folderID, ownerID, fetchFolders, fetchItems, sortOrder, SendInventoryComplete, d);
557
558 return;
559 }
560
561 DescendentsRequestData req = new DescendentsRequestData();
562 req.RemoteClient = remoteClient;
563 req.FolderID = folderID;
564 req.OwnerID = ownerID;
565 req.FetchFolders = fetchFolders;
566 req.FetchItems = fetchItems;
567 req.SortOrder = sortOrder;
568
569 m_descendentsRequestQueue.Enqueue(req);
570 }
483 } 571 }
484 572
485 delegate void SendInventoryDelegate(IClientAPI remoteClient, UUID folderID, UUID ownerID, bool fetchFolders, bool fetchItems, int sortOrder); 573 delegate void SendInventoryDelegate(IClientAPI remoteClient, UUID folderID, UUID ownerID, bool fetchFolders, bool fetchItems, int sortOrder);
@@ -494,16 +582,32 @@ namespace OpenSim.Region.Framework.Scenes
494 { 582 {
495 m_log.Error( 583 m_log.Error(
496 string.Format( 584 string.Format(
497 "[AGENT INVENTORY]: Error in SendInventoryAsync() for {0} with folder ID {1}. Exception ", e)); 585 "[AGENT INVENTORY]: Error in SendInventoryAsync() for {0} with folder ID {1}. Exception ", e, folderID));
498 } 586 }
587 Thread.Sleep(20);
499 } 588 }
500 589
501 void SendInventoryComplete(IAsyncResult iar) 590 void SendInventoryComplete(IAsyncResult iar)
502 { 591 {
503 SendInventoryDelegate d = (SendInventoryDelegate)iar.AsyncState; 592 SendInventoryDelegate d = (SendInventoryDelegate)iar.AsyncState;
504 d.EndInvoke(iar); 593 d.EndInvoke(iar);
594
595 lock (m_descendentsRequestLock)
596 {
597 if (m_descendentsRequestQueue.Count > 0)
598 {
599 DescendentsRequestData req = m_descendentsRequestQueue.Dequeue();
600
601 d = SendInventoryAsync;
602 d.BeginInvoke(req.RemoteClient, req.FolderID, req.OwnerID, req.FetchFolders, req.FetchItems, req.SortOrder, SendInventoryComplete, d);
603
604 return;
605 }
606
607 m_descendentsRequestProcessing = false;
608 }
505 } 609 }
506 610
507 /// <summary> 611 /// <summary>
508 /// Handle an inventory folder creation request from the client. 612 /// Handle an inventory folder creation request from the client.
509 /// </summary> 613 /// </summary>
@@ -543,8 +647,7 @@ namespace OpenSim.Region.Framework.Scenes
543// m_log.DebugFormat( 647// m_log.DebugFormat(
544// "[AGENT INVENTORY]: Updating inventory folder {0} {1} for {2} {3}", folderID, name, remoteClient.Name, remoteClient.AgentId); 648// "[AGENT INVENTORY]: Updating inventory folder {0} {1} for {2} {3}", folderID, name, remoteClient.Name, remoteClient.AgentId);
545 649
546 InventoryFolderBase folder = new InventoryFolderBase(folderID, remoteClient.AgentId); 650 InventoryFolderBase folder = InventoryService.GetFolder(remoteClient.AgentId, folderID);
547 folder = InventoryService.GetFolder(folder);
548 if (folder != null) 651 if (folder != null)
549 { 652 {
550 folder.Name = name; 653 folder.Name = name;
@@ -558,11 +661,10 @@ namespace OpenSim.Region.Framework.Scenes
558 } 661 }
559 } 662 }
560 } 663 }
561 664
562 public void HandleMoveInventoryFolder(IClientAPI remoteClient, UUID folderID, UUID parentID) 665 public void HandleMoveInventoryFolder(IClientAPI remoteClient, UUID folderID, UUID parentID)
563 { 666 {
564 InventoryFolderBase folder = new InventoryFolderBase(folderID, remoteClient.AgentId); 667 InventoryFolderBase folder = InventoryService.GetFolder(remoteClient.AgentId, folderID);
565 folder = InventoryService.GetFolder(folder);
566 if (folder != null) 668 if (folder != null)
567 { 669 {
568 folder.ParentID = parentID; 670 folder.ParentID = parentID;
@@ -601,10 +703,17 @@ namespace OpenSim.Region.Framework.Scenes
601 { 703 {
602 InventoryFolderBase folder = new InventoryFolderBase(folderID, userID); 704 InventoryFolderBase folder = new InventoryFolderBase(folderID, userID);
603 705
604 if (InventoryService.PurgeFolder(folder)) 706 try
605 m_log.DebugFormat("[AGENT INVENTORY]: folder {0} purged successfully", folderID); 707 {
606 else 708 if (InventoryService.PurgeFolder(folder))
607 m_log.WarnFormat("[AGENT INVENTORY]: could not purge folder {0}", folderID); 709 m_log.DebugFormat("[AGENT INVENTORY]: folder {0} purged successfully", folderID);
710 else
711 m_log.WarnFormat("[AGENT INVENTORY]: could not purge folder {0}", folderID);
712 }
713 catch (Exception e)
714 {
715 m_log.WarnFormat("[AGENT INVENTORY]: Exception on async purge folder for user {0}: {1}", userID, e.Message);
716 }
608 } 717 }
609 718
610 private void PurgeFolderCompleted(IAsyncResult iar) 719 private void PurgeFolderCompleted(IAsyncResult iar)
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
index 535d87a..a75671e 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
@@ -35,52 +35,63 @@ using OpenSim.Framework;
35using OpenSim.Region.Framework.Interfaces; 35using OpenSim.Region.Framework.Interfaces;
36 36
37namespace OpenSim.Region.Framework.Scenes 37namespace OpenSim.Region.Framework.Scenes
38{ 38{
39 #region Delegates 39 #region Delegates
40 public delegate uint GenerateClientFlagsHandler(UUID userID, UUID objectID); 40 public delegate uint GenerateClientFlagsHandler(SceneObjectPart part, ScenePresence sp, uint curEffectivePerms);
41 public delegate void SetBypassPermissionsHandler(bool value); 41 public delegate void SetBypassPermissionsHandler(bool value);
42 public delegate bool BypassPermissionsHandler(); 42 public delegate bool BypassPermissionsHandler();
43 public delegate bool PropagatePermissionsHandler(); 43 public delegate bool PropagatePermissionsHandler();
44 public delegate bool RezObjectHandler(int objectCount, UUID owner, Vector3 objectPosition, Scene scene); 44 public delegate bool RezObjectHandler(int objectCount, UUID owner, Vector3 objectPosition);
45 public delegate bool DeleteObjectHandler(UUID objectID, UUID deleter, Scene scene); 45 public delegate bool DeleteObjectHandlerByIDs(UUID objectID, UUID deleter);
46 public delegate bool TransferObjectHandler(UUID objectID, UUID recipient, Scene scene); 46 public delegate bool DeleteObjectHandler(SceneObjectGroup sog, ScenePresence sp);
47 public delegate bool TakeObjectHandler(UUID objectID, UUID stealer, Scene scene); 47 public delegate bool TransferObjectHandler(UUID objectID, UUID recipient);
48 public delegate bool TakeCopyObjectHandler(UUID objectID, UUID userID, Scene inScene); 48 public delegate bool TakeObjectHandler(SceneObjectGroup sog, ScenePresence sp);
49 public delegate bool DuplicateObjectHandler(int objectCount, UUID objectID, UUID owner, Scene scene, Vector3 objectPosition); 49 public delegate bool SellGroupObjectHandler(UUID userID, UUID groupID);
50 public delegate bool EditObjectHandler(UUID objectID, UUID editorID, Scene scene); 50 public delegate bool SellObjectHandlerByUserID(SceneObjectGroup sog, UUID userID, byte saleType);
51 public delegate bool EditObjectInventoryHandler(UUID objectID, UUID editorID, Scene scene); 51 public delegate bool SellObjectHandler(SceneObjectGroup sog, ScenePresence sp, byte saleType);
52 public delegate bool MoveObjectHandler(UUID objectID, UUID moverID, Scene scene); 52 public delegate bool TakeCopyObjectHandler(SceneObjectGroup sog, ScenePresence sp);
53 public delegate bool ObjectEntryHandler(UUID objectID, bool enteringRegion, Vector3 newPoint, Scene scene); 53 public delegate bool DuplicateObjectHandler(SceneObjectGroup sog, ScenePresence sp);
54 public delegate bool ReturnObjectsHandler(ILandObject land, UUID user, List<SceneObjectGroup> objects, Scene scene); 54 public delegate bool EditObjectByIDsHandler(UUID objectID, UUID editorID);
55 public delegate bool InstantMessageHandler(UUID user, UUID target, Scene startScene); 55 public delegate bool EditObjectHandler(SceneObjectGroup sog, ScenePresence sp);
56 public delegate bool InventoryTransferHandler(UUID user, UUID target, Scene startScene); 56 public delegate bool EditObjectPermsHandler(SceneObjectGroup sog, UUID editorID);
57 public delegate bool ViewScriptHandler(UUID script, UUID objectID, UUID user, Scene scene); 57 public delegate bool EditObjectInventoryHandler(UUID objectID, UUID editorID);
58 public delegate bool ViewNotecardHandler(UUID script, UUID objectID, UUID user, Scene scene); 58 public delegate bool MoveObjectHandler(SceneObjectGroup sog, ScenePresence sp);
59 public delegate bool EditScriptHandler(UUID script, UUID objectID, UUID user, Scene scene); 59 public delegate bool ObjectEntryHandler(SceneObjectGroup sog, bool enteringRegion, Vector3 newPoint);
60 public delegate bool EditNotecardHandler(UUID notecard, UUID objectID, UUID user, Scene scene); 60 public delegate bool ObjectEnterWithScriptsHandler(SceneObjectGroup sog, ILandObject land);
61 public delegate bool RunScriptHandler(UUID script, UUID objectID, UUID user, Scene scene); 61 public delegate bool ReturnObjectsHandler(ILandObject land, ScenePresence sp, List<SceneObjectGroup> objects);
62 public delegate bool CompileScriptHandler(UUID ownerUUID, int scriptType, Scene scene); 62 public delegate bool InstantMessageHandler(UUID user, UUID target);
63 public delegate bool StartScriptHandler(UUID script, UUID user, Scene scene); 63 public delegate bool InventoryTransferHandler(UUID user, UUID target);
64 public delegate bool StopScriptHandler(UUID script, UUID user, Scene scene); 64 public delegate bool ViewScriptHandler(UUID script, UUID objectID, UUID user);
65 public delegate bool ResetScriptHandler(UUID prim, UUID script, UUID user, Scene scene); 65 public delegate bool ViewNotecardHandler(UUID script, UUID objectID, UUID user);
66 public delegate bool TerraformLandHandler(UUID user, Vector3 position, Scene requestFromScene); 66 public delegate bool EditScriptHandler(UUID script, UUID objectID, UUID user);
67 public delegate bool RunConsoleCommandHandler(UUID user, Scene requestFromScene); 67 public delegate bool EditNotecardHandler(UUID notecard, UUID objectID, UUID user);
68 public delegate bool IssueEstateCommandHandler(UUID user, Scene requestFromScene, bool ownerCommand); 68 public delegate bool RunScriptHandlerByIDs(UUID script, UUID objectID, UUID user);
69 public delegate bool IsGodHandler(UUID user, Scene requestFromScene); 69 public delegate bool RunScriptHandler(TaskInventoryItem item, SceneObjectPart part);
70 public delegate bool IsGridGodHandler(UUID user, Scene requestFromScene); 70 public delegate bool CompileScriptHandler(UUID ownerUUID, int scriptType);
71 public delegate bool StartScriptHandler(UUID script, UUID user);
72 public delegate bool StopScriptHandler(UUID script, UUID user);
73 public delegate bool ResetScriptHandler(UUID prim, UUID script, UUID user);
74 public delegate bool TerraformLandHandler(UUID user, Vector3 position);
75 public delegate bool RunConsoleCommandHandler(UUID user);
76 public delegate bool IssueEstateCommandHandler(UUID user, bool ownerCommand);
77 public delegate bool IsGodHandler(UUID user);
78 public delegate bool IsGridGodHandler(UUID user);
71 public delegate bool IsAdministratorHandler(UUID user); 79 public delegate bool IsAdministratorHandler(UUID user);
72 public delegate bool EditParcelHandler(UUID user, ILandObject parcel, Scene scene); 80 public delegate bool IsEstateManagerHandler(UUID user);
73 public delegate bool EditParcelPropertiesHandler(UUID user, ILandObject parcel, GroupPowers p, Scene scene); 81 public delegate bool EditParcelHandler(UUID user, ILandObject parcel);
74 public delegate bool SellParcelHandler(UUID user, ILandObject parcel, Scene scene); 82 public delegate bool EditParcelPropertiesHandler(UUID user, ILandObject parcel, GroupPowers p, bool allowManager);
75 public delegate bool AbandonParcelHandler(UUID user, ILandObject parcel, Scene scene); 83 public delegate bool SellParcelHandler(UUID user, ILandObject parcel);
76 public delegate bool ReclaimParcelHandler(UUID user, ILandObject parcel, Scene scene); 84 public delegate bool AbandonParcelHandler(UUID user, ILandObject parcel);
77 public delegate bool DeedParcelHandler(UUID user, ILandObject parcel, Scene scene); 85 public delegate bool ReclaimParcelHandler(UUID user, ILandObject parcel);
78 public delegate bool DeedObjectHandler(UUID user, UUID group, Scene scene); 86 public delegate bool DeedParcelHandler(UUID user, ILandObject parcel);
79 public delegate bool BuyLandHandler(UUID user, ILandObject parcel, Scene scene); 87 public delegate bool DeedObjectHandler(ScenePresence sp, SceneObjectGroup sog, UUID targetGroupID);
88 public delegate bool BuyLandHandler(UUID user, ILandObject parcel);
80 public delegate bool LinkObjectHandler(UUID user, UUID objectID); 89 public delegate bool LinkObjectHandler(UUID user, UUID objectID);
81 public delegate bool DelinkObjectHandler(UUID user, UUID objectID); 90 public delegate bool DelinkObjectHandler(UUID user, UUID objectID);
82 public delegate bool CreateObjectInventoryHandler(int invType, UUID objectID, UUID userID); 91 public delegate bool CreateObjectInventoryHandler(int invType, UUID objectID, UUID userID);
83 public delegate bool CopyObjectInventoryHandler(UUID itemID, UUID objectID, UUID userID); 92 public delegate bool CopyObjectInventoryHandler(UUID itemID, UUID objectID, UUID userID);
93 public delegate bool DoObjectInvToObjectInv(TaskInventoryItem item, SceneObjectPart sourcePart, SceneObjectPart destPart);
94 public delegate bool DoDropInObjectInv(InventoryItemBase item, ScenePresence sp, SceneObjectPart destPart);
84 public delegate bool DeleteObjectInventoryHandler(UUID itemID, UUID objectID, UUID userID); 95 public delegate bool DeleteObjectInventoryHandler(UUID itemID, UUID objectID, UUID userID);
85 public delegate bool TransferObjectInventoryHandler(UUID itemID, UUID objectID, UUID userID); 96 public delegate bool TransferObjectInventoryHandler(UUID itemID, UUID objectID, UUID userID);
86 public delegate bool CreateUserInventoryHandler(int invType, UUID userID); 97 public delegate bool CreateUserInventoryHandler(int invType, UUID userID);
@@ -96,7 +107,7 @@ namespace OpenSim.Region.Framework.Scenes
96 public class ScenePermissions 107 public class ScenePermissions
97 { 108 {
98// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 109// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
99 110
100 private Scene m_scene; 111 private Scene m_scene;
101 112
102 public ScenePermissions(Scene scene) 113 public ScenePermissions(Scene scene)
@@ -110,15 +121,24 @@ namespace OpenSim.Region.Framework.Scenes
110 public event BypassPermissionsHandler OnBypassPermissions; 121 public event BypassPermissionsHandler OnBypassPermissions;
111 public event PropagatePermissionsHandler OnPropagatePermissions; 122 public event PropagatePermissionsHandler OnPropagatePermissions;
112 public event RezObjectHandler OnRezObject; 123 public event RezObjectHandler OnRezObject;
124 public event DeleteObjectHandlerByIDs OnDeleteObjectByIDs;
113 public event DeleteObjectHandler OnDeleteObject; 125 public event DeleteObjectHandler OnDeleteObject;
114 public event TransferObjectHandler OnTransferObject; 126 public event TransferObjectHandler OnTransferObject;
115 public event TakeObjectHandler OnTakeObject; 127 public event TakeObjectHandler OnTakeObject;
128
129 public event SellGroupObjectHandler OnSellGroupObject;
130 public event SellObjectHandlerByUserID OnSellObjectByUserID;
131 public event SellObjectHandler OnSellObject;
132
116 public event TakeCopyObjectHandler OnTakeCopyObject; 133 public event TakeCopyObjectHandler OnTakeCopyObject;
117 public event DuplicateObjectHandler OnDuplicateObject; 134 public event DuplicateObjectHandler OnDuplicateObject;
135 public event EditObjectByIDsHandler OnEditObjectByIDs;
118 public event EditObjectHandler OnEditObject; 136 public event EditObjectHandler OnEditObject;
137 public event EditObjectPermsHandler OnEditObjectPerms;
119 public event EditObjectInventoryHandler OnEditObjectInventory; 138 public event EditObjectInventoryHandler OnEditObjectInventory;
120 public event MoveObjectHandler OnMoveObject; 139 public event MoveObjectHandler OnMoveObject;
121 public event ObjectEntryHandler OnObjectEntry; 140 public event ObjectEntryHandler OnObjectEntry;
141 public event ObjectEnterWithScriptsHandler OnObjectEnterWithScripts;
122 public event ReturnObjectsHandler OnReturnObjects; 142 public event ReturnObjectsHandler OnReturnObjects;
123 public event InstantMessageHandler OnInstantMessage; 143 public event InstantMessageHandler OnInstantMessage;
124 public event InventoryTransferHandler OnInventoryTransfer; 144 public event InventoryTransferHandler OnInventoryTransfer;
@@ -126,6 +146,7 @@ namespace OpenSim.Region.Framework.Scenes
126 public event ViewNotecardHandler OnViewNotecard; 146 public event ViewNotecardHandler OnViewNotecard;
127 public event EditScriptHandler OnEditScript; 147 public event EditScriptHandler OnEditScript;
128 public event EditNotecardHandler OnEditNotecard; 148 public event EditNotecardHandler OnEditNotecard;
149 public event RunScriptHandlerByIDs OnRunScriptByIDs;
129 public event RunScriptHandler OnRunScript; 150 public event RunScriptHandler OnRunScript;
130 public event CompileScriptHandler OnCompileScript; 151 public event CompileScriptHandler OnCompileScript;
131 public event StartScriptHandler OnStartScript; 152 public event StartScriptHandler OnStartScript;
@@ -134,9 +155,9 @@ namespace OpenSim.Region.Framework.Scenes
134 public event TerraformLandHandler OnTerraformLand; 155 public event TerraformLandHandler OnTerraformLand;
135 public event RunConsoleCommandHandler OnRunConsoleCommand; 156 public event RunConsoleCommandHandler OnRunConsoleCommand;
136 public event IssueEstateCommandHandler OnIssueEstateCommand; 157 public event IssueEstateCommandHandler OnIssueEstateCommand;
137 public event IsGodHandler OnIsGod;
138 public event IsGridGodHandler OnIsGridGod; 158 public event IsGridGodHandler OnIsGridGod;
139 public event IsAdministratorHandler OnIsAdministrator; 159 public event IsAdministratorHandler OnIsAdministrator;
160 public event IsEstateManagerHandler OnIsEstateManager;
140// public event EditParcelHandler OnEditParcel; 161// public event EditParcelHandler OnEditParcel;
141 public event EditParcelPropertiesHandler OnEditParcelProperties; 162 public event EditParcelPropertiesHandler OnEditParcelProperties;
142 public event SellParcelHandler OnSellParcel; 163 public event SellParcelHandler OnSellParcel;
@@ -149,6 +170,8 @@ namespace OpenSim.Region.Framework.Scenes
149 public event DelinkObjectHandler OnDelinkObject; 170 public event DelinkObjectHandler OnDelinkObject;
150 public event CreateObjectInventoryHandler OnCreateObjectInventory; 171 public event CreateObjectInventoryHandler OnCreateObjectInventory;
151 public event CopyObjectInventoryHandler OnCopyObjectInventory; 172 public event CopyObjectInventoryHandler OnCopyObjectInventory;
173 public event DoObjectInvToObjectInv OnDoObjectInvToObjectInv;
174 public event DoDropInObjectInv OnDropInObjectInv;
152 public event DeleteObjectInventoryHandler OnDeleteObjectInventory; 175 public event DeleteObjectInventoryHandler OnDeleteObjectInventory;
153 public event TransferObjectInventoryHandler OnTransferObjectInventory; 176 public event TransferObjectInventoryHandler OnTransferObjectInventory;
154 public event CreateUserInventoryHandler OnCreateUserInventory; 177 public event CreateUserInventoryHandler OnCreateUserInventory;
@@ -163,7 +186,7 @@ namespace OpenSim.Region.Framework.Scenes
163 186
164 #region Object Permission Checks 187 #region Object Permission Checks
165 188
166 public uint GenerateClientFlags(UUID userID, UUID objectID) 189 public uint GenerateClientFlags( SceneObjectPart part, ScenePresence sp)
167 { 190 {
168 // libomv will moan about PrimFlags.ObjectYouOfficer being 191 // libomv will moan about PrimFlags.ObjectYouOfficer being
169 // obsolete... 192 // obsolete...
@@ -175,12 +198,9 @@ namespace OpenSim.Region.Framework.Scenes
175 PrimFlags.ObjectTransfer | 198 PrimFlags.ObjectTransfer |
176 PrimFlags.ObjectYouOwner | 199 PrimFlags.ObjectYouOwner |
177 PrimFlags.ObjectAnyOwner | 200 PrimFlags.ObjectAnyOwner |
178 PrimFlags.ObjectOwnerModify | 201 PrimFlags.ObjectOwnerModify;
179 PrimFlags.ObjectYouOfficer;
180#pragma warning restore 0612 202#pragma warning restore 0612
181 203
182 SceneObjectPart part = m_scene.GetSceneObjectPart(objectID);
183
184 if (part == null) 204 if (part == null)
185 return 0; 205 return 0;
186 206
@@ -192,7 +212,7 @@ namespace OpenSim.Region.Framework.Scenes
192 Delegate[] list = handlerGenerateClientFlags.GetInvocationList(); 212 Delegate[] list = handlerGenerateClientFlags.GetInvocationList();
193 foreach (GenerateClientFlagsHandler check in list) 213 foreach (GenerateClientFlagsHandler check in list)
194 { 214 {
195 perms &= check(userID, objectID); 215 perms &= check(part, sp, perms);
196 } 216 }
197 } 217 }
198 return perms; 218 return perms;
@@ -244,7 +264,7 @@ namespace OpenSim.Region.Framework.Scenes
244 Delegate[] list = handler.GetInvocationList(); 264 Delegate[] list = handler.GetInvocationList();
245 foreach (RezObjectHandler h in list) 265 foreach (RezObjectHandler h in list)
246 { 266 {
247 if (h(objectCount, owner,objectPosition, m_scene) == false) 267 if (h(objectCount, owner,objectPosition) == false)
248 return false; 268 return false;
249 } 269 }
250 } 270 }
@@ -257,113 +277,184 @@ namespace OpenSim.Region.Framework.Scenes
257 public bool CanDeleteObject(UUID objectID, UUID deleter) 277 public bool CanDeleteObject(UUID objectID, UUID deleter)
258 { 278 {
259 bool result = true; 279 bool result = true;
260 280
261 DeleteObjectHandler handler = OnDeleteObject; 281 DeleteObjectHandlerByIDs handler = OnDeleteObjectByIDs;
262 if (handler != null) 282 if (handler != null)
263 { 283 {
264 Delegate[] list = handler.GetInvocationList(); 284 Delegate[] list = handler.GetInvocationList();
265 foreach (DeleteObjectHandler h in list) 285 foreach (DeleteObjectHandlerByIDs h in list)
266 { 286 {
267 if (h(objectID, deleter, m_scene) == false) 287 if (h(objectID, deleter) == false)
268 { 288 {
269 result = false; 289 result = false;
270 break; 290 break;
271 } 291 }
272 } 292 }
273 } 293 }
274
275 return result; 294 return result;
276 } 295 }
277 296
297 public bool CanDeleteObject(SceneObjectGroup sog, IClientAPI client)
298 {
299 DeleteObjectHandler handler = OnDeleteObject;
300 if (handler != null)
301 {
302 if(sog == null || client == null || client.SceneAgent == null)
303 return false;
304
305 ScenePresence sp = client.SceneAgent as ScenePresence;
306
307 Delegate[] list = handler.GetInvocationList();
308 foreach (DeleteObjectHandler h in list)
309 {
310 if (h(sog, sp) == false)
311 return false;
312 }
313 }
314
315 return true;
316 }
317
278 public bool CanTransferObject(UUID objectID, UUID recipient) 318 public bool CanTransferObject(UUID objectID, UUID recipient)
279 { 319 {
280 bool result = true;
281
282 TransferObjectHandler handler = OnTransferObject; 320 TransferObjectHandler handler = OnTransferObject;
283 if (handler != null) 321 if (handler != null)
284 { 322 {
285 Delegate[] list = handler.GetInvocationList(); 323 Delegate[] list = handler.GetInvocationList();
286 foreach (TransferObjectHandler h in list) 324 foreach (TransferObjectHandler h in list)
287 { 325 {
288 if (h(objectID, recipient, m_scene) == false) 326 if (h(objectID, recipient) == false)
289 { 327 return false;
290 result = false;
291 break;
292 }
293 } 328 }
294 } 329 }
295 330 return true;
296 return result;
297 } 331 }
298 332
299 #endregion 333 #endregion
300 334
301 #region TAKE OBJECT 335 #region TAKE OBJECT
302 public bool CanTakeObject(UUID objectID, UUID AvatarTakingUUID) 336 public bool CanTakeObject(SceneObjectGroup sog, ScenePresence sp)
303 { 337 {
304 bool result = true;
305
306 TakeObjectHandler handler = OnTakeObject; 338 TakeObjectHandler handler = OnTakeObject;
307 if (handler != null) 339 if (handler != null)
308 { 340 {
341 if(sog == null || sp == null)
342 return false;
343
309 Delegate[] list = handler.GetInvocationList(); 344 Delegate[] list = handler.GetInvocationList();
310 foreach (TakeObjectHandler h in list) 345 foreach (TakeObjectHandler h in list)
311 { 346 {
312 if (h(objectID, AvatarTakingUUID, m_scene) == false) 347 if (h(sog, sp) == false)
313 { 348 return false;
314 result = false;
315 break;
316 }
317 } 349 }
318 } 350 }
319
320// m_log.DebugFormat( 351// m_log.DebugFormat(
321// "[SCENE PERMISSIONS]: CanTakeObject() fired for object {0}, taker {1}, result {2}", 352// "[SCENE PERMISSIONS]: CanTakeObject() fired for object {0}, taker {1}, result {2}",
322// objectID, AvatarTakingUUID, result); 353// objectID, AvatarTakingUUID, result);
323 354 return true;
324 return result;
325 } 355 }
326 356
327 #endregion 357 #endregion
328 358
359 #region SELL GROUP OBJECT
360 public bool CanSellGroupObject(UUID userID, UUID groupID)
361 {
362 SellGroupObjectHandler handler = OnSellGroupObject;
363 if (handler != null)
364 {
365 Delegate[] list = handler.GetInvocationList();
366 foreach (SellGroupObjectHandler h in list)
367 {
368 if (h(userID, groupID) == false)
369 return false;
370 }
371 }
372 //m_log.DebugFormat(
373 // "[SCENE PERMISSIONS]: CanSellGroupObject() fired for user {0}, group {1}, result {2}",
374 // userID, groupID, result);
375 return true;
376 }
377
378 #endregion
379
380 #region SELL OBJECT
381 public bool CanSellObject(IClientAPI client, SceneObjectGroup sog, byte saleType)
382 {
383 SellObjectHandler handler = OnSellObject;
384 if (handler != null)
385 {
386 if(sog == null || client == null || client.SceneAgent == null)
387 return false;
388
389 ScenePresence sp = client.SceneAgent as ScenePresence;
390 Delegate[] list = handler.GetInvocationList();
391 foreach (SellObjectHandler h in list)
392 {
393 if (h(sog, sp, saleType) == false)
394 return false;
395 }
396 }
397 return true;
398 }
399
400 public bool CanSellObject(UUID userID, SceneObjectGroup sog, byte saleType)
401 {
402 SellObjectHandlerByUserID handler = OnSellObjectByUserID;
403 if (handler != null)
404 {
405 if(sog == null)
406 return false;
407 Delegate[] list = handler.GetInvocationList();
408 foreach (SellObjectHandlerByUserID h in list)
409 {
410 if (h(sog, userID, saleType) == false)
411 return false;
412 }
413 }
414 return true;
415 }
416
417 #endregion
418
419
329 #region TAKE COPY OBJECT 420 #region TAKE COPY OBJECT
330 public bool CanTakeCopyObject(UUID objectID, UUID userID) 421 public bool CanTakeCopyObject(SceneObjectGroup sog, ScenePresence sp)
331 { 422 {
332 bool result = true;
333
334 TakeCopyObjectHandler handler = OnTakeCopyObject; 423 TakeCopyObjectHandler handler = OnTakeCopyObject;
335 if (handler != null) 424 if (handler != null)
336 { 425 {
426 if(sog == null || sp == null)
427 return false;
337 Delegate[] list = handler.GetInvocationList(); 428 Delegate[] list = handler.GetInvocationList();
338 foreach (TakeCopyObjectHandler h in list) 429 foreach (TakeCopyObjectHandler h in list)
339 { 430 {
340 if (h(objectID, userID, m_scene) == false) 431 if (h(sog, sp) == false)
341 { 432 return false;
342 result = false;
343 break;
344 }
345 } 433 }
346 } 434 }
347
348// m_log.DebugFormat( 435// m_log.DebugFormat(
349// "[SCENE PERMISSIONS]: CanTakeCopyObject() fired for object {0}, user {1}, result {2}", 436// "[SCENE PERMISSIONS]: CanTakeCopyObject() fired for object {0}, user {1}, result {2}",
350// objectID, userID, result); 437// objectID, userID, result);
351 438 return true;
352 return result;
353 } 439 }
354 440
355 #endregion 441 #endregion
356 442
357 #region DUPLICATE OBJECT 443 #region DUPLICATE OBJECT
358 public bool CanDuplicateObject(int objectCount, UUID objectID, UUID owner, Vector3 objectPosition) 444 public bool CanDuplicateObject(SceneObjectGroup sog, UUID agentID)
359 { 445 {
360 DuplicateObjectHandler handler = OnDuplicateObject; 446 DuplicateObjectHandler handler = OnDuplicateObject;
361 if (handler != null) 447 if (handler != null)
362 { 448 {
449 if(sog == null || sog.IsDeleted)
450 return false;
451 ScenePresence sp = m_scene.GetScenePresence(agentID);
452 if(sp == null || sp.IsDeleted)
453 return false;
363 Delegate[] list = handler.GetInvocationList(); 454 Delegate[] list = handler.GetInvocationList();
364 foreach (DuplicateObjectHandler h in list) 455 foreach (DuplicateObjectHandler h in list)
365 { 456 {
366 if (h(objectCount, objectID, owner, m_scene, objectPosition) == false) 457 if (h(sog, sp) == false)
367 return false; 458 return false;
368 } 459 }
369 } 460 }
@@ -372,22 +463,74 @@ namespace OpenSim.Region.Framework.Scenes
372 463
373 #endregion 464 #endregion
374 465
466 #region persence EDIT or MOVE OBJECT
467 private const uint CANSELECTMASK = (uint)(
468 PrimFlags.ObjectMove |
469 PrimFlags.ObjectModify |
470 PrimFlags.ObjectOwnerModify
471 );
472
473 public bool CanChangeSelectedState(SceneObjectPart part, ScenePresence sp)
474 {
475 uint perms = GenerateClientFlags(part, sp);
476 return (perms & CANSELECTMASK) != 0;
477 }
478
479 #endregion
375 #region EDIT OBJECT 480 #region EDIT OBJECT
376 public bool CanEditObject(UUID objectID, UUID editorID) 481 public bool CanEditObject(UUID objectID, UUID editorID)
377 { 482 {
483 EditObjectByIDsHandler handler = OnEditObjectByIDs;
484 if (handler != null)
485 {
486 Delegate[] list = handler.GetInvocationList();
487 foreach (EditObjectByIDsHandler h in list)
488 {
489 if (h(objectID, editorID) == false)
490 return false;
491 }
492 }
493 return true;
494 }
495
496 public bool CanEditObject(SceneObjectGroup sog, IClientAPI client)
497 {
378 EditObjectHandler handler = OnEditObject; 498 EditObjectHandler handler = OnEditObject;
379 if (handler != null) 499 if (handler != null)
380 { 500 {
501 if(sog == null || client == null || client.SceneAgent == null)
502 return false;
503
504 ScenePresence sp = client.SceneAgent as ScenePresence;
505
381 Delegate[] list = handler.GetInvocationList(); 506 Delegate[] list = handler.GetInvocationList();
382 foreach (EditObjectHandler h in list) 507 foreach (EditObjectHandler h in list)
383 { 508 {
384 if (h(objectID, editorID, m_scene) == false) 509 if (h(sog, sp) == false)
510 return false;
511 }
512 }
513 return true;
514 }
515
516 public bool CanEditObjectPermissions(SceneObjectGroup sog, UUID editorID)
517 {
518 EditObjectPermsHandler handler = OnEditObjectPerms;
519 if (handler != null)
520 {
521 if(sog == null)
522 return false;
523 Delegate[] list = handler.GetInvocationList();
524 foreach (EditObjectPermsHandler h in list)
525 {
526 if (h(sog, editorID) == false)
385 return false; 527 return false;
386 } 528 }
387 } 529 }
388 return true; 530 return true;
389 } 531 }
390 532
533
391 public bool CanEditObjectInventory(UUID objectID, UUID editorID) 534 public bool CanEditObjectInventory(UUID objectID, UUID editorID)
392 { 535 {
393 EditObjectInventoryHandler handler = OnEditObjectInventory; 536 EditObjectInventoryHandler handler = OnEditObjectInventory;
@@ -396,7 +539,7 @@ namespace OpenSim.Region.Framework.Scenes
396 Delegate[] list = handler.GetInvocationList(); 539 Delegate[] list = handler.GetInvocationList();
397 foreach (EditObjectInventoryHandler h in list) 540 foreach (EditObjectInventoryHandler h in list)
398 { 541 {
399 if (h(objectID, editorID, m_scene) == false) 542 if (h(objectID, editorID) == false)
400 return false; 543 return false;
401 } 544 }
402 } 545 }
@@ -406,15 +549,20 @@ namespace OpenSim.Region.Framework.Scenes
406 #endregion 549 #endregion
407 550
408 #region MOVE OBJECT 551 #region MOVE OBJECT
409 public bool CanMoveObject(UUID objectID, UUID moverID) 552 public bool CanMoveObject(SceneObjectGroup sog, IClientAPI client)
410 { 553 {
411 MoveObjectHandler handler = OnMoveObject; 554 MoveObjectHandler handler = OnMoveObject;
412 if (handler != null) 555 if (handler != null)
413 { 556 {
557 if(sog == null || client == null || client.SceneAgent == null)
558 return false;
559
560 ScenePresence sp = client.SceneAgent as ScenePresence;
561
414 Delegate[] list = handler.GetInvocationList(); 562 Delegate[] list = handler.GetInvocationList();
415 foreach (MoveObjectHandler h in list) 563 foreach (MoveObjectHandler h in list)
416 { 564 {
417 if (h(objectID, moverID, m_scene) == false) 565 if (h(sog, sp) == false)
418 return false; 566 return false;
419 } 567 }
420 } 568 }
@@ -424,7 +572,7 @@ namespace OpenSim.Region.Framework.Scenes
424 #endregion 572 #endregion
425 573
426 #region OBJECT ENTRY 574 #region OBJECT ENTRY
427 public bool CanObjectEntry(UUID objectID, bool enteringRegion, Vector3 newPoint) 575 public bool CanObjectEntry(SceneObjectGroup sog, bool enteringRegion, Vector3 newPoint)
428 { 576 {
429 ObjectEntryHandler handler = OnObjectEntry; 577 ObjectEntryHandler handler = OnObjectEntry;
430 if (handler != null) 578 if (handler != null)
@@ -432,7 +580,22 @@ namespace OpenSim.Region.Framework.Scenes
432 Delegate[] list = handler.GetInvocationList(); 580 Delegate[] list = handler.GetInvocationList();
433 foreach (ObjectEntryHandler h in list) 581 foreach (ObjectEntryHandler h in list)
434 { 582 {
435 if (h(objectID, enteringRegion, newPoint, m_scene) == false) 583 if (h(sog, enteringRegion, newPoint) == false)
584 return false;
585 }
586 }
587 return true;
588 }
589
590 public bool CanObjectEnterWithScripts(SceneObjectGroup sog, ILandObject land)
591 {
592 ObjectEnterWithScriptsHandler handler = OnObjectEnterWithScripts;
593 if (handler != null)
594 {
595 Delegate[] list = handler.GetInvocationList();
596 foreach (ObjectEnterWithScriptsHandler h in list)
597 {
598 if (h(sog, land) == false)
436 return false; 599 return false;
437 } 600 }
438 } 601 }
@@ -442,29 +605,30 @@ namespace OpenSim.Region.Framework.Scenes
442 #endregion 605 #endregion
443 606
444 #region RETURN OBJECT 607 #region RETURN OBJECT
445 public bool CanReturnObjects(ILandObject land, UUID user, List<SceneObjectGroup> objects) 608 public bool CanReturnObjects(ILandObject land, IClientAPI client, List<SceneObjectGroup> objects)
446 { 609 {
447 bool result = true;
448
449 ReturnObjectsHandler handler = OnReturnObjects; 610 ReturnObjectsHandler handler = OnReturnObjects;
450 if (handler != null) 611 if (handler != null)
451 { 612 {
613 if(objects == null)
614 return false;
615
616 ScenePresence sp = null;
617 if(client != null && client.SceneAgent != null)
618 sp = client.SceneAgent as ScenePresence;
619
452 Delegate[] list = handler.GetInvocationList(); 620 Delegate[] list = handler.GetInvocationList();
453 foreach (ReturnObjectsHandler h in list) 621 foreach (ReturnObjectsHandler h in list)
454 { 622 {
455 if (h(land, user, objects, m_scene) == false) 623 if (h(land, sp, objects) == false)
456 { 624 return false;
457 result = false;
458 break;
459 }
460 } 625 }
461 } 626 }
462
463// m_log.DebugFormat( 627// m_log.DebugFormat(
464// "[SCENE PERMISSIONS]: CanReturnObjects() fired for user {0} for {1} objects on {2}, result {3}", 628// "[SCENE PERMISSIONS]: CanReturnObjects() fired for user {0} for {1} objects on {2}, result {3}",
465// user, objects.Count, land.LandData.Name, result); 629// user, objects.Count, land.LandData.Name, result);
466 630
467 return result; 631 return true;
468 } 632 }
469 633
470 #endregion 634 #endregion
@@ -478,7 +642,7 @@ namespace OpenSim.Region.Framework.Scenes
478 Delegate[] list = handler.GetInvocationList(); 642 Delegate[] list = handler.GetInvocationList();
479 foreach (InstantMessageHandler h in list) 643 foreach (InstantMessageHandler h in list)
480 { 644 {
481 if (h(user, target, m_scene) == false) 645 if (h(user, target) == false)
482 return false; 646 return false;
483 } 647 }
484 } 648 }
@@ -496,7 +660,7 @@ namespace OpenSim.Region.Framework.Scenes
496 Delegate[] list = handler.GetInvocationList(); 660 Delegate[] list = handler.GetInvocationList();
497 foreach (InventoryTransferHandler h in list) 661 foreach (InventoryTransferHandler h in list)
498 { 662 {
499 if (h(user, target, m_scene) == false) 663 if (h(user, target) == false)
500 return false; 664 return false;
501 } 665 }
502 } 666 }
@@ -514,7 +678,7 @@ namespace OpenSim.Region.Framework.Scenes
514 Delegate[] list = handler.GetInvocationList(); 678 Delegate[] list = handler.GetInvocationList();
515 foreach (ViewScriptHandler h in list) 679 foreach (ViewScriptHandler h in list)
516 { 680 {
517 if (h(script, objectID, user, m_scene) == false) 681 if (h(script, objectID, user) == false)
518 return false; 682 return false;
519 } 683 }
520 } 684 }
@@ -529,7 +693,7 @@ namespace OpenSim.Region.Framework.Scenes
529 Delegate[] list = handler.GetInvocationList(); 693 Delegate[] list = handler.GetInvocationList();
530 foreach (ViewNotecardHandler h in list) 694 foreach (ViewNotecardHandler h in list)
531 { 695 {
532 if (h(script, objectID, user, m_scene) == false) 696 if (h(script, objectID, user) == false)
533 return false; 697 return false;
534 } 698 }
535 } 699 }
@@ -547,7 +711,7 @@ namespace OpenSim.Region.Framework.Scenes
547 Delegate[] list = handler.GetInvocationList(); 711 Delegate[] list = handler.GetInvocationList();
548 foreach (EditScriptHandler h in list) 712 foreach (EditScriptHandler h in list)
549 { 713 {
550 if (h(script, objectID, user, m_scene) == false) 714 if (h(script, objectID, user) == false)
551 return false; 715 return false;
552 } 716 }
553 } 717 }
@@ -562,7 +726,7 @@ namespace OpenSim.Region.Framework.Scenes
562 Delegate[] list = handler.GetInvocationList(); 726 Delegate[] list = handler.GetInvocationList();
563 foreach (EditNotecardHandler h in list) 727 foreach (EditNotecardHandler h in list)
564 { 728 {
565 if (h(script, objectID, user, m_scene) == false) 729 if (h(script, objectID, user) == false)
566 return false; 730 return false;
567 } 731 }
568 } 732 }
@@ -574,19 +738,37 @@ namespace OpenSim.Region.Framework.Scenes
574 #region RUN SCRIPT (When Script Placed in Object) 738 #region RUN SCRIPT (When Script Placed in Object)
575 public bool CanRunScript(UUID script, UUID objectID, UUID user) 739 public bool CanRunScript(UUID script, UUID objectID, UUID user)
576 { 740 {
741 RunScriptHandlerByIDs handler = OnRunScriptByIDs;
742 if (handler != null)
743 {
744 Delegate[] list = handler.GetInvocationList();
745 foreach (RunScriptHandlerByIDs h in list)
746 {
747 if (h(script, objectID, user) == false)
748 return false;
749 }
750 }
751 return true;
752 }
753
754 public bool CanRunScript(TaskInventoryItem item, SceneObjectPart part)
755 {
577 RunScriptHandler handler = OnRunScript; 756 RunScriptHandler handler = OnRunScript;
578 if (handler != null) 757 if (handler != null)
579 { 758 {
759 if(item == null || part == null)
760 return false;
580 Delegate[] list = handler.GetInvocationList(); 761 Delegate[] list = handler.GetInvocationList();
581 foreach (RunScriptHandler h in list) 762 foreach (RunScriptHandler h in list)
582 { 763 {
583 if (h(script, objectID, user, m_scene) == false) 764 if (h(item, part) == false)
584 return false; 765 return false;
585 } 766 }
586 } 767 }
587 return true; 768 return true;
588 } 769 }
589 770
771
590 #endregion 772 #endregion
591 773
592 #region COMPILE SCRIPT (When Script needs to get (re)compiled) 774 #region COMPILE SCRIPT (When Script needs to get (re)compiled)
@@ -598,7 +780,7 @@ namespace OpenSim.Region.Framework.Scenes
598 Delegate[] list = handler.GetInvocationList(); 780 Delegate[] list = handler.GetInvocationList();
599 foreach (CompileScriptHandler h in list) 781 foreach (CompileScriptHandler h in list)
600 { 782 {
601 if (h(ownerUUID, scriptType, m_scene) == false) 783 if (h(ownerUUID, scriptType) == false)
602 return false; 784 return false;
603 } 785 }
604 } 786 }
@@ -616,7 +798,7 @@ namespace OpenSim.Region.Framework.Scenes
616 Delegate[] list = handler.GetInvocationList(); 798 Delegate[] list = handler.GetInvocationList();
617 foreach (StartScriptHandler h in list) 799 foreach (StartScriptHandler h in list)
618 { 800 {
619 if (h(script, user, m_scene) == false) 801 if (h(script, user) == false)
620 return false; 802 return false;
621 } 803 }
622 } 804 }
@@ -634,7 +816,7 @@ namespace OpenSim.Region.Framework.Scenes
634 Delegate[] list = handler.GetInvocationList(); 816 Delegate[] list = handler.GetInvocationList();
635 foreach (StopScriptHandler h in list) 817 foreach (StopScriptHandler h in list)
636 { 818 {
637 if (h(script, user, m_scene) == false) 819 if (h(script, user) == false)
638 return false; 820 return false;
639 } 821 }
640 } 822 }
@@ -652,7 +834,7 @@ namespace OpenSim.Region.Framework.Scenes
652 Delegate[] list = handler.GetInvocationList(); 834 Delegate[] list = handler.GetInvocationList();
653 foreach (ResetScriptHandler h in list) 835 foreach (ResetScriptHandler h in list)
654 { 836 {
655 if (h(prim, script, user, m_scene) == false) 837 if (h(prim, script, user) == false)
656 return false; 838 return false;
657 } 839 }
658 } 840 }
@@ -670,7 +852,7 @@ namespace OpenSim.Region.Framework.Scenes
670 Delegate[] list = handler.GetInvocationList(); 852 Delegate[] list = handler.GetInvocationList();
671 foreach (TerraformLandHandler h in list) 853 foreach (TerraformLandHandler h in list)
672 { 854 {
673 if (h(user, pos, m_scene) == false) 855 if (h(user, pos) == false)
674 return false; 856 return false;
675 } 857 }
676 } 858 }
@@ -688,7 +870,7 @@ namespace OpenSim.Region.Framework.Scenes
688 Delegate[] list = handler.GetInvocationList(); 870 Delegate[] list = handler.GetInvocationList();
689 foreach (RunConsoleCommandHandler h in list) 871 foreach (RunConsoleCommandHandler h in list)
690 { 872 {
691 if (h(user, m_scene) == false) 873 if (h(user) == false)
692 return false; 874 return false;
693 } 875 }
694 } 876 }
@@ -706,7 +888,7 @@ namespace OpenSim.Region.Framework.Scenes
706 Delegate[] list = handler.GetInvocationList(); 888 Delegate[] list = handler.GetInvocationList();
707 foreach (IssueEstateCommandHandler h in list) 889 foreach (IssueEstateCommandHandler h in list)
708 { 890 {
709 if (h(user, m_scene, ownerCommand) == false) 891 if (h(user, ownerCommand) == false)
710 return false; 892 return false;
711 } 893 }
712 } 894 }
@@ -717,13 +899,13 @@ namespace OpenSim.Region.Framework.Scenes
717 #region CAN BE GODLIKE 899 #region CAN BE GODLIKE
718 public bool IsGod(UUID user) 900 public bool IsGod(UUID user)
719 { 901 {
720 IsGodHandler handler = OnIsGod; 902 IsAdministratorHandler handler = OnIsAdministrator;
721 if (handler != null) 903 if (handler != null)
722 { 904 {
723 Delegate[] list = handler.GetInvocationList(); 905 Delegate[] list = handler.GetInvocationList();
724 foreach (IsGodHandler h in list) 906 foreach (IsAdministratorHandler h in list)
725 { 907 {
726 if (h(user, m_scene) == false) 908 if (h(user) == false)
727 return false; 909 return false;
728 } 910 }
729 } 911 }
@@ -738,7 +920,7 @@ namespace OpenSim.Region.Framework.Scenes
738 Delegate[] list = handler.GetInvocationList(); 920 Delegate[] list = handler.GetInvocationList();
739 foreach (IsGridGodHandler h in list) 921 foreach (IsGridGodHandler h in list)
740 { 922 {
741 if (h(user, m_scene) == false) 923 if (h(user) == false)
742 return false; 924 return false;
743 } 925 }
744 } 926 }
@@ -761,9 +943,24 @@ namespace OpenSim.Region.Framework.Scenes
761 } 943 }
762 #endregion 944 #endregion
763 945
946 public bool IsEstateManager(UUID user)
947 {
948 IsEstateManagerHandler handler = OnIsEstateManager;
949 if (handler != null)
950 {
951 Delegate[] list = handler.GetInvocationList();
952 foreach (IsEstateManagerHandler h in list)
953 {
954 if (h(user) == false)
955 return false;
956 }
957 }
958 return true;
959 }
960
764 #region EDIT PARCEL 961 #region EDIT PARCEL
765 962
766 public bool CanEditParcelProperties(UUID user, ILandObject parcel, GroupPowers p) 963 public bool CanEditParcelProperties(UUID user, ILandObject parcel, GroupPowers p, bool allowManager)
767 { 964 {
768 EditParcelPropertiesHandler handler = OnEditParcelProperties; 965 EditParcelPropertiesHandler handler = OnEditParcelProperties;
769 if (handler != null) 966 if (handler != null)
@@ -771,7 +968,7 @@ namespace OpenSim.Region.Framework.Scenes
771 Delegate[] list = handler.GetInvocationList(); 968 Delegate[] list = handler.GetInvocationList();
772 foreach (EditParcelPropertiesHandler h in list) 969 foreach (EditParcelPropertiesHandler h in list)
773 { 970 {
774 if (h(user, parcel, p, m_scene) == false) 971 if (h(user, parcel, p, allowManager) == false)
775 return false; 972 return false;
776 } 973 }
777 } 974 }
@@ -788,7 +985,7 @@ namespace OpenSim.Region.Framework.Scenes
788 Delegate[] list = handler.GetInvocationList(); 985 Delegate[] list = handler.GetInvocationList();
789 foreach (SellParcelHandler h in list) 986 foreach (SellParcelHandler h in list)
790 { 987 {
791 if (h(user, parcel, m_scene) == false) 988 if (h(user, parcel) == false)
792 return false; 989 return false;
793 } 990 }
794 } 991 }
@@ -805,7 +1002,7 @@ namespace OpenSim.Region.Framework.Scenes
805 Delegate[] list = handler.GetInvocationList(); 1002 Delegate[] list = handler.GetInvocationList();
806 foreach (AbandonParcelHandler h in list) 1003 foreach (AbandonParcelHandler h in list)
807 { 1004 {
808 if (h(user, parcel, m_scene) == false) 1005 if (h(user, parcel) == false)
809 return false; 1006 return false;
810 } 1007 }
811 } 1008 }
@@ -821,7 +1018,7 @@ namespace OpenSim.Region.Framework.Scenes
821 Delegate[] list = handler.GetInvocationList(); 1018 Delegate[] list = handler.GetInvocationList();
822 foreach (ReclaimParcelHandler h in list) 1019 foreach (ReclaimParcelHandler h in list)
823 { 1020 {
824 if (h(user, parcel, m_scene) == false) 1021 if (h(user, parcel) == false)
825 return false; 1022 return false;
826 } 1023 }
827 } 1024 }
@@ -836,22 +1033,27 @@ namespace OpenSim.Region.Framework.Scenes
836 Delegate[] list = handler.GetInvocationList(); 1033 Delegate[] list = handler.GetInvocationList();
837 foreach (DeedParcelHandler h in list) 1034 foreach (DeedParcelHandler h in list)
838 { 1035 {
839 if (h(user, parcel, m_scene) == false) 1036 if (h(user, parcel) == false)
840 return false; 1037 return false;
841 } 1038 }
842 } 1039 }
843 return true; 1040 return true;
844 } 1041 }
845 1042
846 public bool CanDeedObject(UUID user, UUID group) 1043 public bool CanDeedObject(IClientAPI client, SceneObjectGroup sog, UUID targetGroupID)
847 { 1044 {
848 DeedObjectHandler handler = OnDeedObject; 1045 DeedObjectHandler handler = OnDeedObject;
849 if (handler != null) 1046 if (handler != null)
850 { 1047 {
1048 if(sog == null || client == null || client.SceneAgent == null || targetGroupID == UUID.Zero)
1049 return false;
1050
1051 ScenePresence sp = client.SceneAgent as ScenePresence;
1052
851 Delegate[] list = handler.GetInvocationList(); 1053 Delegate[] list = handler.GetInvocationList();
852 foreach (DeedObjectHandler h in list) 1054 foreach (DeedObjectHandler h in list)
853 { 1055 {
854 if (h(user, group, m_scene) == false) 1056 if (h(sp, sog, targetGroupID) == false)
855 return false; 1057 return false;
856 } 1058 }
857 } 1059 }
@@ -866,7 +1068,7 @@ namespace OpenSim.Region.Framework.Scenes
866 Delegate[] list = handler.GetInvocationList(); 1068 Delegate[] list = handler.GetInvocationList();
867 foreach (BuyLandHandler h in list) 1069 foreach (BuyLandHandler h in list)
868 { 1070 {
869 if (h(user, parcel, m_scene) == false) 1071 if (h(user, parcel) == false)
870 return false; 1072 return false;
871 } 1073 }
872 } 1074 }
@@ -942,6 +1144,45 @@ namespace OpenSim.Region.Framework.Scenes
942 return true; 1144 return true;
943 } 1145 }
944 1146
1147 public bool CanDoObjectInvToObjectInv(TaskInventoryItem item, SceneObjectPart sourcePart, SceneObjectPart destPart)
1148 {
1149 DoObjectInvToObjectInv handler = OnDoObjectInvToObjectInv;
1150 if (handler != null)
1151 {
1152 if (sourcePart == null || destPart == null || item == null)
1153 return false;
1154 Delegate[] list = handler.GetInvocationList();
1155 foreach (DoObjectInvToObjectInv h in list)
1156 {
1157 if (h(item, sourcePart, destPart) == false)
1158 return false;
1159 }
1160 }
1161 return true;
1162 }
1163
1164 public bool CanDropInObjectInv(InventoryItemBase item, IClientAPI client, SceneObjectPart destPart)
1165 {
1166 DoDropInObjectInv handler = OnDropInObjectInv;
1167 if (handler != null)
1168 {
1169 if (client == null || client.SceneAgent == null|| destPart == null || item == null)
1170 return false;
1171
1172 ScenePresence sp = client.SceneAgent as ScenePresence;
1173 if(sp == null || sp.IsDeleted)
1174 return false;
1175
1176 Delegate[] list = handler.GetInvocationList();
1177 foreach (DoDropInObjectInv h in list)
1178 {
1179 if (h(item, sp, destPart) == false)
1180 return false;
1181 }
1182 }
1183 return true;
1184 }
1185
945 public bool CanDeleteObjectInventory(UUID itemID, UUID objectID, UUID userID) 1186 public bool CanDeleteObjectInventory(UUID itemID, UUID objectID, UUID userID)
946 { 1187 {
947 DeleteObjectInventoryHandler handler = OnDeleteObjectInventory; 1188 DeleteObjectInventoryHandler handler = OnDeleteObjectInventory;
@@ -956,7 +1197,7 @@ namespace OpenSim.Region.Framework.Scenes
956 } 1197 }
957 return true; 1198 return true;
958 } 1199 }
959 1200
960 public bool CanTransferObjectInventory(UUID itemID, UUID objectID, UUID userID) 1201 public bool CanTransferObjectInventory(UUID itemID, UUID objectID, UUID userID)
961 { 1202 {
962 TransferObjectInventoryHandler handler = OnTransferObjectInventory; 1203 TransferObjectInventoryHandler handler = OnTransferObjectInventory;
@@ -971,7 +1212,7 @@ namespace OpenSim.Region.Framework.Scenes
971 } 1212 }
972 return true; 1213 return true;
973 } 1214 }
974 1215
975 /// <summary> 1216 /// <summary>
976 /// Check whether the specified user is allowed to create the given inventory type in their inventory. 1217 /// Check whether the specified user is allowed to create the given inventory type in their inventory.
977 /// </summary> 1218 /// </summary>
@@ -991,8 +1232,8 @@ namespace OpenSim.Region.Framework.Scenes
991 } 1232 }
992 } 1233 }
993 return true; 1234 return true;
994 } 1235 }
995 1236
996 /// <summary> 1237 /// <summary>
997 /// Check whether the specified user is allowed to edit the given inventory item within their own inventory. 1238 /// Check whether the specified user is allowed to edit the given inventory item within their own inventory.
998 /// </summary> 1239 /// </summary>
@@ -1013,7 +1254,7 @@ namespace OpenSim.Region.Framework.Scenes
1013 } 1254 }
1014 return true; 1255 return true;
1015 } 1256 }
1016 1257
1017 /// <summary> 1258 /// <summary>
1018 /// Check whether the specified user is allowed to copy the given inventory item from their own inventory. 1259 /// Check whether the specified user is allowed to copy the given inventory item from their own inventory.
1019 /// </summary> 1260 /// </summary>
@@ -1034,7 +1275,7 @@ namespace OpenSim.Region.Framework.Scenes
1034 } 1275 }
1035 return true; 1276 return true;
1036 } 1277 }
1037 1278
1038 /// <summary> 1279 /// <summary>
1039 /// Check whether the specified user is allowed to edit the given inventory item within their own inventory. 1280 /// Check whether the specified user is allowed to edit the given inventory item within their own inventory.
1040 /// </summary> 1281 /// </summary>
@@ -1055,7 +1296,7 @@ namespace OpenSim.Region.Framework.Scenes
1055 } 1296 }
1056 return true; 1297 return true;
1057 } 1298 }
1058 1299
1059 public bool CanTransferUserInventory(UUID itemID, UUID userID, UUID recipientID) 1300 public bool CanTransferUserInventory(UUID itemID, UUID userID, UUID recipientID)
1060 { 1301 {
1061 TransferUserInventoryHandler handler = OnTransferUserInventory; 1302 TransferUserInventoryHandler handler = OnTransferUserInventory;
@@ -1070,7 +1311,7 @@ namespace OpenSim.Region.Framework.Scenes
1070 } 1311 }
1071 return true; 1312 return true;
1072 } 1313 }
1073 1314
1074 public bool CanTeleport(UUID userID) 1315 public bool CanTeleport(UUID userID)
1075 { 1316 {
1076 TeleportHandler handler = OnTeleport; 1317 TeleportHandler handler = OnTeleport;
@@ -1085,7 +1326,7 @@ namespace OpenSim.Region.Framework.Scenes
1085 } 1326 }
1086 return true; 1327 return true;
1087 } 1328 }
1088 1329
1089 public bool CanControlPrimMedia(UUID userID, UUID primID, int face) 1330 public bool CanControlPrimMedia(UUID userID, UUID primID, int face)
1090 { 1331 {
1091 ControlPrimMediaHandler handler = OnControlPrimMedia; 1332 ControlPrimMediaHandler handler = OnControlPrimMedia;
@@ -1099,8 +1340,8 @@ namespace OpenSim.Region.Framework.Scenes
1099 } 1340 }
1100 } 1341 }
1101 return true; 1342 return true;
1102 } 1343 }
1103 1344
1104 public bool CanInteractWithPrimMedia(UUID userID, UUID primID, int face) 1345 public bool CanInteractWithPrimMedia(UUID userID, UUID primID, int face)
1105 { 1346 {
1106 InteractWithPrimMediaHandler handler = OnInteractWithPrimMedia; 1347 InteractWithPrimMediaHandler handler = OnInteractWithPrimMedia;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 2fe6e22..15a0493 100644..100755
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -61,15 +61,12 @@ namespace OpenSim.Region.Framework.Scenes
61 { 61 {
62 private const long DEFAULT_MIN_TIME_FOR_PERSISTENCE = 60L; 62 private const long DEFAULT_MIN_TIME_FOR_PERSISTENCE = 60L;
63 private const long DEFAULT_MAX_TIME_FOR_PERSISTENCE = 600L; 63 private const long DEFAULT_MAX_TIME_FOR_PERSISTENCE = 600L;
64 64
65 public const int m_defaultNumberFramesStored = 10;
66 65
67 public delegate void SynchronizeSceneHandler(Scene scene); 66 public delegate void SynchronizeSceneHandler(Scene scene);
68 67
69 #region Fields 68 #region Fields
70 69
71 public bool EmergencyMonitoring = false;
72
73 /// <summary> 70 /// <summary>
74 /// Show debug information about animations. 71 /// Show debug information about animations.
75 /// </summary> 72 /// </summary>
@@ -91,7 +88,7 @@ namespace OpenSim.Region.Framework.Scenes
91 /// </summary> 88 /// </summary>
92 /// <remarks> 89 /// <remarks>
93 /// Even if false, the scene will still be saved on clean shutdown. 90 /// Even if false, the scene will still be saved on clean shutdown.
94 /// FIXME: Currently, setting this to false will mean that objects are not periodically returned from parcels. 91 /// FIXME: Currently, setting this to false will mean that objects are not periodically returned from parcels.
95 /// This needs to be fixed. 92 /// This needs to be fixed.
96 /// </remarks> 93 /// </remarks>
97 public bool PeriodicBackup { get; set; } 94 public bool PeriodicBackup { get; set; }
@@ -105,6 +102,7 @@ namespace OpenSim.Region.Framework.Scenes
105 /// <summary> 102 /// <summary>
106 /// If false then physical objects are disabled, though collisions will continue as normal. 103 /// If false then physical objects are disabled, though collisions will continue as normal.
107 /// </summary> 104 /// </summary>
105
108 public bool PhysicsEnabled 106 public bool PhysicsEnabled
109 { 107 {
110 get 108 get
@@ -174,6 +172,13 @@ namespace OpenSim.Region.Framework.Scenes
174 172
175 public SynchronizeSceneHandler SynchronizeScene; 173 public SynchronizeSceneHandler SynchronizeScene;
176 174
175 public bool ClampNegativeZ
176 {
177 get { return m_clampNegativeZ; }
178 }
179
180 private bool m_clampNegativeZ = false;
181
177 /// <summary> 182 /// <summary>
178 /// Used to prevent simultaneous calls to code that adds and removes agents. 183 /// Used to prevent simultaneous calls to code that adds and removes agents.
179 /// </summary> 184 /// </summary>
@@ -216,7 +221,7 @@ namespace OpenSim.Region.Framework.Scenes
216 /// <summary> 221 /// <summary>
217 /// Maximum value of the size of a physical prim in each axis 222 /// Maximum value of the size of a physical prim in each axis
218 /// </summary> 223 /// </summary>
219 public float m_maxPhys = 64; 224 public float m_maxPhys = 10;
220 225
221 /// <summary> 226 /// <summary>
222 /// Max prims an object will hold 227 /// Max prims an object will hold
@@ -228,57 +233,48 @@ namespace OpenSim.Region.Framework.Scenes
228 public bool m_allowScriptCrossings = true; 233 public bool m_allowScriptCrossings = true;
229 234
230 /// <summary> 235 /// <summary>
231 /// Can avatars cross from and to this region? 236 /// use legacy sittarget offsets to avoid contents breaks
232 /// </summary> 237 /// to compensate for SL bug
233 public bool AllowAvatarCrossing { get; set; }
234
235 public bool m_useFlySlow;
236 public bool m_useTrashOnDelete = true;
237
238 /// <summary>
239 /// Temporarily setting to trigger appearance resends at 60 second intervals.
240 /// </summary> 238 /// </summary>
241 public bool SendPeriodicAppearanceUpdates { get; set; } 239 public bool LegacySitOffsets = true;
242 240
243 /// <summary> 241 /// <summary>
244 /// How much a root agent has to change position before updates are sent to viewers. 242 /// Can avatars cross from and to this region?
245 /// </summary>
246 public float RootPositionUpdateTolerance { get; set; }
247
248 /// <summary>
249 /// How much a root agent has to rotate before updates are sent to viewers.
250 /// </summary> 243 /// </summary>
251 public float RootRotationUpdateTolerance { get; set; } 244 public bool AllowAvatarCrossing { get; set; }
252 245
253 /// <summary> 246 /// Max prims an Physical object will hold
254 /// How much a root agent has to change velocity before updates are sent to viewers.
255 /// </summary> 247 /// </summary>
256 public float RootVelocityUpdateTolerance { get; set; } 248 ///
249 public int m_linksetPhysCapacity = 0;
257 250
258 /// <summary> 251 /// <summary>
259 /// If greater than 1, we only send terse updates to other root agents on every n updates. 252 /// When placed outside the region's border, do we transfer the objects or
253 /// do we keep simulating them here?
260 /// </summary> 254 /// </summary>
261 public int RootTerseUpdatePeriod { get; set; } 255 public bool DisableObjectTransfer { get; set; }
262 256
263 /// <summary> 257 public bool m_useFlySlow;
264 /// If greater than 1, we only send terse updates to child agents on every n updates. 258 public bool m_useTrashOnDelete = true;
265 /// </summary>
266 public int ChildTerseUpdatePeriod { get; set; }
267 259
268 protected float m_defaultDrawDistance = 255.0f; 260 protected float m_defaultDrawDistance = 255f;
261 protected float m_defaultCullingDrawDistance = 16f;
269 public float DefaultDrawDistance 262 public float DefaultDrawDistance
270 { 263 {
271 // get { return m_defaultDrawDistance; } 264 get { return ObjectsCullingByDistance?m_defaultCullingDrawDistance:m_defaultDrawDistance; }
272 get 265 }
273 {
274 if (RegionInfo != null)
275 {
276 float largestDimension = Math.Max(RegionInfo.RegionSizeX, RegionInfo.RegionSizeY);
277 m_defaultDrawDistance = Math.Max(m_defaultDrawDistance, largestDimension);
278 266
279 } 267 protected float m_maxDrawDistance = 512.0f;
280 return m_defaultDrawDistance; 268// protected float m_maxDrawDistance = 256.0f;
281 } 269 public float MaxDrawDistance
270 {
271 get { return m_maxDrawDistance; }
272 }
273
274 protected float m_maxRegionViewDistance = 255f;
275 public float MaxRegionViewDistance
276 {
277 get { return m_maxRegionViewDistance; }
282 } 278 }
283 279
284 private List<string> m_AllowedViewers = new List<string>(); 280 private List<string> m_AllowedViewers = new List<string>();
@@ -287,8 +283,8 @@ namespace OpenSim.Region.Framework.Scenes
287 // TODO: need to figure out how allow client agents but deny 283 // TODO: need to figure out how allow client agents but deny
288 // root agents when ACL denies access to root agent 284 // root agents when ACL denies access to root agent
289 public bool m_strictAccessControl = true; 285 public bool m_strictAccessControl = true;
290 286 public bool m_seeIntoBannedRegion = false;
291 public int MaxUndoCount { get; set; } 287 public int MaxUndoCount = 5;
292 288
293 public bool SeeIntoRegion { get; set; } 289 public bool SeeIntoRegion { get; set; }
294 290
@@ -306,11 +302,13 @@ namespace OpenSim.Region.Framework.Scenes
306 302
307 protected int m_splitRegionID; 303 protected int m_splitRegionID;
308 protected Timer m_restartWaitTimer = new Timer(); 304 protected Timer m_restartWaitTimer = new Timer();
305 protected Timer m_timerWatchdog = new Timer();
309 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>(); 306 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>();
310 protected List<RegionInfo> m_neighbours = new List<RegionInfo>(); 307 protected List<RegionInfo> m_neighbours = new List<RegionInfo>();
311 protected string m_simulatorVersion = "OpenSimulator Server"; 308 protected string m_simulatorVersion = "OpenSimulator Server";
312 protected AgentCircuitManager m_authenticateHandler; 309 protected AgentCircuitManager m_authenticateHandler;
313 protected SceneCommunicationService m_sceneGridService; 310 protected SceneCommunicationService m_sceneGridService;
311 protected ISnmpModule m_snmpService = null;
314 312
315 protected ISimulationDataService m_SimulationDataService; 313 protected ISimulationDataService m_SimulationDataService;
316 protected IEstateDataService m_EstateDataService; 314 protected IEstateDataService m_EstateDataService;
@@ -339,17 +337,6 @@ namespace OpenSim.Region.Framework.Scenes
339 private Dictionary<string, string> m_extraSettings; 337 private Dictionary<string, string> m_extraSettings;
340 338
341 /// <summary> 339 /// <summary>
342 /// If true then the next time the scene loop is activated, updates will be performed by firing of a timer
343 /// rather than on a single thread that sleeps.
344 /// </summary>
345 public bool UpdateOnTimer { get; set; }
346
347 /// <summary>
348 /// Only used if we are updating scene on a timer rather than sleeping a thread.
349 /// </summary>
350 private Timer m_sceneUpdateTimer;
351
352 /// <summary>
353 /// Current scene frame number 340 /// Current scene frame number
354 /// </summary> 341 /// </summary>
355 public uint Frame 342 public uint Frame
@@ -359,87 +346,38 @@ namespace OpenSim.Region.Framework.Scenes
359 } 346 }
360 347
361 /// <summary> 348 /// <summary>
362 /// Current maintenance run number 349 /// Frame time
363 /// </summary>
364 public uint MaintenanceRun { get; private set; }
365
366 /// <summary>
367 /// The minimum length of time in milliseconds that will be taken for a scene frame. If the frame takes less time then we
368 /// will sleep for the remaining period.
369 /// </summary>
370 /// <remarks>
371 /// One can tweak this number to experiment. One current effect of reducing it is to make avatar animations
372 /// occur too quickly (viewer 1) or with even more slide (viewer 2).
373 /// </remarks> 350 /// </remarks>
374 public int MinFrameTicks 351 public float FrameTime { get; private set; }
375 { 352 public int FrameTimeWarnPercent { get; private set; }
376 get { return m_minFrameTicks; } 353 public int FrameTimeCritPercent { get; private set; }
377 private set
378 {
379 m_minFrameTicks = value;
380 MinFrameSeconds = (float)m_minFrameTicks / 1000;
381 }
382 }
383 private int m_minFrameTicks;
384
385 public int FrameTimeWarnPercent { get; private set; }
386 public int FrameTimeCritPercent { get; private set; }
387 354
388 // Normalize the frame related stats to nominal 55fps for viewer and scripts option 355 // Normalize the frame related stats to nominal 55fps for viewer and scripts option
389 // see SimStatsReporter.cs 356 // see SimStatsReporter.cs
390 public bool Normalized55FPS { get; private set; } 357 public bool Normalized55FPS { get; private set; }
391 358
392 /// <summary>
393 /// The minimum length of time in seconds that will be taken for a scene frame.
394 /// </summary>
395 /// <remarks>
396 /// Always derived from MinFrameTicks.
397 /// </remarks>
398 public float MinFrameSeconds { get; private set; }
399
400 /// <summary>
401 /// The minimum length of time in milliseconds that will be taken for a scene frame. If the frame takes less time then we
402 /// will sleep for the remaining period.
403 /// </summary>
404 /// <remarks>
405 /// One can tweak this number to experiment. One current effect of reducing it is to make avatar animations
406 /// occur too quickly (viewer 1) or with even more slide (viewer 2).
407 /// </remarks>
408 public int MinMaintenanceTicks { get; set; }
409
410 private int m_update_physics = 1; 359 private int m_update_physics = 1;
411 private int m_update_entitymovement = 1; 360 private int m_update_entitymovement = 1;
412 private int m_update_objects = 1; 361 private int m_update_objects = 1;
413 private int m_update_presences = 1; // Update scene presence movements 362 private int m_update_presences = 1; // Update scene presence movements
414 private int m_update_events = 1; 363 private int m_update_events = 1;
415 private int m_update_backup = 200; 364 private int m_update_backup = 200;
416 private int m_update_terrain = 50; 365
417 // private int m_update_land = 1; 366 private int m_update_terrain = 1000;
418 private int m_update_coarse_locations = 50; 367
368 private int m_update_coarse_locations = 5;
419 private int m_update_temp_cleaning = 180; 369 private int m_update_temp_cleaning = 180;
420 370
421 private int agentMS; 371 private float agentMS;
422 private int frameMS; 372 private float frameMS;
423 private int physicsMS2; 373 private float physicsMS2;
424 private int physicsMS; 374 private float physicsMS;
425 private int otherMS; 375 private float otherMS;
426 private int tempOnRezMS; 376 private float tempOnRezMS;
427 private int eventMS; 377 private float eventMS;
428 private int backupMS; 378 private float backupMS;
429 private int terrainMS; 379 private float terrainMS;
430 private int landMS; 380 private float landMS;
431 private int spareMS;
432
433 // A temporary configuration flag to enable using FireAndForget to process
434 // collisions from the physics engine. There is a problem with collisions
435 // stopping sometimes and MB's suspicion is some race condition passing
436 // collisions from the physics engine callback to the script engine.
437 // This causes the collision events to be passed with a FireAndForget
438 // call which should eliminate that linkage. Testers can turn this on
439 // and see if collisions stop. If they don't, the problem is somewhere else.
440 // This feature defaults to 'off' so, by default, the simulator operation
441 // is not changed.
442 public bool ShouldUseFireAndForgetForCollisions = false;
443 381
444 /// <summary> 382 /// <summary>
445 /// Tick at which the last frame was processed. 383 /// Tick at which the last frame was processed.
@@ -447,11 +385,6 @@ namespace OpenSim.Region.Framework.Scenes
447 private int m_lastFrameTick; 385 private int m_lastFrameTick;
448 386
449 /// <summary> 387 /// <summary>
450 /// Tick at which the last maintenance run occurred.
451 /// </summary>
452 private int m_lastMaintenanceTick;
453
454 /// <summary>
455 /// Total script execution time (in Stopwatch Ticks) since the last frame 388 /// Total script execution time (in Stopwatch Ticks) since the last frame
456 /// </summary> 389 /// </summary>
457 private long m_scriptExecutionTime = 0; 390 private long m_scriptExecutionTime = 0;
@@ -461,23 +394,19 @@ namespace OpenSim.Region.Framework.Scenes
461 /// asynchronously from the update loop. 394 /// asynchronously from the update loop.
462 /// </summary> 395 /// </summary>
463 private bool m_cleaningTemps = false; 396 private bool m_cleaningTemps = false;
397 private bool m_sendingCoarseLocations = false; // same for async course locations sending
464 398
465 /// <summary> 399 /// <summary>
466 /// Used to control main scene thread looping time when not updating via timer. 400 /// Used to control main scene thread looping time when not updating via timer.
467 /// </summary> 401 /// </summary>
468 private ManualResetEvent m_updateWaitEvent = new ManualResetEvent(false); 402 private ManualResetEvent m_updateWaitEvent = new ManualResetEvent(false);
469 403
470 /// <summary>
471 /// Used to control maintenance thread runs.
472 /// </summary>
473 private ManualResetEvent m_maintenanceWaitEvent = new ManualResetEvent(false);
474
475 // TODO: Possibly stop other classes being able to manipulate this directly. 404 // TODO: Possibly stop other classes being able to manipulate this directly.
476 private SceneGraph m_sceneGraph; 405 private SceneGraph m_sceneGraph;
477 private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing 406 private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing
478 private volatile bool m_backingup; 407 private volatile bool m_backingup;
479 private Dictionary<UUID, ReturnInfo> m_returns = new Dictionary<UUID, ReturnInfo>(); 408 private Dictionary<UUID, ReturnInfo> m_returns = new Dictionary<UUID, ReturnInfo>();
480 private Dictionary<UUID, SceneObjectGroup> m_groupsWithTargets = new Dictionary<UUID, SceneObjectGroup>(); 409 private Dictionary<UUID, int> m_groupsWithTargets = new Dictionary<UUID, int>();
481 410
482 private string m_defaultScriptEngine; 411 private string m_defaultScriptEngine;
483 412
@@ -492,6 +421,11 @@ namespace OpenSim.Region.Framework.Scenes
492 /// </summary> 421 /// </summary>
493 private int m_LastLogin; 422 private int m_LastLogin;
494 423
424 private int m_lastIncoming;
425 private int m_lastOutgoing;
426 private int m_hbRestarts = 0;
427
428
495 /// <summary> 429 /// <summary>
496 /// Thread that runs the scene loop. 430 /// Thread that runs the scene loop.
497 /// </summary> 431 /// </summary>
@@ -510,7 +444,7 @@ namespace OpenSim.Region.Framework.Scenes
510 /// Is the scene active? 444 /// Is the scene active?
511 /// </summary> 445 /// </summary>
512 /// <remarks> 446 /// <remarks>
513 /// If false, maintenance and update loops are not being run, though after setting to false update may still 447 /// If false, update loop is not being run, though after setting to false update may still
514 /// be active for a period (and IsRunning will still be true). Updates can still be triggered manually if 448 /// be active for a period (and IsRunning will still be true). Updates can still be triggered manually if
515 /// the scene is not active. 449 /// the scene is not active.
516 /// </remarks> 450 /// </remarks>
@@ -540,9 +474,21 @@ namespace OpenSim.Region.Framework.Scenes
540 public bool IsRunning { get { return m_isRunning; } } 474 public bool IsRunning { get { return m_isRunning; } }
541 private volatile bool m_isRunning; 475 private volatile bool m_isRunning;
542 476
477 private bool m_firstHeartbeat = true;
478
479// private UpdatePrioritizationSchemes m_priorityScheme = UpdatePrioritizationSchemes.Time;
480// private bool m_reprioritizationEnabled = true;
481// private double m_reprioritizationInterval = 5000.0;
482// private double m_rootReprioritizationDistance = 10.0;
483// private double m_childReprioritizationDistance = 20.0;
484
485
543 private Timer m_mapGenerationTimer = new Timer(); 486 private Timer m_mapGenerationTimer = new Timer();
544 private bool m_generateMaptiles; 487 private bool m_generateMaptiles;
545 488
489 protected int m_lastHealth = -1;
490 protected int m_lastUsers = -1;
491
546 #endregion Fields 492 #endregion Fields
547 493
548 #region Properties 494 #region Properties
@@ -571,6 +517,19 @@ namespace OpenSim.Region.Framework.Scenes
571 get { return m_sceneGridService; } 517 get { return m_sceneGridService; }
572 } 518 }
573 519
520 public ISnmpModule SnmpService
521 {
522 get
523 {
524 if (m_snmpService == null)
525 {
526 m_snmpService = RequestModuleInterface<ISnmpModule>();
527 }
528
529 return m_snmpService;
530 }
531 }
532
574 public ISimulationDataService SimulationDataService 533 public ISimulationDataService SimulationDataService
575 { 534 {
576 get 535 get
@@ -777,22 +736,25 @@ namespace OpenSim.Region.Framework.Scenes
777 get { return m_capsModule; } 736 get { return m_capsModule; }
778 } 737 }
779 738
780 public int MonitorFrameTime { get { return frameMS; } } 739 public int MonitorFrameTime { get { return (int)frameMS; } }
781 public int MonitorPhysicsUpdateTime { get { return physicsMS; } } 740 public int MonitorPhysicsUpdateTime { get { return (int)physicsMS; } }
782 public int MonitorPhysicsSyncTime { get { return physicsMS2; } } 741 public int MonitorPhysicsSyncTime { get { return (int)physicsMS2; } }
783 public int MonitorOtherTime { get { return otherMS; } } 742 public int MonitorOtherTime { get { return (int)otherMS; } }
784 public int MonitorTempOnRezTime { get { return tempOnRezMS; } } 743 public int MonitorTempOnRezTime { get { return (int)tempOnRezMS; } }
785 public int MonitorEventTime { get { return eventMS; } } // This may need to be divided into each event? 744 public int MonitorEventTime { get { return (int)eventMS; } } // This may need to be divided into each event?
786 public int MonitorBackupTime { get { return backupMS; } } 745 public int MonitorBackupTime { get { return (int)backupMS; } }
787 public int MonitorTerrainTime { get { return terrainMS; } } 746 public int MonitorTerrainTime { get { return (int)terrainMS; } }
788 public int MonitorLandTime { get { return landMS; } } 747 public int MonitorLandTime { get { return (int)landMS; } }
789 public int MonitorLastFrameTick { get { return m_lastFrameTick; } } 748 public int MonitorLastFrameTick { get { return m_lastFrameTick; } }
790 749
791 public UpdatePrioritizationSchemes UpdatePrioritizationScheme { get; set; } 750 public UpdatePrioritizationSchemes UpdatePrioritizationScheme { get; set; }
792 public bool IsReprioritizationEnabled { get; set; } 751 public bool IsReprioritizationEnabled { get; set; }
793 public double ReprioritizationInterval { get; set; } 752 public float ReprioritizationInterval { get; set; }
794 public double RootReprioritizationDistance { get; set; } 753 public float ReprioritizationDistance { get; set; }
795 public double ChildReprioritizationDistance { get; set; } 754 private float m_minReprioritizationDistance = 32f;
755 public bool ObjectsCullingByDistance = false;
756
757 private ExpiringCache<UUID, UUID> TeleportTargetsCoolDown = new ExpiringCache<UUID, UUID>();
796 758
797 public AgentCircuitManager AuthenticateHandler 759 public AgentCircuitManager AuthenticateHandler
798 { 760 {
@@ -857,17 +819,16 @@ namespace OpenSim.Region.Framework.Scenes
857 819
858 #region Constructors 820 #region Constructors
859 821
860 public Scene(RegionInfo regInfo, AgentCircuitManager authen, 822 public Scene(RegionInfo regInfo, AgentCircuitManager authen,
861 ISimulationDataService simDataService, IEstateDataService estateDataService, 823 ISimulationDataService simDataService, IEstateDataService estateDataService,
862 IConfigSource config, string simulatorVersion) 824 IConfigSource config, string simulatorVersion)
863 : this(regInfo) 825 : this(regInfo)
864 { 826 {
865 m_config = config; 827 m_config = config;
866 MinFrameTicks = 89; 828 FrameTime = 0.0908f;
867 FrameTimeWarnPercent = 60; 829 FrameTimeWarnPercent = 60;
868 FrameTimeCritPercent = 40; 830 FrameTimeCritPercent = 40;
869 Normalized55FPS = true; 831 Normalized55FPS = true;
870 MinMaintenanceTicks = 1000;
871 SeeIntoRegion = true; 832 SeeIntoRegion = true;
872 833
873 Random random = new Random(); 834 Random random = new Random();
@@ -878,6 +839,9 @@ namespace OpenSim.Region.Framework.Scenes
878 m_SimulationDataService = simDataService; 839 m_SimulationDataService = simDataService;
879 m_EstateDataService = estateDataService; 840 m_EstateDataService = estateDataService;
880 841
842 m_lastIncoming = 0;
843 m_lastOutgoing = 0;
844
881 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this); 845 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this);
882 m_asyncSceneObjectDeleter.Enabled = true; 846 m_asyncSceneObjectDeleter.Enabled = true;
883 847
@@ -935,9 +899,9 @@ namespace OpenSim.Region.Framework.Scenes
935 EventManager.OnLandObjectRemoved += 899 EventManager.OnLandObjectRemoved +=
936 new EventManager.LandObjectRemoved(simDataService.RemoveLandObject); 900 new EventManager.LandObjectRemoved(simDataService.RemoveLandObject);
937 901
938 RegisterDefaultSceneEvents(); 902 RegisterDefaultSceneEvents();
939 903
940 // XXX: Don't set the public property since we don't want to activate here. This needs to be handled 904 // XXX: Don't set the public property since we don't want to activate here. This needs to be handled
941 // better in the future. 905 // better in the future.
942 m_scripts_enabled = !RegionInfo.RegionSettings.DisableScripts; 906 m_scripts_enabled = !RegionInfo.RegionSettings.DisableScripts;
943 907
@@ -956,6 +920,18 @@ namespace OpenSim.Region.Framework.Scenes
956 StartDisabled = startupConfig.GetBoolean("StartDisabled", false); 920 StartDisabled = startupConfig.GetBoolean("StartDisabled", false);
957 921
958 m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance", m_defaultDrawDistance); 922 m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance", m_defaultDrawDistance);
923 m_maxDrawDistance = startupConfig.GetFloat("MaxDrawDistance", m_maxDrawDistance);
924 m_maxRegionViewDistance = startupConfig.GetFloat("MaxRegionsViewDistance", m_maxRegionViewDistance);
925
926 // old versions compatibility
927 LegacySitOffsets = startupConfig.GetBoolean("LegacySitOffsets", LegacySitOffsets);
928
929 if (m_defaultDrawDistance > m_maxDrawDistance)
930 m_defaultDrawDistance = m_maxDrawDistance;
931
932 if (m_maxRegionViewDistance > m_maxDrawDistance)
933 m_maxRegionViewDistance = m_maxDrawDistance;
934
959 UseBackup = startupConfig.GetBoolean("UseSceneBackup", UseBackup); 935 UseBackup = startupConfig.GetBoolean("UseSceneBackup", UseBackup);
960 if (!UseBackup) 936 if (!UseBackup)
961 m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName); 937 m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName);
@@ -967,9 +943,8 @@ namespace OpenSim.Region.Framework.Scenes
967 943
968 MaxUndoCount = startupConfig.GetInt("MaxPrimUndos", 20); 944 MaxUndoCount = startupConfig.GetInt("MaxPrimUndos", 20);
969 945
970 PhysicalPrims = startupConfig.GetBoolean("physical_prim", PhysicalPrims); 946 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true);
971 CollidablePrims = startupConfig.GetBoolean("collidable_prim", CollidablePrims); 947 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true);
972
973 m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys); 948 m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys);
974 if (RegionInfo.NonphysPrimMin > 0) 949 if (RegionInfo.NonphysPrimMin > 0)
975 { 950 {
@@ -989,11 +964,24 @@ namespace OpenSim.Region.Framework.Scenes
989 } 964 }
990 965
991 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys); 966 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys);
967
992 if (RegionInfo.PhysPrimMax > 0) 968 if (RegionInfo.PhysPrimMax > 0)
993 { 969 {
994 m_maxPhys = RegionInfo.PhysPrimMax; 970 m_maxPhys = RegionInfo.PhysPrimMax;
995 } 971 }
996 972
973 m_linksetCapacity = startupConfig.GetInt("LinksetPrims", m_linksetCapacity);
974 if (RegionInfo.LinksetCapacity > 0)
975 {
976 m_linksetCapacity = RegionInfo.LinksetCapacity;
977 }
978
979 m_linksetPhysCapacity = startupConfig.GetInt("LinksetPhysPrims", m_linksetPhysCapacity);
980
981
982 SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest");
983 TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false);
984
997 // Here, if clamping is requested in either global or 985 // Here, if clamping is requested in either global or
998 // local config, it will be used 986 // local config, it will be used
999 // 987 //
@@ -1003,13 +991,9 @@ namespace OpenSim.Region.Framework.Scenes
1003 m_clampPrimSize = true; 991 m_clampPrimSize = true;
1004 } 992 }
1005 993
1006 m_linksetCapacity = startupConfig.GetInt("LinksetPrims", m_linksetCapacity); 994 m_clampNegativeZ = startupConfig.GetBoolean("ClampNegativeZ", m_clampNegativeZ);
1007 if (RegionInfo.LinksetCapacity > 0)
1008 {
1009 m_linksetCapacity = RegionInfo.LinksetCapacity;
1010 }
1011 995
1012 m_useTrashOnDelete = startupConfig.GetBoolean("UseTrashOnDelete", m_useTrashOnDelete); 996 m_useTrashOnDelete = startupConfig.GetBoolean("UseTrashOnDelete",m_useTrashOnDelete);
1013 m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries); 997 m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries);
1014 m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings); 998 m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings);
1015 m_dontPersistBefore = 999 m_dontPersistBefore =
@@ -1020,11 +1004,10 @@ namespace OpenSim.Region.Framework.Scenes
1020 m_persistAfter *= 10000000; 1004 m_persistAfter *= 10000000;
1021 1005
1022 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); 1006 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
1023 1007 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine);
1024 SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest");
1025 TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false);
1026 1008
1027 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); 1009 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
1010 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
1028 1011
1029 string[] possibleMapConfigSections = new string[] { "Map", "Startup" }; 1012 string[] possibleMapConfigSections = new string[] { "Map", "Startup" };
1030 1013
@@ -1070,7 +1053,7 @@ namespace OpenSim.Region.Framework.Scenes
1070 1053
1071 if (grant.Length > 0) 1054 if (grant.Length > 0)
1072 { 1055 {
1073 foreach (string viewer in grant.Split('|')) 1056 foreach (string viewer in grant.Split(','))
1074 { 1057 {
1075 m_AllowedViewers.Add(viewer.Trim().ToLower()); 1058 m_AllowedViewers.Add(viewer.Trim().ToLower());
1076 } 1059 }
@@ -1086,17 +1069,16 @@ namespace OpenSim.Region.Framework.Scenes
1086 1069
1087 if (grant.Length > 0) 1070 if (grant.Length > 0)
1088 { 1071 {
1089 foreach (string viewer in grant.Split('|')) 1072 foreach (string viewer in grant.Split(','))
1090 { 1073 {
1091 m_BannedViewers.Add(viewer.Trim().ToLower()); 1074 m_BannedViewers.Add(viewer.Trim().ToLower());
1092 } 1075 }
1093 } 1076 }
1094 1077
1095 if (startupConfig.Contains("MinFrameTime")) 1078 FrameTime = startupConfig.GetFloat( "FrameTime", FrameTime);
1096 MinFrameTicks = (int)(startupConfig.GetFloat("MinFrameTime") * 1000);
1097 FrameTimeWarnPercent = startupConfig.GetInt( "FrameTimeWarnPercent", FrameTimeWarnPercent); 1079 FrameTimeWarnPercent = startupConfig.GetInt( "FrameTimeWarnPercent", FrameTimeWarnPercent);
1098 FrameTimeCritPercent = startupConfig.GetInt( "FrameTimeCritPercent", FrameTimeCritPercent); 1080 FrameTimeCritPercent = startupConfig.GetInt( "FrameTimeCritPercent", FrameTimeCritPercent);
1099 Normalized55FPS = startupConfig.GetBoolean( "Normalized55FPS", Normalized55FPS); 1081 Normalized55FPS = startupConfig.GetBoolean( "Normalized55FPS", Normalized55FPS);
1100 1082
1101 m_update_backup = startupConfig.GetInt("UpdateStorageEveryNFrames", m_update_backup); 1083 m_update_backup = startupConfig.GetInt("UpdateStorageEveryNFrames", m_update_backup);
1102 m_update_coarse_locations = startupConfig.GetInt("UpdateCoarseLocationsEveryNFrames", m_update_coarse_locations); 1084 m_update_coarse_locations = startupConfig.GetInt("UpdateCoarseLocationsEveryNFrames", m_update_coarse_locations);
@@ -1108,21 +1090,6 @@ namespace OpenSim.Region.Framework.Scenes
1108 m_update_terrain = startupConfig.GetInt("UpdateTerrainEveryNFrames", m_update_terrain); 1090 m_update_terrain = startupConfig.GetInt("UpdateTerrainEveryNFrames", m_update_terrain);
1109 m_update_temp_cleaning = startupConfig.GetInt("UpdateTempCleaningEveryNSeconds", m_update_temp_cleaning); 1091 m_update_temp_cleaning = startupConfig.GetInt("UpdateTempCleaningEveryNSeconds", m_update_temp_cleaning);
1110 1092
1111 if (startupConfig.Contains("ShouldUseFireAndForgetForCollisions"))
1112 {
1113 ShouldUseFireAndForgetForCollisions = startupConfig.GetBoolean("ShouldUseFireAndForgetForCollisions", false);
1114 }
1115 }
1116
1117
1118 // FIXME: Ultimately this should be in a module.
1119 SendPeriodicAppearanceUpdates = false;
1120
1121 IConfig appearanceConfig = m_config.Configs["Appearance"];
1122 if (appearanceConfig != null)
1123 {
1124 SendPeriodicAppearanceUpdates
1125 = appearanceConfig.GetBoolean("ResendAppearanceUpdates", SendPeriodicAppearanceUpdates);
1126 } 1093 }
1127 1094
1128 #endregion Region Config 1095 #endregion Region Config
@@ -1131,6 +1098,7 @@ namespace OpenSim.Region.Framework.Scenes
1131 if (entityTransferConfig != null) 1098 if (entityTransferConfig != null)
1132 { 1099 {
1133 AllowAvatarCrossing = entityTransferConfig.GetBoolean("AllowAvatarCrossing", AllowAvatarCrossing); 1100 AllowAvatarCrossing = entityTransferConfig.GetBoolean("AllowAvatarCrossing", AllowAvatarCrossing);
1101 DisableObjectTransfer = entityTransferConfig.GetBoolean("DisableObjectTransfer", false);
1134 } 1102 }
1135 1103
1136 #region Interest Management 1104 #region Interest Management
@@ -1153,60 +1121,51 @@ namespace OpenSim.Region.Framework.Scenes
1153 IsReprioritizationEnabled 1121 IsReprioritizationEnabled
1154 = interestConfig.GetBoolean("ReprioritizationEnabled", IsReprioritizationEnabled); 1122 = interestConfig.GetBoolean("ReprioritizationEnabled", IsReprioritizationEnabled);
1155 ReprioritizationInterval 1123 ReprioritizationInterval
1156 = interestConfig.GetDouble("ReprioritizationInterval", ReprioritizationInterval); 1124 = interestConfig.GetFloat("ReprioritizationInterval", ReprioritizationInterval);
1157 RootReprioritizationDistance 1125 ReprioritizationDistance
1158 = interestConfig.GetDouble("RootReprioritizationDistance", RootReprioritizationDistance); 1126 = interestConfig.GetFloat("RootReprioritizationDistance", ReprioritizationDistance);
1159 ChildReprioritizationDistance
1160 = interestConfig.GetDouble("ChildReprioritizationDistance", ChildReprioritizationDistance);
1161 1127
1162 RootTerseUpdatePeriod = interestConfig.GetInt("RootTerseUpdatePeriod", RootTerseUpdatePeriod); 1128 if(ReprioritizationDistance < m_minReprioritizationDistance)
1163 ChildTerseUpdatePeriod = interestConfig.GetInt("ChildTerseUpdatePeriod", ChildTerseUpdatePeriod); 1129 ReprioritizationDistance = m_minReprioritizationDistance;
1130
1131 ObjectsCullingByDistance
1132 = interestConfig.GetBoolean("ObjectsCullingByDistance", ObjectsCullingByDistance);
1164 1133
1165 RootPositionUpdateTolerance
1166 = interestConfig.GetFloat("RootPositionUpdateTolerance", RootPositionUpdateTolerance);
1167 RootRotationUpdateTolerance
1168 = interestConfig.GetFloat("RootRotationUpdateTolerance", RootRotationUpdateTolerance);
1169 RootVelocityUpdateTolerance
1170 = interestConfig.GetFloat("RootVelocityUpdateTolerance", RootVelocityUpdateTolerance);
1171 } 1134 }
1172 1135
1173 m_log.DebugFormat("[SCENE]: Using the {0} prioritization scheme", UpdatePrioritizationScheme); 1136 m_log.DebugFormat("[SCENE]: Using the {0} prioritization scheme", UpdatePrioritizationScheme);
1174 1137
1175 #endregion Interest Management 1138 #endregion Interest Management
1176 1139
1177 // The timer used by the Stopwatch class depends on the system hardware and operating system; inform 1140 StatsReporter = new SimStatsReporter(this);
1178 // if the timer is based on a high-resolution performance counter or based on the system timer;
1179 // the performance counter will provide a more precise time than the system timer
1180 if (Stopwatch.IsHighResolution)
1181 m_log.InfoFormat("[SCENE]: Using high-resolution performance counter for statistics.");
1182 else
1183 m_log.InfoFormat("[SCENE]: Using system timer for statistics.");
1184 1141
1185 // Acquire the statistics section of the OpenSim.ini file located 1142 StatsReporter.OnSendStatsResult += SendSimStatsPackets;
1186 // in the bin directory 1143 StatsReporter.OnStatsIncorrect += m_sceneGraph.RecalculateStats;
1187 IConfig statisticsConfig = m_config.Configs["Statistics"];
1188 1144
1189 // Confirm that the statistics section existed in the configuration 1145 IConfig restartConfig = config.Configs["RestartModule"];
1190 // file 1146 if (restartConfig != null)
1191 if (statisticsConfig != null)
1192 {
1193 // Create the StatsReporter using the number of frames to store
1194 // for the frame time statistics, or 10 frames if the config
1195 // file doesn't contain a value
1196 StatsReporter = new SimStatsReporter(this,
1197 statisticsConfig.GetInt("NumberOfFrames",
1198 m_defaultNumberFramesStored));
1199 }
1200 else
1201 { 1147 {
1202 // Create a StatsReporter with the current scene and a default 1148 string markerPath = restartConfig.GetString("MarkerPath", String.Empty);
1203 // 10 frames stored for the frame time statistics
1204 StatsReporter = new SimStatsReporter(this);
1205 }
1206 1149
1207 StatsReporter.OnSendStatsResult += SendSimStatsPackets; 1150 if (markerPath != String.Empty)
1208 StatsReporter.OnStatsIncorrect += m_sceneGraph.RecalculateStats; 1151 {
1152 string path = Path.Combine(markerPath, RegionInfo.RegionID.ToString() + ".started");
1153 try
1154 {
1155 string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString();
1156 FileStream fs = File.Create(path);
1157 System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
1158 Byte[] buf = enc.GetBytes(pidstring);
1159 fs.Write(buf, 0, buf.Length);
1160 fs.Close();
1161 }
1162 catch (Exception)
1163 {
1164 }
1165 }
1166 }
1209 1167
1168 StartTimerWatchdog();
1210 } 1169 }
1211 1170
1212 public Scene(RegionInfo regInfo) 1171 public Scene(RegionInfo regInfo)
@@ -1240,15 +1199,12 @@ namespace OpenSim.Region.Framework.Scenes
1240 UpdatePrioritizationScheme = UpdatePrioritizationSchemes.Time; 1199 UpdatePrioritizationScheme = UpdatePrioritizationSchemes.Time;
1241 ReprioritizationInterval = 5000; 1200 ReprioritizationInterval = 5000;
1242 1201
1243 RootRotationUpdateTolerance = 0.1f; 1202 ReprioritizationDistance = m_minReprioritizationDistance;
1244 RootVelocityUpdateTolerance = 0.001f;
1245 RootPositionUpdateTolerance = 0.05f;
1246 RootReprioritizationDistance = 10.0;
1247 ChildReprioritizationDistance = 20.0;
1248 1203
1249 m_eventManager = new EventManager(); 1204 m_eventManager = new EventManager();
1250 1205
1251 m_permissions = new ScenePermissions(this); 1206 m_permissions = new ScenePermissions(this);
1207
1252 } 1208 }
1253 1209
1254 #endregion 1210 #endregion
@@ -1285,7 +1241,6 @@ namespace OpenSim.Region.Framework.Scenes
1285 if (!fm.TryGetFeature("OpenSimExtras", out openSimExtras)) 1241 if (!fm.TryGetFeature("OpenSimExtras", out openSimExtras))
1286 openSimExtras = new OSDMap(); 1242 openSimExtras = new OSDMap();
1287 1243
1288 float FrameTime = MinFrameTicks / 1000.0f;
1289 float statisticsFPSfactor = 1.0f; 1244 float statisticsFPSfactor = 1.0f;
1290 if(Normalized55FPS) 1245 if(Normalized55FPS)
1291 statisticsFPSfactor = 55.0f * FrameTime; 1246 statisticsFPSfactor = 55.0f * FrameTime;
@@ -1302,7 +1257,7 @@ namespace OpenSim.Region.Framework.Scenes
1302 1257
1303 protected virtual void RegisterDefaultSceneEvents() 1258 protected virtual void RegisterDefaultSceneEvents()
1304 { 1259 {
1305 m_eventManager.OnSignificantClientMovement += HandleOnSignificantClientMovement; 1260// m_eventManager.OnSignificantClientMovement += HandleOnSignificantClientMovement;
1306 } 1261 }
1307 1262
1308 public override string GetSimulatorVersion() 1263 public override string GetSimulatorVersion()
@@ -1325,20 +1280,8 @@ namespace OpenSim.Region.Framework.Scenes
1325 { 1280 {
1326 if (RegionInfo.RegionHandle != otherRegion.RegionHandle) 1281 if (RegionInfo.RegionHandle != otherRegion.RegionHandle)
1327 { 1282 {
1328 //// If these are cast to INT because long + negative values + abs returns invalid data
1329 //int resultX = Math.Abs((int)xcell - (int)RegionInfo.RegionLocX);
1330 //int resultY = Math.Abs((int)ycell - (int)RegionInfo.RegionLocY);
1331 //if (resultX <= 1 && resultY <= 1)
1332 float dist = (float)Math.Max(DefaultDrawDistance,
1333 (float)Math.Max(RegionInfo.RegionSizeX, RegionInfo.RegionSizeY));
1334 uint newRegionX, newRegionY, thisRegionX, thisRegionY;
1335 Util.RegionHandleToRegionLoc(otherRegion.RegionHandle, out newRegionX, out newRegionY);
1336 Util.RegionHandleToRegionLoc(RegionInfo.RegionHandle, out thisRegionX, out thisRegionY);
1337 1283
1338 //m_log.InfoFormat("[SCENE]: (on region {0}): Region {1} up in coords {2}-{3}", 1284 if (isNeighborRegion(otherRegion))
1339 // RegionInfo.RegionName, otherRegion.RegionName, newRegionX, newRegionY);
1340
1341 if (!Util.IsOutsideView(dist, thisRegionX, newRegionX, thisRegionY, newRegionY))
1342 { 1285 {
1343 // Let the grid service module know, so this can be cached 1286 // Let the grid service module know, so this can be cached
1344 m_eventManager.TriggerOnRegionUp(otherRegion); 1287 m_eventManager.TriggerOnRegionUp(otherRegion);
@@ -1373,6 +1316,21 @@ namespace OpenSim.Region.Framework.Scenes
1373 } 1316 }
1374 } 1317 }
1375 1318
1319 public bool isNeighborRegion(GridRegion otherRegion)
1320 {
1321 int tmp = otherRegion.RegionLocX - (int)RegionInfo.WorldLocX; ;
1322
1323 if (tmp < -otherRegion.RegionSizeX && tmp > RegionInfo.RegionSizeX)
1324 return false;
1325
1326 tmp = otherRegion.RegionLocY - (int)RegionInfo.WorldLocY;
1327
1328 if (tmp < -otherRegion.RegionSizeY && tmp > RegionInfo.RegionSizeY)
1329 return false;
1330
1331 return true;
1332 }
1333
1376 public void AddNeighborRegion(RegionInfo region) 1334 public void AddNeighborRegion(RegionInfo region)
1377 { 1335 {
1378 lock (m_neighbours) 1336 lock (m_neighbours)
@@ -1475,13 +1433,24 @@ namespace OpenSim.Region.Framework.Scenes
1475 return; 1433 return;
1476 } 1434 }
1477 1435
1436 IEtcdModule etcd = RequestModuleInterface<IEtcdModule>();
1437 if (etcd != null)
1438 {
1439 etcd.Delete("Health");
1440 etcd.Delete("HealthFlags");
1441 etcd.Delete("RootAgents");
1442 }
1443
1478 m_log.InfoFormat("[SCENE]: Closing down the single simulator: {0}", RegionInfo.RegionName); 1444 m_log.InfoFormat("[SCENE]: Closing down the single simulator: {0}", RegionInfo.RegionName);
1479 1445
1480 StatsReporter.Close();
1481 1446
1447 StatsReporter.Close();
1482 m_restartTimer.Stop(); 1448 m_restartTimer.Stop();
1483 m_restartTimer.Close(); 1449 m_restartTimer.Close();
1484 1450
1451 if (!GridService.DeregisterRegion(RegionInfo.RegionID))
1452 m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", Name);
1453
1485 // Kick all ROOT agents with the message, 'The simulator is going down' 1454 // Kick all ROOT agents with the message, 'The simulator is going down'
1486 ForEachScenePresence(delegate(ScenePresence avatar) 1455 ForEachScenePresence(delegate(ScenePresence avatar)
1487 { 1456 {
@@ -1504,13 +1473,15 @@ namespace OpenSim.Region.Framework.Scenes
1504 // Stop all client threads. 1473 // Stop all client threads.
1505 ForEachScenePresence(delegate(ScenePresence avatar) { CloseAgent(avatar.UUID, false); }); 1474 ForEachScenePresence(delegate(ScenePresence avatar) { CloseAgent(avatar.UUID, false); });
1506 1475
1507 m_log.Debug("[SCENE]: Persisting changed objects"); 1476 m_log.Debug("[SCENE]: TriggerSceneShuttingDown");
1508 EventManager.TriggerSceneShuttingDown(this); 1477 EventManager.TriggerSceneShuttingDown(this);
1509 Backup(false);
1510 m_sceneGraph.Close();
1511 1478
1512 if (!GridService.DeregisterRegion(RegionInfo.RegionID)) 1479 m_log.Debug("[SCENE]: Persisting changed objects");
1513 m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", Name); 1480 Backup(true);
1481
1482 m_log.Debug("[SCENE]: Closing scene");
1483
1484 m_sceneGraph.Close();
1514 1485
1515 base.Close(); 1486 base.Close();
1516 1487
@@ -1519,6 +1490,7 @@ namespace OpenSim.Region.Framework.Scenes
1519 // attempt to reference a null or disposed physics scene. 1490 // attempt to reference a null or disposed physics scene.
1520 if (PhysicsScene != null) 1491 if (PhysicsScene != null)
1521 { 1492 {
1493 m_log.Debug("[SCENE]: Dispose Physics");
1522 PhysicsScene phys = PhysicsScene; 1494 PhysicsScene phys = PhysicsScene;
1523 // remove the physics engine from both Scene and SceneGraph 1495 // remove the physics engine from both Scene and SceneGraph
1524 PhysicsScene = null; 1496 PhysicsScene = null;
@@ -1537,7 +1509,7 @@ namespace OpenSim.Region.Framework.Scenes
1537 /// </summary> 1509 /// </summary>
1538 /// <param name='startScripts'> 1510 /// <param name='startScripts'>
1539 /// Start the scripts within the scene. 1511 /// Start the scripts within the scene.
1540 /// </param> 1512 /// </param>
1541 public void Start(bool startScripts) 1513 public void Start(bool startScripts)
1542 { 1514 {
1543 if (IsRunning) 1515 if (IsRunning)
@@ -1550,10 +1522,31 @@ namespace OpenSim.Region.Framework.Scenes
1550// m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName); 1522// m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName);
1551 if (m_heartbeatThread != null) 1523 if (m_heartbeatThread != null)
1552 { 1524 {
1525 m_hbRestarts++;
1526 if(m_hbRestarts > 10)
1527 Environment.Exit(1);
1528 m_log.ErrorFormat("[SCENE]: Restarting heartbeat thread because it hasn't reported in in region {0}", RegionInfo.RegionName);
1529
1530//int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
1531//System.Diagnostics.Process proc = new System.Diagnostics.Process();
1532//proc.EnableRaisingEvents=false;
1533//proc.StartInfo.FileName = "/bin/kill";
1534//proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
1535//proc.Start();
1536//proc.WaitForExit();
1537//Thread.Sleep(1000);
1538//Environment.Exit(1);
1553 m_heartbeatThread.Abort(); 1539 m_heartbeatThread.Abort();
1540 Watchdog.AbortThread(m_heartbeatThread.ManagedThreadId);
1554 m_heartbeatThread = null; 1541 m_heartbeatThread = null;
1555 } 1542 }
1556 1543
1544 GC.Collect();
1545 GC.WaitForPendingFinalizers();
1546 GC.Collect();
1547 // tell physics to finish building actor
1548 m_sceneGraph.ProcessPhysicsPreSimulation();
1549
1557 m_heartbeatThread 1550 m_heartbeatThread
1558 = WorkManager.StartThread( 1551 = WorkManager.StartThread(
1559 Heartbeat, string.Format("Heartbeat-({0})", RegionInfo.RegionName.Replace(" ", "_")), ThreadPriority.Normal, false, false); 1552 Heartbeat, string.Format("Heartbeat-({0})", RegionInfo.RegionName.Replace(" ", "_")), ThreadPriority.Normal, false, false);
@@ -1596,136 +1589,13 @@ namespace OpenSim.Region.Framework.Scenes
1596 // alarms for scenes with many objects. 1589 // alarms for scenes with many objects.
1597 Update(1); 1590 Update(1);
1598 1591
1599 WorkManager.StartThread(
1600 Maintenance, string.Format("Maintenance ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, true);
1601
1602 Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true; 1592 Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true;
1603 m_lastFrameTick = Util.EnvironmentTickCount(); 1593 m_lastFrameTick = Util.EnvironmentTickCount();
1604 1594 Update(-1);
1605 if (UpdateOnTimer)
1606 {
1607 m_sceneUpdateTimer = new Timer(MinFrameTicks);
1608 m_sceneUpdateTimer.AutoReset = true;
1609 m_sceneUpdateTimer.Elapsed += Update;
1610 m_sceneUpdateTimer.Start();
1611 }
1612 else
1613 {
1614 Thread.CurrentThread.Priority = ThreadPriority.Highest;
1615 Update(-1);
1616 Watchdog.RemoveThread();
1617 m_isRunning = false;
1618 }
1619 }
1620
1621 private volatile bool m_isTimerUpdateRunning;
1622
1623 private void Update(object sender, ElapsedEventArgs e)
1624 {
1625 if (m_isTimerUpdateRunning)
1626 return;
1627
1628 m_isTimerUpdateRunning = true;
1629
1630 // If the last frame did not complete on time, then immediately start the next update on the same thread
1631 // and ignore further timed updates until we have a frame that had spare time.
1632 while (!Update(1) && Active) { }
1633
1634 if (!Active || m_shuttingDown)
1635 {
1636 m_sceneUpdateTimer.Stop();
1637 m_sceneUpdateTimer = null;
1638 m_isRunning = false;
1639 }
1640
1641 m_isTimerUpdateRunning = false;
1642 }
1643
1644 private void Maintenance()
1645 {
1646 DoMaintenance(-1);
1647
1648 Watchdog.RemoveThread(); 1595 Watchdog.RemoveThread();
1649 } 1596 }
1650 1597
1651 public void DoMaintenance(int runs) 1598 public override void Update(int frames)
1652 {
1653 long? endRun = null;
1654 int runtc, tmpMS;
1655 int previousMaintenanceTick;
1656
1657 if (runs >= 0)
1658 endRun = MaintenanceRun + runs;
1659
1660 List<Vector3> coarseLocations;
1661 List<UUID> avatarUUIDs;
1662
1663 while (!m_shuttingDown && ((endRun == null && Active) || MaintenanceRun < endRun))
1664 {
1665 runtc = Util.EnvironmentTickCount();
1666 ++MaintenanceRun;
1667
1668 // m_log.DebugFormat("[SCENE]: Maintenance run {0} in {1}", MaintenanceRun, Name);
1669
1670 // Coarse locations relate to positions of green dots on the mini-map (on a SecondLife client)
1671 if (MaintenanceRun % (m_update_coarse_locations / 10) == 0)
1672 {
1673 SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60);
1674 // Send coarse locations to clients
1675 ForEachScenePresence(delegate(ScenePresence presence)
1676 {
1677 presence.SendCoarseLocations(coarseLocations, avatarUUIDs);
1678 });
1679 }
1680
1681 if (SendPeriodicAppearanceUpdates && MaintenanceRun % 60 == 0)
1682 {
1683 // m_log.DebugFormat("[SCENE]: Sending periodic appearance updates");
1684
1685 if (AvatarFactory != null)
1686 {
1687 ForEachRootScenePresence(sp => AvatarFactory.SendAppearance(sp.UUID));
1688 }
1689 }
1690
1691 // Delete temp-on-rez stuff
1692 if (MaintenanceRun % m_update_temp_cleaning == 0 && !m_cleaningTemps)
1693 {
1694 // m_log.DebugFormat("[SCENE]: Running temp-on-rez cleaning in {0}", Name);
1695 tmpMS = Util.EnvironmentTickCount();
1696 m_cleaningTemps = true;
1697
1698 WorkManager.RunInThread(
1699 delegate { CleanTempObjects(); m_cleaningTemps = false; },
1700 null,
1701 string.Format("CleanTempObjects ({0})", Name));
1702
1703 tempOnRezMS = Util.EnvironmentTickCountSubtract(tmpMS);
1704 }
1705
1706 Watchdog.UpdateThread();
1707
1708 previousMaintenanceTick = m_lastMaintenanceTick;
1709 m_lastMaintenanceTick = Util.EnvironmentTickCount();
1710 runtc = Util.EnvironmentTickCountSubtract(m_lastMaintenanceTick, runtc);
1711 runtc = MinMaintenanceTicks - runtc;
1712
1713 if (runtc > 0)
1714 m_maintenanceWaitEvent.WaitOne(runtc);
1715
1716 // Optionally warn if a frame takes double the amount of time that it should.
1717 if (DebugUpdates
1718 && Util.EnvironmentTickCountSubtract(
1719 m_lastMaintenanceTick, previousMaintenanceTick) > MinMaintenanceTicks * 2)
1720 m_log.WarnFormat(
1721 "[SCENE]: Maintenance took {0} ms (desired max {1} ms) in {2}",
1722 Util.EnvironmentTickCountSubtract(m_lastMaintenanceTick, previousMaintenanceTick),
1723 MinMaintenanceTicks,
1724 RegionInfo.RegionName);
1725 }
1726 }
1727
1728 public override bool Update(int frames)
1729 { 1599 {
1730 long? endFrame = null; 1600 long? endFrame = null;
1731 1601
@@ -1733,119 +1603,97 @@ namespace OpenSim.Region.Framework.Scenes
1733 endFrame = Frame + frames; 1603 endFrame = Frame + frames;
1734 1604
1735 float physicsFPS = 0f; 1605 float physicsFPS = 0f;
1736 int previousFrameTick, tmpMS; 1606 float frameTimeMS = FrameTime * 1000.0f;
1737 1607
1738 // These variables will be used to save the precise frame time using the 1608 int previousFrameTick;
1739 // Stopwatch class of Microsoft SDK; the times are recorded at the start 1609
1740 // and end of a particular section of code, and then used to calculate 1610 double tmpMS;
1741 // the frame times, which are the sums of the sections for each given name 1611 double tmpMS2;
1742 double preciseTotalFrameTime = 0.0; 1612 double framestart;
1743 double preciseSimFrameTime = 0.0; 1613 float sleepMS;
1744 double precisePhysicsFrameTime = 0.0; 1614 float sleepError = 0;
1745 Stopwatch totalFrameStopwatch = new Stopwatch();
1746 Stopwatch simFrameStopwatch = new Stopwatch();
1747 Stopwatch physicsFrameStopwatch = new Stopwatch();
1748
1749 // Begin the stopwatch to keep track of the time that the frame
1750 // started running to determine how long the frame took to complete
1751 totalFrameStopwatch.Start();
1752 1615
1753 while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame)) 1616 while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame))
1754 { 1617 {
1618 framestart = Util.GetTimeStampMS();
1755 ++Frame; 1619 ++Frame;
1756 1620
1757 // m_log.DebugFormat("[SCENE]: Processing frame {0} in {1}", Frame, RegionInfo.RegionName); 1621 // m_log.DebugFormat("[SCENE]: Processing frame {0} in {1}", Frame, RegionInfo.RegionName);
1758 1622
1759 agentMS = eventMS = backupMS = terrainMS = landMS = spareMS = 0; 1623 agentMS = tempOnRezMS = eventMS = backupMS = terrainMS = landMS = 0f;
1760 1624
1761 try 1625 try
1762 { 1626 {
1763 EventManager.TriggerRegionHeartbeatStart(this); 1627 EventManager.TriggerRegionHeartbeatStart(this);
1764 1628
1765 // Apply taints in terrain module to terrain in physics scene 1629 // Apply taints in terrain module to terrain in physics scene
1630
1631 tmpMS = Util.GetTimeStampMS();
1632
1633 if (Frame % 4 == 0)
1634 {
1635 CheckTerrainUpdates();
1636 }
1637
1766 if (Frame % m_update_terrain == 0) 1638 if (Frame % m_update_terrain == 0)
1767 { 1639 {
1768 // At several points inside the code there was a need to
1769 // create a more precise measurement of time elapsed.
1770 // This led to the addition of variables that have a
1771 // similar function and thus remain tightly connected to
1772 // their original counterparts. However, the original
1773 // code is not receiving comments from our group because
1774 // we don't feel right modifying the code to that degree
1775 // at this point in time, the precise values all begin
1776 // with the keyword precise
1777 tmpMS = Util.EnvironmentTickCount();
1778 simFrameStopwatch.Start();
1779 UpdateTerrain(); 1640 UpdateTerrain();
1780
1781 // Get the simulation frame time that the avatar force
1782 // input took
1783 simFrameStopwatch.Stop();
1784 preciseSimFrameTime =
1785 simFrameStopwatch.Elapsed.TotalMilliseconds;
1786 terrainMS = Util.EnvironmentTickCountSubtract(tmpMS);
1787 } 1641 }
1788 1642
1789 // At several points inside the code there was a need to 1643 tmpMS2 = Util.GetTimeStampMS();
1790 // create a more precise measurement of time elapsed. This 1644 terrainMS = (float)(tmpMS2 - tmpMS);
1791 // led to the addition of variables that have a similar 1645 tmpMS = tmpMS2;
1792 // function and thus remain tightly connected to their
1793 // original counterparts. However, the original code is
1794 // not receiving comments from our group because we don't
1795 // feel right modifying the code to that degree at this
1796 // point in time, the precise values all begin with the
1797 // keyword precise
1798
1799 tmpMS = Util.EnvironmentTickCount();
1800 1646
1801 // Begin the stopwatch to track the time to prepare physics
1802 physicsFrameStopwatch.Start();
1803 if (PhysicsEnabled && Frame % m_update_physics == 0) 1647 if (PhysicsEnabled && Frame % m_update_physics == 0)
1804 m_sceneGraph.UpdatePreparePhysics(); 1648 m_sceneGraph.UpdatePreparePhysics();
1805 1649
1806 // Get the time it took to prepare the physics, this 1650 tmpMS2 = Util.GetTimeStampMS();
1807 // would report the most precise time that physics was 1651 physicsMS2 = (float)(tmpMS2 - tmpMS);
1808 // running on the machine and should the physics not be 1652 tmpMS = tmpMS2;
1809 // enabled will report the time it took to check if physics
1810 // was enabled
1811 physicsFrameStopwatch.Stop();
1812 precisePhysicsFrameTime = physicsFrameStopwatch.Elapsed.TotalMilliseconds;
1813 physicsMS2 = Util.EnvironmentTickCountSubtract(tmpMS);
1814 1653
1654/*
1815 // Apply any pending avatar force input to the avatar's velocity 1655 // Apply any pending avatar force input to the avatar's velocity
1816 tmpMS = Util.EnvironmentTickCount();
1817 simFrameStopwatch.Restart();
1818 if (Frame % m_update_entitymovement == 0) 1656 if (Frame % m_update_entitymovement == 0)
1819 m_sceneGraph.UpdateScenePresenceMovement(); 1657 m_sceneGraph.UpdateScenePresenceMovement();
1658*/
1659 if (Frame % (m_update_coarse_locations) == 0 && !m_sendingCoarseLocations)
1660 {
1661 m_sendingCoarseLocations = true;
1662 WorkManager.RunInThreadPool(
1663 delegate
1664 {
1665 List<Vector3> coarseLocations;
1666 List<UUID> avatarUUIDs;
1667 SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60);
1668 // Send coarse locations to clients
1669 ForEachScenePresence(delegate(ScenePresence presence)
1670 {
1671 presence.SendCoarseLocations(coarseLocations, avatarUUIDs);
1672 });
1673 m_sendingCoarseLocations = false;
1674 }, null, string.Format("SendCoarseLocations ({0})", Name));
1675 }
1820 1676
1821 // Get the simulation frame time that the avatar force input 1677 // Get the simulation frame time that the avatar force input
1822 // took 1678 // took
1823 simFrameStopwatch.Stop(); 1679 tmpMS2 = Util.GetTimeStampMS();
1824 preciseSimFrameTime += 1680 agentMS = (float)(tmpMS2 - tmpMS);
1825 simFrameStopwatch.Elapsed.TotalMilliseconds; 1681 tmpMS = tmpMS2;
1826 agentMS = Util.EnvironmentTickCountSubtract(tmpMS);
1827 1682
1828 // Perform the main physics update. This will do the actual work of moving objects and avatars according to their 1683 // Perform the main physics update. This will do the actual work of moving objects and avatars according to their
1829 // velocity 1684 // velocity
1830 tmpMS = Util.EnvironmentTickCount();
1831 physicsFrameStopwatch.Restart();
1832 if (Frame % m_update_physics == 0) 1685 if (Frame % m_update_physics == 0)
1833 { 1686 {
1834 if (PhysicsEnabled) 1687 if (PhysicsEnabled)
1835 physicsFPS = m_sceneGraph.UpdatePhysics(MinFrameSeconds); 1688 physicsFPS = m_sceneGraph.UpdatePhysics(FrameTime);
1836 1689
1837 if (SynchronizeScene != null) 1690 if (SynchronizeScene != null)
1838 SynchronizeScene(this); 1691 SynchronizeScene(this);
1839 } 1692 }
1840 1693
1841 // Add the main physics update time to the prepare physics time 1694 tmpMS2 = Util.GetTimeStampMS();
1842 physicsFrameStopwatch.Stop(); 1695 physicsMS = (float)(tmpMS2 - tmpMS);
1843 precisePhysicsFrameTime += physicsFrameStopwatch.Elapsed.TotalMilliseconds; 1696 tmpMS = tmpMS2;
1844 physicsMS = Util.EnvironmentTickCountSubtract(tmpMS);
1845
1846 // Start the stopwatch for the remainder of the simulation
1847 simFrameStopwatch.Restart();
1848 tmpMS = Util.EnvironmentTickCount();
1849 1697
1850 // Check if any objects have reached their targets 1698 // Check if any objects have reached their targets
1851 CheckAtTargets(); 1699 CheckAtTargets();
@@ -1860,20 +1708,37 @@ namespace OpenSim.Region.Framework.Scenes
1860 if (Frame % m_update_presences == 0) 1708 if (Frame % m_update_presences == 0)
1861 m_sceneGraph.UpdatePresences(); 1709 m_sceneGraph.UpdatePresences();
1862 1710
1863 agentMS += Util.EnvironmentTickCountSubtract(tmpMS); 1711 tmpMS2 = Util.GetTimeStampMS();
1712 agentMS += (float)(tmpMS2 - tmpMS);
1713 tmpMS = tmpMS2;
1714
1715 // Delete temp-on-rez stuff
1716 if (Frame % m_update_temp_cleaning == 0 && !m_cleaningTemps)
1717 {
1718 m_cleaningTemps = true;
1719 WorkManager.RunInThreadPool(
1720 delegate { CleanTempObjects(); m_cleaningTemps = false; }, null, string.Format("CleanTempObjects ({0})", Name));
1721 tmpMS2 = Util.GetTimeStampMS();
1722 tempOnRezMS = (float)(tmpMS2 - tmpMS); // bad.. counts the FireAndForget, not CleanTempObjects
1723 tmpMS = tmpMS2;
1724 }
1864 1725
1865 if (Frame % m_update_events == 0) 1726 if (Frame % m_update_events == 0)
1866 { 1727 {
1867 tmpMS = Util.EnvironmentTickCount();
1868 UpdateEvents(); 1728 UpdateEvents();
1869 eventMS = Util.EnvironmentTickCountSubtract(tmpMS); 1729
1730 tmpMS2 = Util.GetTimeStampMS();
1731 eventMS = (float)(tmpMS2 - tmpMS);
1732 tmpMS = tmpMS2;
1870 } 1733 }
1871 1734
1872 if (PeriodicBackup && Frame % m_update_backup == 0) 1735 if (PeriodicBackup && Frame % m_update_backup == 0)
1873 { 1736 {
1874 tmpMS = Util.EnvironmentTickCount();
1875 UpdateStorageBackup(); 1737 UpdateStorageBackup();
1876 backupMS = Util.EnvironmentTickCountSubtract(tmpMS); 1738
1739 tmpMS2 = Util.GetTimeStampMS();
1740 backupMS = (float)(tmpMS2 - tmpMS);
1741 tmpMS = tmpMS2;
1877 } 1742 }
1878 1743
1879 //if (Frame % m_update_land == 0) 1744 //if (Frame % m_update_land == 0)
@@ -1885,13 +1750,9 @@ namespace OpenSim.Region.Framework.Scenes
1885 1750
1886 if (!LoginsEnabled && Frame == 20) 1751 if (!LoginsEnabled && Frame == 20)
1887 { 1752 {
1888 // m_log.DebugFormat("{0} {1} {2}", LoginsDisabled, m_sceneGraph.GetActiveScriptsCount(), LoginLock);
1889
1890 // In 99.9% of cases it is a bad idea to manually force garbage collection. However,
1891 // this is a rare case where we know we have just went through a long cycle of heap
1892 // allocations, and there is no more work to be done until someone logs in
1893 GC.Collect(); 1753 GC.Collect();
1894 1754 GC.WaitForPendingFinalizers();
1755 GC.Collect();
1895 if (!LoginLock) 1756 if (!LoginLock)
1896 { 1757 {
1897 if (!StartDisabled) 1758 if (!StartDisabled)
@@ -1916,6 +1777,7 @@ namespace OpenSim.Region.Framework.Scenes
1916 // LoginLock can currently only be set by a region module implementation. 1777 // LoginLock can currently only be set by a region module implementation.
1917 // If somehow this hasn't been done then the quickest way to bugfix is to see the 1778 // If somehow this hasn't been done then the quickest way to bugfix is to see the
1918 // NullReferenceException 1779 // NullReferenceException
1780
1919 IRegionReadyModule rrm = RequestModuleInterface<IRegionReadyModule>(); 1781 IRegionReadyModule rrm = RequestModuleInterface<IRegionReadyModule>();
1920 rrm.TriggerRegionReady(this); 1782 rrm.TriggerRegionReady(this);
1921 } 1783 }
@@ -1930,79 +1792,64 @@ namespace OpenSim.Region.Framework.Scenes
1930 } 1792 }
1931 1793
1932 EventManager.TriggerRegionHeartbeatEnd(this); 1794 EventManager.TriggerRegionHeartbeatEnd(this);
1933 otherMS = eventMS + backupMS + terrainMS + landMS; 1795 m_firstHeartbeat = false;
1796 Watchdog.UpdateThread();
1934 1797
1935 // Get the elapsed time for the simulation frame 1798 otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS;
1936 simFrameStopwatch.Stop();
1937 preciseSimFrameTime +=
1938 simFrameStopwatch.Elapsed.TotalMilliseconds;
1939 1799
1940 if (!UpdateOnTimer) 1800 tmpMS = Util.GetTimeStampMS();
1941 {
1942 Watchdog.UpdateThread();
1943 1801
1944 spareMS = MinFrameTicks - Util.EnvironmentTickCountSubtract(m_lastFrameTick); 1802 previousFrameTick = m_lastFrameTick;
1803 m_lastFrameTick = (int)(tmpMS + 0.5);
1945 1804
1946 if (spareMS > 0) 1805 // estimate sleep time
1947 m_updateWaitEvent.WaitOne(spareMS); 1806 tmpMS2 = tmpMS - framestart;
1948 else 1807 tmpMS2 = (double)frameTimeMS - tmpMS2 - sleepError;
1949 spareMS = 0; 1808
1950 } 1809 // reuse frameMS as temporary
1810 frameMS = (float)tmpMS2;
1811
1812 // sleep if we can
1813 if (tmpMS2 > 0)
1814 {
1815 Thread.Sleep((int)(tmpMS2 + 0.5));
1816
1817 tmpMS2 = Util.GetTimeStampMS();
1818 sleepMS = (float)(tmpMS2 - tmpMS);
1819 sleepError = sleepMS - frameMS;
1820 Util.Clamp(sleepError, 0.0f, 20f);
1821 frameMS = (float)(tmpMS2 - framestart);
1822 }
1951 else 1823 else
1952 { 1824 {
1953 spareMS = Math.Max(0, MinFrameTicks - physicsMS2 - agentMS - physicsMS - otherMS); 1825 tmpMS2 = Util.GetTimeStampMS();
1954 } 1826 frameMS = (float)(tmpMS2 - framestart);
1827 sleepMS = 0.0f;
1828 sleepError = 0.0f;
1829 }
1955 1830
1956 // Get the total frame time 1831 // script time is not scene frame time, but is displayed per frame
1957 totalFrameStopwatch.Stop(); 1832 float scriptTimeMS = GetAndResetScriptExecutionTime();
1958 preciseTotalFrameTime = 1833 StatsReporter.AddFrameStats(TimeDilation, physicsFPS, agentMS,
1959 totalFrameStopwatch.Elapsed.TotalMilliseconds; 1834 physicsMS + physicsMS2, otherMS , sleepMS, frameMS, scriptTimeMS);
1960 1835
1961 // Restart the stopwatch for the total time of the next frame
1962 totalFrameStopwatch.Restart();
1963 1836
1964 previousFrameTick = m_lastFrameTick;
1965 frameMS = Util.EnvironmentTickCountSubtract(m_lastFrameTick);
1966 m_lastFrameTick = Util.EnvironmentTickCount();
1967 1837
1968 // if (Frame%m_update_avatars == 0) 1838 // if (Frame%m_update_avatars == 0)
1969 // UpdateInWorldTime(); 1839 // UpdateInWorldTime();
1970 StatsReporter.AddPhysicsFPS(physicsFPS); 1840
1971 StatsReporter.AddTimeDilation(TimeDilation); 1841 // Optionally warn if a frame takes double the amount of time that it should.
1972 StatsReporter.AddFPS(1);
1973
1974 StatsReporter.addFrameMS(frameMS);
1975 StatsReporter.addAgentMS(agentMS);
1976 StatsReporter.addPhysicsMS(physicsMS + physicsMS2);
1977 StatsReporter.addOtherMS(otherMS);
1978 StatsReporter.AddSpareMS(spareMS);
1979 StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS());
1980 StatsReporter.AddScriptMS((int) GetAndResetScriptExecutionTime());
1981
1982 // Send the correct time values to the stats reporter for the
1983 // frame times
1984 StatsReporter.addFrameTimeMilliseconds(preciseTotalFrameTime,
1985 preciseSimFrameTime, precisePhysicsFrameTime, 0.0);
1986
1987 // Send the correct number of frames that the physics library
1988 // has processed to the stats reporter
1989 StatsReporter.addPhysicsFrame(1);
1990
1991 // Optionally warn if a frame takes double the amount of time that it should.
1992 if (DebugUpdates 1842 if (DebugUpdates
1993 && Util.EnvironmentTickCountSubtract( 1843 && Util.EnvironmentTickCountSubtract(
1994 m_lastFrameTick, previousFrameTick) > MinFrameTicks * 2) 1844 m_lastFrameTick, previousFrameTick) > (int)(FrameTime * 1000 * 2))
1845
1995 m_log.WarnFormat( 1846 m_log.WarnFormat(
1996 "[SCENE]: Frame took {0} ms (desired max {1} ms) in {2}", 1847 "[SCENE]: Frame took {0} ms (desired max {1} ms) in {2}",
1997 Util.EnvironmentTickCountSubtract(m_lastFrameTick, previousFrameTick), 1848 Util.EnvironmentTickCountSubtract(m_lastFrameTick, previousFrameTick),
1998 MinFrameTicks, 1849 FrameTime * 1000,
1850
1999 RegionInfo.RegionName); 1851 RegionInfo.RegionName);
2000 } 1852 }
2001
2002 // Finished updating scene frame, so stop the total frame's Stopwatch
2003 totalFrameStopwatch.Stop();
2004
2005 return spareMS >= 0;
2006 } 1853 }
2007 1854
2008 /// <summary> 1855 /// <summary>
@@ -2011,24 +1858,28 @@ namespace OpenSim.Region.Framework.Scenes
2011 /// <param name="ticks">Elapsed Stopwatch ticks</param> 1858 /// <param name="ticks">Elapsed Stopwatch ticks</param>
2012 public void AddScriptExecutionTime(long ticks) 1859 public void AddScriptExecutionTime(long ticks)
2013 { 1860 {
1861 StatsReporter.addScriptEvents(1);
2014 Interlocked.Add(ref m_scriptExecutionTime, ticks); 1862 Interlocked.Add(ref m_scriptExecutionTime, ticks);
2015 } 1863 }
2016 1864
2017 /// <summary> 1865 /// <summary>
2018 /// Returns the total execution time of all the scripts in the region since the last frame 1866 /// Returns the total execution time of all the scripts in the region since the last call
2019 /// (in milliseconds), and clears the value in preparation for the next frame. 1867 /// (in milliseconds), and clears the value in preparation for the next call.
2020 /// </summary> 1868 /// </summary>
2021 /// <returns>Time in milliseconds</returns> 1869 /// <returns>Time in milliseconds</returns>
2022 private long GetAndResetScriptExecutionTime() 1870
1871 // Warning: this is now called from StatsReporter, and can't be shared
1872
1873 public long GetAndResetScriptExecutionTime()
2023 { 1874 {
2024 long ticks = Interlocked.Exchange(ref m_scriptExecutionTime, 0); 1875 long ticks = Interlocked.Exchange(ref m_scriptExecutionTime, 0);
2025 return (ticks * 1000) / Stopwatch.Frequency; 1876 return (ticks * 1000L) / Stopwatch.Frequency;
2026 } 1877 }
2027 1878
2028 public void AddGroupTarget(SceneObjectGroup grp) 1879 public void AddGroupTarget(SceneObjectGroup grp)
2029 { 1880 {
2030 lock (m_groupsWithTargets) 1881 lock (m_groupsWithTargets)
2031 m_groupsWithTargets[grp.UUID] = grp; 1882 m_groupsWithTargets[grp.UUID] = 0;
2032 } 1883 }
2033 1884
2034 public void RemoveGroupTarget(SceneObjectGroup grp) 1885 public void RemoveGroupTarget(SceneObjectGroup grp)
@@ -2039,18 +1890,24 @@ namespace OpenSim.Region.Framework.Scenes
2039 1890
2040 private void CheckAtTargets() 1891 private void CheckAtTargets()
2041 { 1892 {
2042 List<SceneObjectGroup> objs = null; 1893 List<UUID> objs = null;
2043 1894
2044 lock (m_groupsWithTargets) 1895 lock (m_groupsWithTargets)
2045 { 1896 {
2046 if (m_groupsWithTargets.Count != 0) 1897 if (m_groupsWithTargets.Count != 0)
2047 objs = new List<SceneObjectGroup>(m_groupsWithTargets.Values); 1898 objs = new List<UUID>(m_groupsWithTargets.Keys);
2048 } 1899 }
2049 1900
2050 if (objs != null) 1901 if (objs != null)
2051 { 1902 {
2052 foreach (SceneObjectGroup entry in objs) 1903 foreach (UUID entry in objs)
2053 entry.checkAtTargets(); 1904 {
1905 SceneObjectGroup grp = GetSceneObjectGroup(entry);
1906 if (grp == null)
1907 m_groupsWithTargets.Remove(entry);
1908 else
1909 grp.checkAtTargets();
1910 }
2054 } 1911 }
2055 } 1912 }
2056 1913
@@ -2074,6 +1931,11 @@ namespace OpenSim.Region.Framework.Scenes
2074 EventManager.TriggerTerrainTick(); 1931 EventManager.TriggerTerrainTick();
2075 } 1932 }
2076 1933
1934 private void CheckTerrainUpdates()
1935 {
1936 EventManager.TriggerTerrainCheckUpdates();
1937 }
1938
2077 /// <summary> 1939 /// <summary>
2078 /// Back up queued up changes 1940 /// Back up queued up changes
2079 /// </summary> 1941 /// </summary>
@@ -2081,8 +1943,7 @@ namespace OpenSim.Region.Framework.Scenes
2081 { 1943 {
2082 if (!m_backingup) 1944 if (!m_backingup)
2083 { 1945 {
2084 m_backingup = true; 1946 WorkManager.RunInThreadPool(o => Backup(false), null, string.Format("BackupWorker ({0}", Name), false);
2085 WorkManager.RunInThread(o => Backup(false), null, string.Format("BackupWaitCallback ({0})", Name));
2086 } 1947 }
2087 } 1948 }
2088 1949
@@ -2110,38 +1971,58 @@ namespace OpenSim.Region.Framework.Scenes
2110 { 1971 {
2111 lock (m_returns) 1972 lock (m_returns)
2112 { 1973 {
2113 EventManager.TriggerOnBackup(SimulationDataService, forced); 1974 if(m_backingup)
2114 m_backingup = false; 1975 {
1976 m_log.WarnFormat("[Scene] Backup of {0} already running. New call skipped", RegionInfo.RegionName);
1977 return;
1978 }
2115 1979
2116 foreach (KeyValuePair<UUID, ReturnInfo> ret in m_returns) 1980 m_backingup = true;
1981 try
2117 { 1982 {
2118 UUID transaction = UUID.Random(); 1983 EventManager.TriggerOnBackup(SimulationDataService, forced);
2119 1984
2120 GridInstantMessage msg = new GridInstantMessage(); 1985 if(m_returns.Count == 0)
2121 msg.fromAgentID = new Guid(UUID.Zero.ToString()); // From server 1986 return;
2122 msg.toAgentID = new Guid(ret.Key.ToString());
2123 msg.imSessionID = new Guid(transaction.ToString());
2124 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();
2125 msg.fromAgentName = "Server";
2126 msg.dialog = (byte)19; // Object msg
2127 msg.fromGroup = false;
2128 msg.offline = (byte)0;
2129 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID;
2130 msg.Position = Vector3.Zero;
2131 msg.RegionID = RegionInfo.RegionID.Guid;
2132
2133 // We must fill in a null-terminated 'empty' string here since bytes[0] will crash viewer 3.
2134 msg.binaryBucket = Util.StringToBytes256("\0");
2135 if (ret.Value.count > 1)
2136 msg.message = string.Format("Your {0} objects were returned from {1} in region {2} due to {3}", ret.Value.count, ret.Value.location.ToString(), RegionInfo.RegionName, ret.Value.reason);
2137 else
2138 msg.message = string.Format("Your object {0} was returned from {1} in region {2} due to {3}", ret.Value.objectName, ret.Value.location.ToString(), RegionInfo.RegionName, ret.Value.reason);
2139 1987
2140 IMessageTransferModule tr = RequestModuleInterface<IMessageTransferModule>(); 1988 IMessageTransferModule tr = RequestModuleInterface<IMessageTransferModule>();
2141 if (tr != null) 1989 if (tr == null)
1990 return;
1991
1992 uint unixtime = (uint)Util.UnixTimeSinceEpoch();
1993 uint estateid = RegionInfo.EstateSettings.ParentEstateID;
1994 Guid regionguid = RegionInfo.RegionID.Guid;
1995
1996 foreach (KeyValuePair<UUID, ReturnInfo> ret in m_returns)
1997 {
1998 GridInstantMessage msg = new GridInstantMessage();
1999 msg.fromAgentID = Guid.Empty; // From server
2000 msg.toAgentID = ret.Key.Guid;
2001 msg.imSessionID = Guid.NewGuid();
2002 msg.timestamp = unixtime;
2003 msg.fromAgentName = "Server";
2004 msg.dialog = 19; // Object msg
2005 msg.fromGroup = false;
2006 msg.offline = 1;
2007 msg.ParentEstateID = estateid;
2008 msg.Position = Vector3.Zero;
2009 msg.RegionID = regionguid;
2010
2011 // We must fill in a null-terminated 'empty' string here since bytes[0] will crash viewer 3.
2012 msg.binaryBucket = new Byte[1] {0};
2013 if (ret.Value.count > 1)
2014 msg.message = string.Format("Your {0} objects were returned from {1} in region {2} due to {3}", ret.Value.count, ret.Value.location.ToString(), RegionInfo.RegionName, ret.Value.reason);
2015 else
2016 msg.message = string.Format("Your object {0} was returned from {1} in region {2} due to {3}", ret.Value.objectName, ret.Value.location.ToString(), RegionInfo.RegionName, ret.Value.reason);
2017
2142 tr.SendInstantMessage(msg, delegate(bool success) { }); 2018 tr.SendInstantMessage(msg, delegate(bool success) { });
2019 }
2020 m_returns.Clear();
2021 }
2022 finally
2023 {
2024 m_backingup = false;
2143 } 2025 }
2144 m_returns.Clear();
2145 } 2026 }
2146 } 2027 }
2147 2028
@@ -2159,7 +2040,7 @@ namespace OpenSim.Region.Framework.Scenes
2159 } 2040 }
2160 2041
2161 /// <summary> 2042 /// <summary>
2162 /// Tell an agent that their object has been returned. 2043 /// Tell an agent that their object has been returned.
2163 /// </summary> 2044 /// </summary>
2164 /// <remarks> 2045 /// <remarks>
2165 /// The actual return is handled by the caller. 2046 /// The actual return is handled by the caller.
@@ -2199,7 +2080,16 @@ namespace OpenSim.Region.Framework.Scenes
2199 /// </summary> 2080 /// </summary>
2200 public void SaveTerrain() 2081 public void SaveTerrain()
2201 { 2082 {
2202 SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); 2083 SimulationDataService.StoreTerrain(Heightmap.GetTerrainData(), RegionInfo.RegionID);
2084 }
2085
2086 /// <summary>
2087 /// Store the terrain in the persistant data store
2088 /// </summary>
2089 public void SaveBakedTerrain()
2090 {
2091 if(Bakedmap != null)
2092 SimulationDataService.StoreBakedTerrain(Bakedmap.GetTerrainData(), RegionInfo.RegionID);
2203 } 2093 }
2204 2094
2205 public void StoreWindlightProfile(RegionLightShareData wl) 2095 public void StoreWindlightProfile(RegionLightShareData wl)
@@ -2222,20 +2112,44 @@ namespace OpenSim.Region.Framework.Scenes
2222 { 2112 {
2223 try 2113 try
2224 { 2114 {
2115 Bakedmap = null;
2116 TerrainData map = SimulationDataService.LoadBakedTerrain(RegionInfo.RegionID, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ);
2117 if (map != null)
2118 {
2119 Bakedmap = new TerrainChannel(map);
2120 }
2121 }
2122 catch (Exception e)
2123 {
2124 m_log.WarnFormat(
2125 "[TERRAIN]: Scene.cs: LoadWorldMap() baked terrain - Failed with exception {0}{1}", e.Message, e.StackTrace);
2126 }
2127
2128 try
2129 {
2225 TerrainData map = SimulationDataService.LoadTerrain(RegionInfo.RegionID, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ); 2130 TerrainData map = SimulationDataService.LoadTerrain(RegionInfo.RegionID, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ);
2226 if (map == null) 2131 if (map == null)
2227 { 2132 {
2228 // This should be in the Terrain module, but it isn't because 2133 if(Bakedmap != null)
2229 // the heightmap is needed _way_ before the modules are initialized... 2134 {
2230 IConfig terrainConfig = m_config.Configs["Terrain"]; 2135 m_log.Warn("[TERRAIN]: terrain not found. Used stored baked terrain.");
2231 String m_InitialTerrain = "pinhead-island"; 2136 Heightmap = Bakedmap.MakeCopy();
2232 if (terrainConfig != null) 2137 SimulationDataService.StoreTerrain(Heightmap.GetTerrainData(), RegionInfo.RegionID);
2233 m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain); 2138 }
2139 else
2140 {
2141 // This should be in the Terrain module, but it isn't because
2142 // the heightmap is needed _way_ before the modules are initialized...
2143 IConfig terrainConfig = m_config.Configs["Terrain"];
2144 String m_InitialTerrain = "pinhead-island";
2145 if (terrainConfig != null)
2146 m_InitialTerrain = terrainConfig.GetString("InitialTerrain", m_InitialTerrain);
2234 2147
2235 m_log.InfoFormat("[TERRAIN]: No default terrain. Generating a new terrain {0}.", m_InitialTerrain); 2148 m_log.InfoFormat("[TERRAIN]: No default terrain. Generating a new terrain {0}.", m_InitialTerrain);
2236 Heightmap = new TerrainChannel(m_InitialTerrain, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ); 2149 Heightmap = new TerrainChannel(m_InitialTerrain, (int)RegionInfo.RegionSizeX, (int)RegionInfo.RegionSizeY, (int)RegionInfo.RegionSizeZ);
2237 2150
2238 SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); 2151 SimulationDataService.StoreTerrain(Heightmap.GetTerrainData(), RegionInfo.RegionID);
2152 }
2239 } 2153 }
2240 else 2154 else
2241 { 2155 {
@@ -2248,13 +2162,12 @@ namespace OpenSim.Region.Framework.Scenes
2248 "[TERRAIN]: Scene.cs: LoadWorldMap() - Regenerating as failed with exception {0}{1}", 2162 "[TERRAIN]: Scene.cs: LoadWorldMap() - Regenerating as failed with exception {0}{1}",
2249 e.Message, e.StackTrace); 2163 e.Message, e.StackTrace);
2250 2164
2251 // Non standard region size. If there's an old terrain in the database, it might read past the buffer
2252#pragma warning disable 0162 2165#pragma warning disable 0162
2253 if ((int)Constants.RegionSize != 256) 2166 if ((int)Constants.RegionSize != 256)
2254 { 2167 {
2255 Heightmap = new TerrainChannel(); 2168 Heightmap = new TerrainChannel();
2256 2169
2257 SimulationDataService.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); 2170 SimulationDataService.StoreTerrain(Heightmap.GetTerrainData(), RegionInfo.RegionID);
2258 } 2171 }
2259 } 2172 }
2260 catch (Exception e) 2173 catch (Exception e)
@@ -2262,6 +2175,12 @@ namespace OpenSim.Region.Framework.Scenes
2262 m_log.WarnFormat( 2175 m_log.WarnFormat(
2263 "[TERRAIN]: Scene.cs: LoadWorldMap() - Failed with exception {0}{1}", e.Message, e.StackTrace); 2176 "[TERRAIN]: Scene.cs: LoadWorldMap() - Failed with exception {0}{1}", e.Message, e.StackTrace);
2264 } 2177 }
2178
2179 if(Bakedmap == null && Heightmap != null)
2180 {
2181 Bakedmap = Heightmap.MakeCopy();
2182 SimulationDataService.StoreBakedTerrain(Bakedmap.GetTerrainData(), RegionInfo.RegionID);
2183 }
2265 } 2184 }
2266 2185
2267 /// <summary> 2186 /// <summary>
@@ -2277,12 +2196,12 @@ namespace OpenSim.Region.Framework.Scenes
2277 //// stored in the GridService, because that's what the world map module uses 2196 //// stored in the GridService, because that's what the world map module uses
2278 //// to send the map image UUIDs (of other regions) to the viewer... 2197 //// to send the map image UUIDs (of other regions) to the viewer...
2279 if (m_generateMaptiles) 2198 if (m_generateMaptiles)
2280 RegenerateMaptile(); 2199 RegenerateMaptile();
2281 2200
2282 GridRegion region = new GridRegion(RegionInfo); 2201 GridRegion region = new GridRegion(RegionInfo);
2283 string error = GridService.RegisterRegion(RegionInfo.ScopeID, region); 2202 string error = GridService.RegisterRegion(RegionInfo.ScopeID, region);
2284 // m_log.DebugFormat("[SCENE]: RegisterRegionWithGrid. name={0},id={1},loc=<{2},{3}>,size=<{4},{5}>", 2203 // m_log.DebugFormat("[SCENE]: RegisterRegionWithGrid. name={0},id={1},loc=<{2},{3}>,size=<{4},{5}>",
2285 // m_regionName, 2204 // m_regionName,
2286 // RegionInfo.RegionID, 2205 // RegionInfo.RegionID,
2287 // RegionInfo.RegionLocX, RegionInfo.RegionLocY, 2206 // RegionInfo.RegionLocX, RegionInfo.RegionLocY,
2288 // RegionInfo.RegionSizeX, RegionInfo.RegionSizeY); 2207 // RegionInfo.RegionSizeX, RegionInfo.RegionSizeY);
@@ -2344,7 +2263,9 @@ namespace OpenSim.Region.Framework.Scenes
2344 EventManager.TriggerOnSceneObjectLoaded(group); 2263 EventManager.TriggerOnSceneObjectLoaded(group);
2345 SceneObjectPart rootPart = group.GetPart(group.UUID); 2264 SceneObjectPart rootPart = group.GetPart(group.UUID);
2346 rootPart.Flags &= ~PrimFlags.Scripted; 2265 rootPart.Flags &= ~PrimFlags.Scripted;
2266
2347 rootPart.TrimPermissions(); 2267 rootPart.TrimPermissions();
2268 group.InvalidateDeepEffectivePerms();
2348 2269
2349 // Don't do this here - it will get done later on when sculpt data is loaded. 2270 // Don't do this here - it will get done later on when sculpt data is loaded.
2350 // group.CheckSculptAndLoad(); 2271 // group.CheckSculptAndLoad();
@@ -2383,93 +2304,166 @@ namespace OpenSim.Region.Framework.Scenes
2383 /// <returns></returns> 2304 /// <returns></returns>
2384 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) 2305 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter)
2385 { 2306 {
2386 Vector3 pos = Vector3.Zero;
2387 if (RayEndIsIntersection == (byte)1)
2388 {
2389 pos = RayEnd;
2390 return pos;
2391 }
2392 2307
2393 if (RayTargetID != UUID.Zero) 2308 Vector3 dir = RayEnd - RayStart;
2309
2310 float wheight = (float)RegionInfo.RegionSettings.WaterHeight;
2311 Vector3 wpos = Vector3.Zero;
2312 // Check for water surface intersection from above
2313 if ((RayStart.Z > wheight) && (RayEnd.Z < wheight))
2394 { 2314 {
2395 SceneObjectPart target = GetSceneObjectPart(RayTargetID); 2315 float ratio = (wheight - RayStart.Z) / dir.Z;
2316 wpos.X = RayStart.X + (ratio * dir.X);
2317 wpos.Y = RayStart.Y + (ratio * dir.Y);
2318 wpos.Z = wheight;
2319 }
2396 2320
2397 Vector3 direction = Vector3.Normalize(RayEnd - RayStart); 2321 Vector3 pos = Vector3.Zero;
2398 Vector3 AXOrigin = RayStart;
2399 Vector3 AXdirection = direction;
2400 2322
2401 if (target != null) 2323 if (RayEndIsIntersection != (byte)1)
2324 {
2325 float dist = dir.Length();
2326 if (dist != 0)
2402 { 2327 {
2403 pos = target.AbsolutePosition; 2328 Vector3 direction = dir * (1 / dist);
2404 //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());
2405 2329
2406 // TODO: Raytrace better here 2330 dist += 1.0f;
2407 2331
2408 //EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection)); 2332 if (SupportsRayCastFiltered())
2409 Ray NewRay = new Ray(AXOrigin, AXdirection); 2333 {
2334 RayFilterFlags rayfilter = RayFilterFlags.BackFaceCull;
2335 rayfilter |= RayFilterFlags.land;
2336 rayfilter |= RayFilterFlags.physical;
2337 rayfilter |= RayFilterFlags.nonphysical;
2338 rayfilter |= RayFilterFlags.LSLPhantom; // ubODE will only see volume detectors
2339
2340 // get some more contacts ???
2341 int physcount = 4;
2342
2343 List<ContactResult> physresults =
2344 (List<ContactResult>)RayCastFiltered(RayStart, direction, dist, physcount, rayfilter);
2345 if (physresults != null && physresults.Count > 0)
2346 {
2347 // look for terrain ?
2348 if(RayTargetID == UUID.Zero)
2349 {
2350 foreach (ContactResult r in physresults)
2351 {
2352 if (r.ConsumerID == 0)
2353 {
2354 pos = r.Normal * scale;
2355 pos *= 0.5f;
2356 pos = r.Pos + pos;
2357
2358 if (wpos.Z > pos.Z) pos = wpos;
2359 return pos;
2360 }
2361 }
2362 }
2363 else
2364 {
2365 foreach (ContactResult r in physresults)
2366 {
2367 SceneObjectPart part = GetSceneObjectPart(r.ConsumerID);
2368 if (part == null)
2369 continue;
2370 if (part.UUID == RayTargetID)
2371 {
2372 pos = r.Normal * scale;
2373 pos *= 0.5f;
2374 pos = r.Pos + pos;
2375
2376 if (wpos.Z > pos.Z) pos = wpos;
2377 return pos;
2378 }
2379 }
2380 }
2381 // else the first we got
2382 pos = physresults[0].Normal * scale;
2383 pos *= 0.5f;
2384 pos = physresults[0].Pos + pos;
2385
2386 if (wpos.Z > pos.Z)
2387 pos = wpos;
2388 return pos;
2389 }
2410 2390
2411 // Ray Trace against target here 2391 }
2412 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); 2392 if (RayTargetID != UUID.Zero)
2393 {
2394 SceneObjectPart target = GetSceneObjectPart(RayTargetID);
2413 2395
2414 // Un-comment out the following line to Get Raytrace results printed to the console. 2396 Ray NewRay = new Ray(RayStart, direction);
2415 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
2416 float ScaleOffset = 0.5f;
2417 2397
2418 // If we hit something 2398 if (target != null)
2419 if (ei.HitTF) 2399 {
2420 { 2400 pos = target.AbsolutePosition;
2421 Vector3 scaleComponent = ei.AAfaceNormal;
2422 if (scaleComponent.X != 0) ScaleOffset = scale.X;
2423 if (scaleComponent.Y != 0) ScaleOffset = scale.Y;
2424 if (scaleComponent.Z != 0) ScaleOffset = scale.Z;
2425 ScaleOffset = Math.Abs(ScaleOffset);
2426 Vector3 intersectionpoint = ei.ipoint;
2427 Vector3 normal = ei.normal;
2428 // Set the position to the intersection point
2429 Vector3 offset = (normal * (ScaleOffset / 2f));
2430 pos = (intersectionpoint + offset);
2431
2432 //Seems to make no sense to do this as this call is used for rezzing from inventory as well, and with inventory items their size is not always 0.5f
2433 //And in cases when we weren't rezzing from inventory we were re-adding the 0.25 straight after calling this method
2434 // Un-offset the prim (it gets offset later by the consumer method)
2435 //pos.Z -= 0.25F;
2436 2401
2437 } 2402 // Ray Trace against target here
2403 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);
2438 2404
2439 return pos; 2405 // Un-comment out the following line to Get Raytrace results printed to the console.
2440 } 2406 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
2441 else 2407 float ScaleOffset = 0.5f;
2442 {
2443 // We don't have a target here, so we're going to raytrace all the objects in the scene.
2444 2408
2445 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); 2409 // If we hit something
2410 if (ei.HitTF)
2411 {
2412 Vector3 scaleComponent = ei.AAfaceNormal;
2413 if (scaleComponent.X != 0) ScaleOffset = scale.X;
2414 if (scaleComponent.Y != 0) ScaleOffset = scale.Y;
2415 if (scaleComponent.Z != 0) ScaleOffset = scale.Z;
2416 ScaleOffset = Math.Abs(ScaleOffset);
2417 Vector3 intersectionpoint = ei.ipoint;
2418 Vector3 normal = ei.normal;
2419 // Set the position to the intersection point
2420 Vector3 offset = (normal * (ScaleOffset / 2f));
2421 pos = (intersectionpoint + offset);
2422
2423 //Seems to make no sense to do this as this call is used for rezzing from inventory as well, and with inventory items their size is not always 0.5f
2424 //And in cases when we weren't rezzing from inventory we were re-adding the 0.25 straight after calling this method
2425 // Un-offset the prim (it gets offset later by the consumer method)
2426 //pos.Z -= 0.25F;
2427
2428 if (wpos.Z > pos.Z) pos = wpos;
2429 return pos;
2430 }
2431 }
2432 else
2433 {
2434 // We don't have a target here, so we're going to raytrace all the objects in the scene.
2435 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(NewRay, true, false);
2446 2436
2447 // Un-comment the following line to print the raytrace results to the console. 2437 // Un-comment the following line to print the raytrace results to the console.
2448 //m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); 2438 //m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
2449 2439
2450 if (ei.HitTF) 2440 if (ei.HitTF)
2451 { 2441 {
2452 pos = ei.ipoint; 2442 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
2453 } 2443 }
2454 else 2444 else
2455 { 2445 {
2456 // fall back to our stupid functionality 2446 // fall back to our stupid functionality
2457 pos = RayEnd; 2447 pos = RayEnd;
2458 } 2448 }
2459 2449
2460 return pos; 2450 if (wpos.Z > pos.Z) pos = wpos;
2451 return pos;
2452 }
2453 }
2461 } 2454 }
2462 } 2455 }
2463 else
2464 {
2465 // fall back to our stupid functionality
2466 pos = RayEnd;
2467 2456
2468 //increase height so its above the ground. 2457 // fall back to our stupid functionality
2469 //should be getting the normal of the ground at the rez point and using that? 2458 pos = RayEnd;
2470 pos.Z += scale.Z / 2f; 2459
2471 return pos; 2460 //increase height so its above the ground.
2472 } 2461 //should be getting the normal of the ground at the rez point and using that?
2462 pos.Z += scale.Z / 2f;
2463 // return pos;
2464 // check against posible water intercept
2465 if (wpos.Z > pos.Z) pos = wpos;
2466 return pos;
2473 } 2467 }
2474 2468
2475 2469
@@ -2523,13 +2517,26 @@ namespace OpenSim.Region.Framework.Scenes
2523 { 2517 {
2524 // Otherwise, use this default creation code; 2518 // Otherwise, use this default creation code;
2525 sceneObject = new SceneObjectGroup(ownerID, pos, rot, shape); 2519 sceneObject = new SceneObjectGroup(ownerID, pos, rot, shape);
2526 AddNewSceneObject(sceneObject, true);
2527 sceneObject.SetGroup(groupID, null); 2520 sceneObject.SetGroup(groupID, null);
2521 AddNewSceneObject(sceneObject, true);
2522
2523 if (AgentPreferencesService != null) // This will override the brave new full perm world!
2524 {
2525 AgentPrefs prefs = AgentPreferencesService.GetAgentPreferences(ownerID);
2526 // Only apply user selected prefs if the user set them
2527 if (prefs != null && prefs.PermNextOwner != 0)
2528 {
2529 sceneObject.RootPart.GroupMask = (uint)prefs.PermGroup;
2530 sceneObject.RootPart.EveryoneMask = (uint)prefs.PermEveryone;
2531 sceneObject.RootPart.NextOwnerMask = (uint)prefs.PermNextOwner;
2532 }
2533 }
2528 } 2534 }
2529 2535
2530 if (UserManagementModule != null) 2536 if (UserManagementModule != null)
2531 sceneObject.RootPart.CreatorIdentification = UserManagementModule.GetUserUUI(ownerID); 2537 sceneObject.RootPart.CreatorIdentification = UserManagementModule.GetUserUUI(ownerID);
2532 2538
2539 sceneObject.InvalidateDeepEffectivePerms();;
2533 sceneObject.ScheduleGroupForFullUpdate(); 2540 sceneObject.ScheduleGroupForFullUpdate();
2534 2541
2535 return sceneObject; 2542 return sceneObject;
@@ -2560,12 +2567,12 @@ namespace OpenSim.Region.Framework.Scenes
2560 { 2567 {
2561 if (m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates)) 2568 if (m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates))
2562 { 2569 {
2570 sceneObject.IsDeleted = false;
2563 EventManager.TriggerObjectAddedToScene(sceneObject); 2571 EventManager.TriggerObjectAddedToScene(sceneObject);
2564 return true; 2572 return true;
2565 } 2573 }
2566 2574
2567 return false; 2575 return false;
2568
2569 } 2576 }
2570 2577
2571 /// <summary> 2578 /// <summary>
@@ -2657,6 +2664,15 @@ namespace OpenSim.Region.Framework.Scenes
2657 /// </summary> 2664 /// </summary>
2658 public void DeleteAllSceneObjects() 2665 public void DeleteAllSceneObjects()
2659 { 2666 {
2667 DeleteAllSceneObjects(false);
2668 }
2669
2670 /// <summary>
2671 /// Delete every object from the scene. This does not include attachments worn by avatars.
2672 /// </summary>
2673 public void DeleteAllSceneObjects(bool exceptNoCopy)
2674 {
2675 List<SceneObjectGroup> toReturn = new List<SceneObjectGroup>();
2660 lock (Entities) 2676 lock (Entities)
2661 { 2677 {
2662 EntityBase[] entities = Entities.GetEntities(); 2678 EntityBase[] entities = Entities.GetEntities();
@@ -2665,11 +2681,24 @@ namespace OpenSim.Region.Framework.Scenes
2665 if (e is SceneObjectGroup) 2681 if (e is SceneObjectGroup)
2666 { 2682 {
2667 SceneObjectGroup sog = (SceneObjectGroup)e; 2683 SceneObjectGroup sog = (SceneObjectGroup)e;
2668 if (!sog.IsAttachment) 2684 if (sog != null && !sog.IsAttachment)
2669 DeleteSceneObject((SceneObjectGroup)e, false); 2685 {
2686 if (!exceptNoCopy || ((sog.EffectiveOwnerPerms & (uint)PermissionMask.Copy) != 0))
2687 {
2688 DeleteSceneObject((SceneObjectGroup)e, false);
2689 }
2690 else
2691 {
2692 toReturn.Add((SceneObjectGroup)e);
2693 }
2694 }
2670 } 2695 }
2671 } 2696 }
2672 } 2697 }
2698 if (toReturn.Count > 0)
2699 {
2700 returnObjects(toReturn.ToArray(), null);
2701 }
2673 } 2702 }
2674 2703
2675 /// <summary> 2704 /// <summary>
@@ -2728,7 +2757,11 @@ namespace OpenSim.Region.Framework.Scenes
2728 2757
2729 group.DeleteGroupFromScene(silent); 2758 group.DeleteGroupFromScene(silent);
2730 2759
2731 // m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); 2760 // use this to mean also full delete
2761 if (removeScripts)
2762 group.Clear();
2763 partList = null;
2764 // m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
2732 } 2765 }
2733 2766
2734 /// <summary> 2767 /// <summary>
@@ -2763,6 +2796,13 @@ namespace OpenSim.Region.Framework.Scenes
2763 return false; 2796 return false;
2764 } 2797 }
2765 2798
2799
2800 public void updateScenePartGroup(SceneObjectPart part, SceneObjectGroup grp)
2801 {
2802 m_sceneGraph.updateScenePartGroup(part, grp);
2803 }
2804
2805/* not in use, outdate by async method
2766 /// <summary> 2806 /// <summary>
2767 /// Move the given scene object into a new region depending on which region its absolute position has moved 2807 /// Move the given scene object into a new region depending on which region its absolute position has moved
2768 /// into. 2808 /// into.
@@ -2811,6 +2851,7 @@ namespace OpenSim.Region.Framework.Scenes
2811 if (EntityTransferModule != null) 2851 if (EntityTransferModule != null)
2812 EntityTransferModule.Cross(grp, attemptedPosition, silent); 2852 EntityTransferModule.Cross(grp, attemptedPosition, silent);
2813 } 2853 }
2854*/
2814 2855
2815 // Simple test to see if a position is in the current region. 2856 // Simple test to see if a position is in the current region.
2816 // This test is mostly used to see if a region crossing is necessary. 2857 // This test is mostly used to see if a region crossing is necessary.
@@ -2818,27 +2859,15 @@ namespace OpenSim.Region.Framework.Scenes
2818 // Return 'true' if position inside region. 2859 // Return 'true' if position inside region.
2819 public bool PositionIsInCurrentRegion(Vector3 pos) 2860 public bool PositionIsInCurrentRegion(Vector3 pos)
2820 { 2861 {
2821 bool ret = false; 2862 float t = pos.X;
2822 int xx = (int)Math.Floor(pos.X); 2863 if (t < 0 || t >= RegionInfo.RegionSizeX)
2823 int yy = (int)Math.Floor(pos.Y);
2824 if (xx < 0 || yy < 0)
2825 return false; 2864 return false;
2826 2865
2827 IRegionCombinerModule regionCombinerModule = RequestModuleInterface<IRegionCombinerModule>(); 2866 t = pos.Y;
2828 if (regionCombinerModule == null) 2867 if (t < 0 || t >= RegionInfo.RegionSizeY)
2829 { 2868 return false;
2830 // Regular region. Just check for region size
2831 if (xx < RegionInfo.RegionSizeX && yy < RegionInfo.RegionSizeY)
2832 ret = true;
2833 }
2834 else
2835 {
2836 // We're in a mega-region so see if we are still in that larger region
2837 ret = regionCombinerModule.PositionIsInMegaregion(this.RegionInfo.RegionID, xx, yy);
2838 }
2839
2840 return ret;
2841 2869
2870 return true;
2842 } 2871 }
2843 2872
2844 /// <summary> 2873 /// <summary>
@@ -2880,6 +2909,23 @@ namespace OpenSim.Region.Framework.Scenes
2880 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns> 2909 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns>
2881 public bool AddSceneObject(SceneObjectGroup sceneObject) 2910 public bool AddSceneObject(SceneObjectGroup sceneObject)
2882 { 2911 {
2912 if (sceneObject.OwnerID == UUID.Zero)
2913 {
2914 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero", sceneObject.UUID);
2915 return false;
2916 }
2917
2918 // If the user is banned, we won't let any of their objects
2919 // enter. Period.
2920 //
2921 int flags = GetUserFlags(sceneObject.OwnerID);
2922 if (RegionInfo.EstateSettings.IsBanned(sceneObject.OwnerID, flags))
2923 {
2924 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID);
2925
2926 return false;
2927 }
2928
2883 // Force allocation of new LocalId 2929 // Force allocation of new LocalId
2884 // 2930 //
2885 SceneObjectPart[] parts = sceneObject.Parts; 2931 SceneObjectPart[] parts = sceneObject.Parts;
@@ -2889,9 +2935,9 @@ namespace OpenSim.Region.Framework.Scenes
2889 if (sceneObject.IsAttachmentCheckFull()) // Attachment 2935 if (sceneObject.IsAttachmentCheckFull()) // Attachment
2890 { 2936 {
2891 sceneObject.RootPart.AddFlag(PrimFlags.TemporaryOnRez); 2937 sceneObject.RootPart.AddFlag(PrimFlags.TemporaryOnRez);
2892 sceneObject.RootPart.AddFlag(PrimFlags.Phantom); 2938// sceneObject.RootPart.AddFlag(PrimFlags.Phantom);
2893 2939
2894 // Don't sent a full update here because this will cause full updates to be sent twice for 2940 // Don't sent a full update here because this will cause full updates to be sent twice for
2895 // attachments on region crossings, resulting in viewer glitches. 2941 // attachments on region crossings, resulting in viewer glitches.
2896 AddRestoredSceneObject(sceneObject, false, false, false); 2942 AddRestoredSceneObject(sceneObject, false, false, false);
2897 2943
@@ -2912,7 +2958,7 @@ namespace OpenSim.Region.Framework.Scenes
2912 2958
2913 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2959 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2914 2960
2915 // We must currently not resume scripts at this stage since AttachmentsModule does not have the 2961 // We must currently not resume scripts at this stage since AttachmentsModule does not have the
2916 // information that this is due to a teleport/border cross rather than an ordinary attachment. 2962 // information that this is due to a teleport/border cross rather than an ordinary attachment.
2917 // We currently do this in Scene.MakeRootAgent() instead. 2963 // We currently do this in Scene.MakeRootAgent() instead.
2918 if (AttachmentsModule != null) 2964 if (AttachmentsModule != null)
@@ -2920,18 +2966,60 @@ namespace OpenSim.Region.Framework.Scenes
2920 } 2966 }
2921 else 2967 else
2922 { 2968 {
2923 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2969 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was not found, setting to temp", sceneObject.UUID);
2924 RootPrim.AddFlag(PrimFlags.TemporaryOnRez); 2970// RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2971// RootPrim.AddFlag(PrimFlags.TemporaryOnRez);
2972 }
2973 if (sceneObject.OwnerID == UUID.Zero)
2974 {
2975 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero after attachment processing. BUG!", sceneObject.UUID);
2976 return false;
2925 } 2977 }
2926 } 2978 }
2927 else 2979 else
2928 { 2980 {
2981 if (sceneObject.OwnerID == UUID.Zero)
2982 {
2983 m_log.ErrorFormat("[SCENE]: Owner ID for non-attachment {0} was zero", sceneObject.UUID);
2984 return false;
2985 }
2929 AddRestoredSceneObject(sceneObject, true, false); 2986 AddRestoredSceneObject(sceneObject, true, false);
2930 } 2987 }
2931 2988
2932 return true; 2989 return true;
2933 } 2990 }
2934 2991
2992 private int GetStateSource(SceneObjectGroup sog)
2993 {
2994 if(!sog.IsAttachmentCheckFull())
2995 return 2; // StateSource.PrimCrossing
2996
2997 ScenePresence sp = GetScenePresence(sog.OwnerID);
2998 if (sp != null)
2999 return sp.GetStateSource();
3000
3001 return 2; // StateSource.PrimCrossing
3002 }
3003
3004 public int GetUserFlags(UUID user)
3005 {
3006 //Unfortunately the SP approach means that the value is cached until region is restarted
3007 /*
3008 ScenePresence sp;
3009 if (TryGetScenePresence(user, out sp))
3010 {
3011 return sp.UserFlags;
3012 }
3013 else
3014 {
3015 */
3016 UserAccount uac = UserAccountService.GetUserAccount(RegionInfo.ScopeID, user);
3017 if (uac == null)
3018 return 0;
3019 return uac.UserFlags;
3020 //}
3021 }
3022
2935 #endregion 3023 #endregion
2936 3024
2937 #region Add/Remove Avatar Methods 3025 #region Add/Remove Avatar Methods
@@ -2968,47 +3056,34 @@ namespace OpenSim.Region.Framework.Scenes
2968 = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 3056 = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0
2969 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; 3057 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2970 3058
2971 // CheckHeartbeat(); 3059 CheckHeartbeat();
2972 3060
2973 sp = GetScenePresence(client.AgentId); 3061 sp = GetScenePresence(client.AgentId);
2974 3062
2975 // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this
2976 // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause
2977 // other problems, and possibly the code calling AddNewAgent() should ensure that no client is already
2978 // connected.
2979 if (sp == null) 3063 if (sp == null)
2980 { 3064 {
2981 m_log.DebugFormat( 3065 m_log.DebugFormat(
2982 "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", 3066 "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}, tpflags: {4}",
2983 client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); 3067 client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos,
2984 3068 ((TPFlags)aCircuit.teleportFlags).ToString());
2985 sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type);
2986
2987 // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the
2988 // client is for a root or child agent.
2989 // We must also set this before adding the client to the client manager so that an exception later on
2990 // does not leave a client manager entry without the scene agent set, which will cause other code
2991 // to fail since any entry in the client manager should have a ScenePresence
2992 //
2993 // XXX: This may be better set for a new client before that client is added to the client manager.
2994 // But need to know what happens in the case where a ScenePresence is already present (and if this
2995 // actually occurs).
2996 client.SceneAgent = sp;
2997 3069
2998 m_clientManager.Add(client); 3070 m_clientManager.Add(client);
2999 SubscribeToClientEvents(client); 3071 SubscribeToClientEvents(client);
3000 m_eventManager.TriggerOnNewPresence(sp); 3072
3073 sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type);
3001 3074
3002 sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags; 3075 sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags;
3076
3077 m_eventManager.TriggerOnNewPresence(sp);
3003 } 3078 }
3004 else 3079 else
3005 { 3080 {
3006 // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the 3081 // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the
3007 // client is for a root or child agent. 3082 // client is for a root or child agent.
3008 // XXX: This may be better set for a new client before that client is added to the client manager. 3083 // XXX: This may be better set for a new client before that client is added to the client manager.
3009 // But need to know what happens in the case where a ScenePresence is already present (and if this 3084 // But need to know what happens in the case where a ScenePresence is already present (and if this
3010 // actually occurs). 3085 // actually occurs).
3011 client.SceneAgent = sp; 3086
3012 3087
3013 m_log.WarnFormat( 3088 m_log.WarnFormat(
3014 "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", 3089 "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence",
@@ -3016,8 +3091,9 @@ namespace OpenSim.Region.Framework.Scenes
3016 3091
3017 reallyNew = false; 3092 reallyNew = false;
3018 } 3093 }
3094 client.SceneAgent = sp;
3019 3095
3020 // This is currently also being done earlier in NewUserConnection for real users to see if this 3096 // This is currently also being done earlier in NewUserConnection for real users to see if this
3021 // resolves problems where HG agents are occasionally seen by others as "Unknown user" in chat and other 3097 // resolves problems where HG agents are occasionally seen by others as "Unknown user" in chat and other
3022 // places. However, we still need to do it here for NPCs. 3098 // places. However, we still need to do it here for NPCs.
3023 CacheUserName(sp, aCircuit); 3099 CacheUserName(sp, aCircuit);
@@ -3063,7 +3139,7 @@ namespace OpenSim.Region.Framework.Scenes
3063 3139
3064 if (sp != null && sp.PresenceType == PresenceType.Npc) 3140 if (sp != null && sp.PresenceType == PresenceType.Npc)
3065 { 3141 {
3066 UserManagementModule.AddUser(aCircuit.AgentID, first, last); 3142 UserManagementModule.AddUser(aCircuit.AgentID, first, last, true);
3067 } 3143 }
3068 else 3144 else
3069 { 3145 {
@@ -3134,19 +3210,15 @@ namespace OpenSim.Region.Framework.Scenes
3134 // and the scene presence and the client, if they exist 3210 // and the scene presence and the client, if they exist
3135 try 3211 try
3136 { 3212 {
3137 // We need to wait for the client to make UDP contact first.
3138 // It's the UDP contact that creates the scene presence
3139 ScenePresence sp = WaitGetScenePresence(agentID); 3213 ScenePresence sp = WaitGetScenePresence(agentID);
3214
3140 if (sp != null) 3215 if (sp != null)
3141 { 3216 {
3142 PresenceService.LogoutAgent(sp.ControllingClient.SessionId); 3217 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
3143 3218
3144 CloseAgent(sp.UUID, false); 3219 CloseAgent(sp.UUID, false);
3145 } 3220 }
3146 else 3221
3147 {
3148 m_log.WarnFormat("[SCENE]: Could not find scene presence for {0}", agentID);
3149 }
3150 // BANG! SLASH! 3222 // BANG! SLASH!
3151 m_authenticateHandler.RemoveCircuit(agentID); 3223 m_authenticateHandler.RemoveCircuit(agentID);
3152 3224
@@ -3183,7 +3255,7 @@ namespace OpenSim.Region.Framework.Scenes
3183 3255
3184 public virtual void SubscribeToClientTerrainEvents(IClientAPI client) 3256 public virtual void SubscribeToClientTerrainEvents(IClientAPI client)
3185 { 3257 {
3186 client.OnRegionHandShakeReply += SendLayerData; 3258// client.OnRegionHandShakeReply += SendLayerData;
3187 } 3259 }
3188 3260
3189 public virtual void SubscribeToClientPrimEvents(IClientAPI client) 3261 public virtual void SubscribeToClientPrimEvents(IClientAPI client)
@@ -3191,6 +3263,8 @@ namespace OpenSim.Region.Framework.Scenes
3191 client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimGroupPosition; 3263 client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimGroupPosition;
3192 client.OnUpdatePrimSinglePosition += m_sceneGraph.UpdatePrimSinglePosition; 3264 client.OnUpdatePrimSinglePosition += m_sceneGraph.UpdatePrimSinglePosition;
3193 3265
3266 client.onClientChangeObject += m_sceneGraph.ClientChangeObject;
3267
3194 client.OnUpdatePrimGroupRotation += m_sceneGraph.UpdatePrimGroupRotation; 3268 client.OnUpdatePrimGroupRotation += m_sceneGraph.UpdatePrimGroupRotation;
3195 client.OnUpdatePrimGroupMouseRotation += m_sceneGraph.UpdatePrimGroupRotation; 3269 client.OnUpdatePrimGroupMouseRotation += m_sceneGraph.UpdatePrimGroupRotation;
3196 client.OnUpdatePrimSingleRotation += m_sceneGraph.UpdatePrimSingleRotation; 3270 client.OnUpdatePrimSingleRotation += m_sceneGraph.UpdatePrimSingleRotation;
@@ -3204,9 +3278,6 @@ namespace OpenSim.Region.Framework.Scenes
3204 client.OnObjectRequest += RequestPrim; 3278 client.OnObjectRequest += RequestPrim;
3205 client.OnObjectSelect += SelectPrim; 3279 client.OnObjectSelect += SelectPrim;
3206 client.OnObjectDeselect += DeselectPrim; 3280 client.OnObjectDeselect += DeselectPrim;
3207 client.OnGrabUpdate += m_sceneGraph.MoveObject;
3208 client.OnSpinStart += m_sceneGraph.SpinStart;
3209 client.OnSpinUpdate += m_sceneGraph.SpinObject;
3210 client.OnDeRezObject += DeRezObjects; 3281 client.OnDeRezObject += DeRezObjects;
3211 3282
3212 client.OnObjectName += m_sceneGraph.PrimName; 3283 client.OnObjectName += m_sceneGraph.PrimName;
@@ -3222,6 +3293,9 @@ namespace OpenSim.Region.Framework.Scenes
3222 client.OnGrabObject += ProcessObjectGrab; 3293 client.OnGrabObject += ProcessObjectGrab;
3223 client.OnGrabUpdate += ProcessObjectGrabUpdate; 3294 client.OnGrabUpdate += ProcessObjectGrabUpdate;
3224 client.OnDeGrabObject += ProcessObjectDeGrab; 3295 client.OnDeGrabObject += ProcessObjectDeGrab;
3296 client.OnSpinStart += ProcessSpinStart;
3297 client.OnSpinUpdate += ProcessSpinObject;
3298 client.OnSpinStop += ProcessSpinObjectStop;
3225 client.OnUndo += m_sceneGraph.HandleUndo; 3299 client.OnUndo += m_sceneGraph.HandleUndo;
3226 client.OnRedo += m_sceneGraph.HandleRedo; 3300 client.OnRedo += m_sceneGraph.HandleRedo;
3227 client.OnObjectDescription += m_sceneGraph.PrimDescription; 3301 client.OnObjectDescription += m_sceneGraph.PrimDescription;
@@ -3247,6 +3321,7 @@ namespace OpenSim.Region.Framework.Scenes
3247 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory; 3321 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory;
3248 client.OnUpdateInventoryItem += UpdateInventoryItemAsset; 3322 client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
3249 client.OnCopyInventoryItem += CopyInventoryItem; 3323 client.OnCopyInventoryItem += CopyInventoryItem;
3324 client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy;
3250 client.OnMoveInventoryItem += MoveInventoryItem; 3325 client.OnMoveInventoryItem += MoveInventoryItem;
3251 client.OnRemoveInventoryItem += RemoveInventoryItem; 3326 client.OnRemoveInventoryItem += RemoveInventoryItem;
3252 client.OnRemoveInventoryFolder += RemoveInventoryFolder; 3327 client.OnRemoveInventoryFolder += RemoveInventoryFolder;
@@ -3308,7 +3383,7 @@ namespace OpenSim.Region.Framework.Scenes
3308 3383
3309 public virtual void UnSubscribeToClientTerrainEvents(IClientAPI client) 3384 public virtual void UnSubscribeToClientTerrainEvents(IClientAPI client)
3310 { 3385 {
3311 client.OnRegionHandShakeReply -= SendLayerData; 3386// client.OnRegionHandShakeReply -= SendLayerData;
3312 } 3387 }
3313 3388
3314 public virtual void UnSubscribeToClientPrimEvents(IClientAPI client) 3389 public virtual void UnSubscribeToClientPrimEvents(IClientAPI client)
@@ -3316,6 +3391,8 @@ namespace OpenSim.Region.Framework.Scenes
3316 client.OnUpdatePrimGroupPosition -= m_sceneGraph.UpdatePrimGroupPosition; 3391 client.OnUpdatePrimGroupPosition -= m_sceneGraph.UpdatePrimGroupPosition;
3317 client.OnUpdatePrimSinglePosition -= m_sceneGraph.UpdatePrimSinglePosition; 3392 client.OnUpdatePrimSinglePosition -= m_sceneGraph.UpdatePrimSinglePosition;
3318 3393
3394 client.onClientChangeObject -= m_sceneGraph.ClientChangeObject;
3395
3319 client.OnUpdatePrimGroupRotation -= m_sceneGraph.UpdatePrimGroupRotation; 3396 client.OnUpdatePrimGroupRotation -= m_sceneGraph.UpdatePrimGroupRotation;
3320 client.OnUpdatePrimGroupMouseRotation -= m_sceneGraph.UpdatePrimGroupRotation; 3397 client.OnUpdatePrimGroupMouseRotation -= m_sceneGraph.UpdatePrimGroupRotation;
3321 client.OnUpdatePrimSingleRotation -= m_sceneGraph.UpdatePrimSingleRotation; 3398 client.OnUpdatePrimSingleRotation -= m_sceneGraph.UpdatePrimSingleRotation;
@@ -3329,9 +3406,6 @@ namespace OpenSim.Region.Framework.Scenes
3329 client.OnObjectRequest -= RequestPrim; 3406 client.OnObjectRequest -= RequestPrim;
3330 client.OnObjectSelect -= SelectPrim; 3407 client.OnObjectSelect -= SelectPrim;
3331 client.OnObjectDeselect -= DeselectPrim; 3408 client.OnObjectDeselect -= DeselectPrim;
3332 client.OnGrabUpdate -= m_sceneGraph.MoveObject;
3333 client.OnSpinStart -= m_sceneGraph.SpinStart;
3334 client.OnSpinUpdate -= m_sceneGraph.SpinObject;
3335 client.OnDeRezObject -= DeRezObjects; 3409 client.OnDeRezObject -= DeRezObjects;
3336 client.OnObjectName -= m_sceneGraph.PrimName; 3410 client.OnObjectName -= m_sceneGraph.PrimName;
3337 client.OnObjectClickAction -= m_sceneGraph.PrimClickAction; 3411 client.OnObjectClickAction -= m_sceneGraph.PrimClickAction;
@@ -3344,7 +3418,11 @@ namespace OpenSim.Region.Framework.Scenes
3344 client.OnRequestObjectPropertiesFamily -= m_sceneGraph.RequestObjectPropertiesFamily; 3418 client.OnRequestObjectPropertiesFamily -= m_sceneGraph.RequestObjectPropertiesFamily;
3345 client.OnObjectPermissions -= HandleObjectPermissionsUpdate; 3419 client.OnObjectPermissions -= HandleObjectPermissionsUpdate;
3346 client.OnGrabObject -= ProcessObjectGrab; 3420 client.OnGrabObject -= ProcessObjectGrab;
3421 client.OnGrabUpdate -= ProcessObjectGrabUpdate;
3347 client.OnDeGrabObject -= ProcessObjectDeGrab; 3422 client.OnDeGrabObject -= ProcessObjectDeGrab;
3423 client.OnSpinStart -= ProcessSpinStart;
3424 client.OnSpinUpdate -= ProcessSpinObject;
3425 client.OnSpinStop -= ProcessSpinObjectStop;
3348 client.OnUndo -= m_sceneGraph.HandleUndo; 3426 client.OnUndo -= m_sceneGraph.HandleUndo;
3349 client.OnRedo -= m_sceneGraph.HandleRedo; 3427 client.OnRedo -= m_sceneGraph.HandleRedo;
3350 client.OnObjectDescription -= m_sceneGraph.PrimDescription; 3428 client.OnObjectDescription -= m_sceneGraph.PrimDescription;
@@ -3440,13 +3518,15 @@ namespace OpenSim.Region.Framework.Scenes
3440 /// <param name="GroupID">Group of new object</param> 3518 /// <param name="GroupID">Group of new object</param>
3441 public void DuplicateObject(uint originalPrim, Vector3 offset, uint flags, UUID AgentID, UUID GroupID) 3519 public void DuplicateObject(uint originalPrim, Vector3 offset, uint flags, UUID AgentID, UUID GroupID)
3442 { 3520 {
3443 SceneObjectGroup copy = SceneGraph.DuplicateObject(originalPrim, offset, flags, AgentID, GroupID, Quaternion.Identity); 3521 bool createSelected = (flags & (uint)PrimFlags.CreateSelected) != 0;
3522 SceneObjectGroup copy = SceneGraph.DuplicateObject(originalPrim, offset, AgentID,
3523 GroupID, Quaternion.Identity, createSelected);
3444 if (copy != null) 3524 if (copy != null)
3445 EventManager.TriggerObjectAddedToScene(copy); 3525 EventManager.TriggerObjectAddedToScene(copy);
3446 } 3526 }
3447 3527
3448 /// <summary> 3528 /// <summary>
3449 /// Duplicates object specified by localID at position raycasted against RayTargetObject using 3529 /// Duplicates object specified by localID at position raycasted against RayTargetObject using
3450 /// RayEnd and RayStart to determine what the angle of the ray is 3530 /// RayEnd and RayStart to determine what the angle of the ray is
3451 /// </summary> 3531 /// </summary>
3452 /// <param name="localID">ID of object to duplicate</param> 3532 /// <param name="localID">ID of object to duplicate</param>
@@ -3470,11 +3550,11 @@ namespace OpenSim.Region.Framework.Scenes
3470 SceneObjectPart target = GetSceneObjectPart(localID); 3550 SceneObjectPart target = GetSceneObjectPart(localID);
3471 SceneObjectPart target2 = GetSceneObjectPart(RayTargetObj); 3551 SceneObjectPart target2 = GetSceneObjectPart(RayTargetObj);
3472 3552
3553 bool createSelected = (dupeFlags & (uint)PrimFlags.CreateSelected) != 0;
3554
3473 if (target != null && target2 != null) 3555 if (target != null && target2 != null)
3474 { 3556 {
3475 Vector3 direction = Vector3.Normalize(RayEnd - RayStart); 3557 Vector3 direction = Vector3.Normalize(RayEnd - RayStart);
3476 Vector3 AXOrigin = RayStart;
3477 Vector3 AXdirection = direction;
3478 3558
3479 pos = target2.AbsolutePosition; 3559 pos = target2.AbsolutePosition;
3480 //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()); 3560 //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());
@@ -3482,7 +3562,7 @@ namespace OpenSim.Region.Framework.Scenes
3482 // TODO: Raytrace better here 3562 // TODO: Raytrace better here
3483 3563
3484 //EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection)); 3564 //EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection));
3485 Ray NewRay = new Ray(AXOrigin, AXdirection); 3565 Ray NewRay = new Ray(RayStart,direction);
3486 3566
3487 // Ray Trace against target here 3567 // Ray Trace against target here
3488 EntityIntersection ei = target2.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, CopyCenters); 3568 EntityIntersection ei = target2.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, CopyCenters);
@@ -3513,13 +3593,13 @@ namespace OpenSim.Region.Framework.Scenes
3513 Quaternion worldRot = target2.GetWorldRotation(); 3593 Quaternion worldRot = target2.GetWorldRotation();
3514 3594
3515 // SceneObjectGroup obj = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, worldRot); 3595 // SceneObjectGroup obj = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, worldRot);
3516 copy = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, worldRot); 3596 copy = m_sceneGraph.DuplicateObject(localID, pos, AgentID, GroupID, worldRot, createSelected);
3517 //obj.Rotation = worldRot; 3597 //obj.Rotation = worldRot;
3518 //obj.UpdateGroupRotationR(worldRot); 3598 //obj.UpdateGroupRotationR(worldRot);
3519 } 3599 }
3520 else 3600 else
3521 { 3601 {
3522 copy = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, Quaternion.Identity); 3602 copy = m_sceneGraph.DuplicateObject(localID, pos, AgentID, GroupID, Quaternion.Identity, createSelected);
3523 } 3603 }
3524 3604
3525 if (copy != null) 3605 if (copy != null)
@@ -3553,7 +3633,7 @@ namespace OpenSim.Region.Framework.Scenes
3553 } 3633 }
3554 3634
3555 /// <summary> 3635 /// <summary>
3556 /// Remove the given client from the scene. 3636 /// Remove the given client from the scene.
3557 /// </summary> 3637 /// </summary>
3558 /// <remarks> 3638 /// <remarks>
3559 /// Only clientstack code should call this directly. All other code should call IncomingCloseAgent() instead 3639 /// Only clientstack code should call this directly. All other code should call IncomingCloseAgent() instead
@@ -3564,11 +3644,15 @@ namespace OpenSim.Region.Framework.Scenes
3564 /// <param name='closeChildAgents'> 3644 /// <param name='closeChildAgents'>
3565 /// Close the neighbour child agents associated with this client. 3645 /// Close the neighbour child agents associated with this client.
3566 /// </param> 3646 /// </param>
3647 ///
3648
3649 private object m_removeClientPrivLock = new Object();
3650
3567 public void RemoveClient(UUID agentID, bool closeChildAgents) 3651 public void RemoveClient(UUID agentID, bool closeChildAgents)
3568 { 3652 {
3569 AgentCircuitData acd = m_authenticateHandler.GetAgentCircuitData(agentID); 3653 AgentCircuitData acd = m_authenticateHandler.GetAgentCircuitData(agentID);
3570 3654
3571 // Shouldn't be necessary since RemoveClient() is currently only called by IClientAPI.Close() which 3655 // Shouldn't be necessary since RemoveClient() is currently only called by IClientAPI.Close() which
3572 // in turn is only called by Scene.IncomingCloseAgent() which checks whether the presence exists or not 3656 // in turn is only called by Scene.IncomingCloseAgent() which checks whether the presence exists or not
3573 // However, will keep for now just in case. 3657 // However, will keep for now just in case.
3574 if (acd == null) 3658 if (acd == null)
@@ -3580,13 +3664,13 @@ namespace OpenSim.Region.Framework.Scenes
3580 } 3664 }
3581 3665
3582 // TODO: Can we now remove this lock? 3666 // TODO: Can we now remove this lock?
3583 lock (acd) 3667 lock (m_removeClientPrivLock)
3584 { 3668 {
3585 bool isChildAgent = false; 3669 bool isChildAgent = false;
3586 3670
3587 ScenePresence avatar = GetScenePresence(agentID); 3671 ScenePresence avatar = GetScenePresence(agentID);
3588 3672
3589 // Shouldn't be necessary since RemoveClient() is currently only called by IClientAPI.Close() which 3673 // Shouldn't be necessary since RemoveClient() is currently only called by IClientAPI.Close() which
3590 // in turn is only called by Scene.IncomingCloseAgent() which checks whether the presence exists or not 3674 // in turn is only called by Scene.IncomingCloseAgent() which checks whether the presence exists or not
3591 // However, will keep for now just in case. 3675 // However, will keep for now just in case.
3592 if (avatar == null) 3676 if (avatar == null)
@@ -3625,7 +3709,7 @@ namespace OpenSim.Region.Framework.Scenes
3625 // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop 3709 // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop
3626 // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI 3710 // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI
3627 if (closeChildAgents && CapsModule != null) 3711 if (closeChildAgents && CapsModule != null)
3628 CapsModule.RemoveCaps(agentID); 3712 CapsModule.RemoveCaps(agentID, avatar.ControllingClient.CircuitCode);
3629 3713
3630 if (closeChildAgents && !isChildAgent) 3714 if (closeChildAgents && !isChildAgent)
3631 { 3715 {
@@ -3637,13 +3721,17 @@ namespace OpenSim.Region.Framework.Scenes
3637 } 3721 }
3638 3722
3639 m_eventManager.TriggerClientClosed(agentID, this); 3723 m_eventManager.TriggerClientClosed(agentID, this);
3724// m_log.Debug("[Scene]TriggerClientClosed done");
3640 m_eventManager.TriggerOnRemovePresence(agentID); 3725 m_eventManager.TriggerOnRemovePresence(agentID);
3726// m_log.Debug("[Scene]TriggerOnRemovePresence done");
3641 3727
3642 if (!isChildAgent) 3728 if (!isChildAgent)
3643 { 3729 {
3644 if (AttachmentsModule != null) 3730 if (AttachmentsModule != null)
3645 { 3731 {
3732// m_log.Debug("[Scene]DeRezAttachments");
3646 AttachmentsModule.DeRezAttachments(avatar); 3733 AttachmentsModule.DeRezAttachments(avatar);
3734// m_log.Debug("[Scene]DeRezAttachments done");
3647 } 3735 }
3648 3736
3649 ForEachClient( 3737 ForEachClient(
@@ -3657,7 +3745,11 @@ namespace OpenSim.Region.Framework.Scenes
3657 3745
3658 // It's possible for child agents to have transactions if changes are being made cross-border. 3746 // It's possible for child agents to have transactions if changes are being made cross-border.
3659 if (AgentTransactionsModule != null) 3747 if (AgentTransactionsModule != null)
3748 {
3749// m_log.Debug("[Scene]RemoveAgentAssetTransactions");
3660 AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); 3750 AgentTransactionsModule.RemoveAgentAssetTransactions(agentID);
3751 }
3752 m_log.Debug("[Scene] The avatar has left the building");
3661 } 3753 }
3662 catch (Exception e) 3754 catch (Exception e)
3663 { 3755 {
@@ -3691,7 +3783,7 @@ namespace OpenSim.Region.Framework.Scenes
3691 3783
3692 /// <summary> 3784 /// <summary>
3693 /// Removes region from an avatar's known region list. This coincides with child agents. For each child agent, there will be a known region entry. 3785 /// Removes region from an avatar's known region list. This coincides with child agents. For each child agent, there will be a known region entry.
3694 /// 3786 ///
3695 /// </summary> 3787 /// </summary>
3696 /// <param name="avatarID"></param> 3788 /// <param name="avatarID"></param>
3697 /// <param name="regionslst"></param> 3789 /// <param name="regionslst"></param>
@@ -3721,15 +3813,9 @@ namespace OpenSim.Region.Framework.Scenes
3721 foreach (uint localID in localIDs) 3813 foreach (uint localID in localIDs)
3722 { 3814 {
3723 SceneObjectPart part = GetSceneObjectPart(localID); 3815 SceneObjectPart part = GetSceneObjectPart(localID);
3724 if (part != null) // It is a prim 3816 if (part != null && part.ParentGroup != null &&
3725 { 3817 part.ParentGroup.RootPart == part)
3726 if (part.ParentGroup != null && !part.ParentGroup.IsDeleted) // Valid 3818 deleteIDs.Add(localID);
3727 {
3728 if (part.ParentGroup.RootPart != part) // Child part
3729 continue;
3730 }
3731 }
3732 deleteIDs.Add(localID);
3733 } 3819 }
3734 3820
3735 ForEachClient(c => c.SendKillObject(deleteIDs)); 3821 ForEachClient(c => c.SendKillObject(deleteIDs));
@@ -3746,7 +3832,7 @@ namespace OpenSim.Region.Framework.Scenes
3746 /// <param name="teleportFlags"></param> 3832 /// <param name="teleportFlags"></param>
3747 /// <param name="source">Source region (may be null)</param> 3833 /// <param name="source">Source region (may be null)</param>
3748 /// <param name="reason">Outputs the reason for the false response on this string</param> 3834 /// <param name="reason">Outputs the reason for the false response on this string</param>
3749 /// <returns>True if the region accepts this agent. False if it does not. False will 3835 /// <returns>True if the region accepts this agent. False if it does not. False will
3750 /// also return a reason.</returns> 3836 /// also return a reason.</returns>
3751 public bool NewUserConnection(AgentCircuitData agent, uint teleportFlags, GridRegion source, out string reason) 3837 public bool NewUserConnection(AgentCircuitData agent, uint teleportFlags, GridRegion source, out string reason)
3752 { 3838 {
@@ -3774,14 +3860,17 @@ namespace OpenSim.Region.Framework.Scenes
3774 /// <param name="reason">Outputs the reason for the false response on this string</param> 3860 /// <param name="reason">Outputs the reason for the false response on this string</param>
3775 /// <param name="requirePresenceLookup">True for normal presence. False for NPC 3861 /// <param name="requirePresenceLookup">True for normal presence. False for NPC
3776 /// or other applications where a full grid/Hypergrid presence may not be required.</param> 3862 /// or other applications where a full grid/Hypergrid presence may not be required.</param>
3777 /// <returns>True if the region accepts this agent. False if it does not. False will 3863 /// <returns>True if the region accepts this agent. False if it does not. False will
3778 /// also return a reason.</returns> 3864 /// also return a reason.</returns>
3865 ///
3866 private object m_newUserConnLock = new object();
3867
3779 public bool NewUserConnection(AgentCircuitData acd, uint teleportFlags, GridRegion source, out string reason, bool requirePresenceLookup) 3868 public bool NewUserConnection(AgentCircuitData acd, uint teleportFlags, GridRegion source, out string reason, bool requirePresenceLookup)
3780 { 3869 {
3781 bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 || 3870 bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 ||
3782 (teleportFlags & (uint)TPFlags.ViaHGLogin) != 0); 3871 (teleportFlags & (uint)TPFlags.ViaHGLogin) != 0);
3783 bool viahome = ((teleportFlags & (uint)TPFlags.ViaHome) != 0); 3872 bool viahome = ((teleportFlags & (uint)TPFlags.ViaHome) != 0);
3784 bool godlike = ((teleportFlags & (uint)TPFlags.Godlike) != 0); 3873// bool godlike = ((teleportFlags & (uint)TPFlags.Godlike) != 0);
3785 3874
3786 reason = String.Empty; 3875 reason = String.Empty;
3787 3876
@@ -3809,9 +3898,11 @@ namespace OpenSim.Region.Framework.Scenes
3809 (source == null) ? "" : string.Format("From region {0} ({1}){2}", source.RegionName, source.RegionID, (source.RawServerURI == null) ? "" : " @ " + source.ServerURI) 3898 (source == null) ? "" : string.Format("From region {0} ({1}){2}", source.RegionName, source.RegionID, (source.RawServerURI == null) ? "" : " @ " + source.ServerURI)
3810 ); 3899 );
3811 3900
3901// m_log.DebugFormat("NewUserConnection stack {0}", Environment.StackTrace);
3902
3812 if (!LoginsEnabled) 3903 if (!LoginsEnabled)
3813 { 3904 {
3814 reason = "Logins Disabled"; 3905 reason = "Logins to this region are disabled";
3815 return false; 3906 return false;
3816 } 3907 }
3817 3908
@@ -3858,14 +3949,13 @@ namespace OpenSim.Region.Framework.Scenes
3858 return false; 3949 return false;
3859 } 3950 }
3860 3951
3861 ILandObject land;
3862 ScenePresence sp; 3952 ScenePresence sp;
3863 3953
3864 lock (m_removeClientLock) 3954 lock (m_removeClientLock)
3865 { 3955 {
3866 sp = GetScenePresence(acd.AgentID); 3956 sp = GetScenePresence(acd.AgentID);
3867 3957
3868 // We need to ensure that we are not already removing the scene presence before we ask it not to be 3958 // We need to ensure that we are not already removing the scene presence before we ask it not to be
3869 // closed. 3959 // closed.
3870 if (sp != null && sp.IsChildAgent 3960 if (sp != null && sp.IsChildAgent
3871 && (sp.LifecycleState == ScenePresenceState.Running 3961 && (sp.LifecycleState == ScenePresenceState.Running
@@ -3879,16 +3969,16 @@ namespace OpenSim.Region.Framework.Scenes
3879 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. When C 3969 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. When C
3880 // renews the lease on the child agent at B, we must make sure that the close from A does not succeed. 3970 // renews the lease on the child agent at B, we must make sure that the close from A does not succeed.
3881 // 3971 //
3882 // XXX: In the end, this should not be necessary if child agents are closed without delay on 3972 // XXX: In the end, this should not be necessary if child agents are closed without delay on
3883 // teleport, since realistically, the close request should always be processed before any other 3973 // teleport, since realistically, the close request should always be processed before any other
3884 // region tried to re-establish a child agent. This is much simpler since the logic below is 3974 // region tried to re-establish a child agent. This is much simpler since the logic below is
3885 // vulnerable to an issue when a viewer quits a region without sending a proper logout but then 3975 // vulnerable to an issue when a viewer quits a region without sending a proper logout but then
3886 // re-establishes the connection on a relogin. This could wrongly set the DoNotCloseAfterTeleport 3976 // re-establishes the connection on a relogin. This could wrongly set the DoNotCloseAfterTeleport
3887 // flag when no teleport had taken place (and hence no close was going to come). 3977 // flag when no teleport had taken place (and hence no close was going to come).
3888// if (!acd.ChildrenCapSeeds.ContainsKey(RegionInfo.RegionHandle)) 3978// if (!acd.ChildrenCapSeeds.ContainsKey(RegionInfo.RegionHandle))
3889// { 3979// {
3890// m_log.DebugFormat( 3980// m_log.DebugFormat(
3891// "[SCENE]: Setting DoNotCloseAfterTeleport for child scene presence {0} in {1} because source will attempt close.", 3981// "[SCENE]: Setting DoNotCloseAfterTeleport for child scene presence {0} in {1} because source will attempt close.",
3892// sp.Name, Name); 3982// sp.Name, Name);
3893// 3983//
3894// sp.DoNotCloseAfterTeleport = true; 3984// sp.DoNotCloseAfterTeleport = true;
@@ -3902,7 +3992,7 @@ namespace OpenSim.Region.Framework.Scenes
3902 sp.DoNotCloseAfterTeleport = true; 3992 sp.DoNotCloseAfterTeleport = true;
3903 3993
3904 m_log.DebugFormat( 3994 m_log.DebugFormat(
3905 "[SCENE]: Set DoNotCloseAfterTeleport for child scene presence {0} in {1} because this region will attempt end-of-teleport close from a previous close.", 3995 "[SCENE]: Set DoNotCloseAfterTeleport for child scene presence {0} in {1} because this region will attempt end-of-teleport close from a previous close.",
3906 sp.Name, Name); 3996 sp.Name, Name);
3907 } 3997 }
3908 } 3998 }
@@ -3922,7 +4012,7 @@ namespace OpenSim.Region.Framework.Scenes
3922 if (sp.LifecycleState == ScenePresenceState.Removing) 4012 if (sp.LifecycleState == ScenePresenceState.Removing)
3923 { 4013 {
3924 m_log.WarnFormat( 4014 m_log.WarnFormat(
3925 "[SCENE]: Agent {0} in {1} was still being removed after {2}s. Aborting NewUserConnection.", 4015 "[SCENE]: Agent {0} in {1} was still being removed after {2}s. Aborting NewUserConnection.",
3926 sp.Name, Name, polls * pollInterval / 1000); 4016 sp.Name, Name, polls * pollInterval / 1000);
3927 4017
3928 return false; 4018 return false;
@@ -3936,14 +4026,14 @@ namespace OpenSim.Region.Framework.Scenes
3936 } 4026 }
3937 4027
3938 // TODO: can we remove this lock? 4028 // TODO: can we remove this lock?
3939 lock (acd) 4029 lock (m_newUserConnLock)
3940 { 4030 {
3941 if (sp != null && !sp.IsChildAgent) 4031 if (sp != null && !sp.IsChildAgent)
3942 { 4032 {
3943 // We have a root agent. Is it in transit? 4033 // We have a root agent. Is it in transit?
3944 if (!EntityTransferModule.IsInTransit(sp.UUID)) 4034 if (!EntityTransferModule.IsInTransit(sp.UUID))
3945 { 4035 {
3946 // We have a zombie from a crashed session. 4036 // We have a zombie from a crashed session.
3947 // Or the same user is trying to be root twice here, won't work. 4037 // Or the same user is trying to be root twice here, won't work.
3948 // Kill it. 4038 // Kill it.
3949 m_log.WarnFormat( 4039 m_log.WarnFormat(
@@ -3963,20 +4053,21 @@ namespace OpenSim.Region.Framework.Scenes
3963 // We need the circuit data here for some of the subsequent checks. (groups, for example) 4053 // We need the circuit data here for some of the subsequent checks. (groups, for example)
3964 // If the checks fail, we remove the circuit. 4054 // If the checks fail, we remove the circuit.
3965 acd.teleportFlags = teleportFlags; 4055 acd.teleportFlags = teleportFlags;
3966 m_authenticateHandler.AddNewCircuit(acd.circuitcode, acd);
3967
3968 land = LandChannel.GetLandObject(acd.startpos.X, acd.startpos.Y);
3969 4056
3970 // On login test land permisions
3971 if (vialogin) 4057 if (vialogin)
3972 { 4058 {
3973 if (land != null && !TestLandRestrictions(acd.AgentID, out reason, ref acd.startpos.X, ref acd.startpos.Y)) 4059 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3974 { 4060 if (cache != null)
3975 m_authenticateHandler.RemoveCircuit(acd.circuitcode); 4061// cache.Remove(acd.firstname + " " + acd.lastname);
3976 return false; 4062 cache.Remove(acd.AgentID);
3977 } 4063
4064 // Remove any preexisting circuit - we don't want duplicates
4065 // This is a stab at preventing avatar "ghosting"
4066 m_authenticateHandler.RemoveCircuit(acd.AgentID);
3978 } 4067 }
3979 4068
4069 m_authenticateHandler.AddNewCircuit(acd.circuitcode, acd);
4070
3980 if (sp == null) // We don't have an [child] agent here already 4071 if (sp == null) // We don't have an [child] agent here already
3981 { 4072 {
3982 if (requirePresenceLookup) 4073 if (requirePresenceLookup)
@@ -4024,7 +4115,7 @@ namespace OpenSim.Region.Framework.Scenes
4024 if (CapsModule != null) 4115 if (CapsModule != null)
4025 { 4116 {
4026 CapsModule.SetAgentCapsSeeds(acd); 4117 CapsModule.SetAgentCapsSeeds(acd);
4027 CapsModule.CreateCaps(acd.AgentID); 4118 CapsModule.CreateCaps(acd.AgentID, acd.circuitcode);
4028 } 4119 }
4029 } 4120 }
4030 else 4121 else
@@ -4039,13 +4130,13 @@ namespace OpenSim.Region.Framework.Scenes
4039 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", 4130 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}",
4040 acd.AgentID, RegionInfo.RegionName); 4131 acd.AgentID, RegionInfo.RegionName);
4041 4132
4042 sp.AdjustKnownSeeds();
4043
4044 if (CapsModule != null) 4133 if (CapsModule != null)
4045 { 4134 {
4046 CapsModule.SetAgentCapsSeeds(acd); 4135 CapsModule.SetAgentCapsSeeds(acd);
4047 CapsModule.CreateCaps(acd.AgentID); 4136 CapsModule.CreateCaps(acd.AgentID, acd.circuitcode);
4048 } 4137 }
4138
4139 sp.AdjustKnownSeeds();
4049 } 4140 }
4050 } 4141 }
4051 4142
@@ -4055,88 +4146,48 @@ namespace OpenSim.Region.Framework.Scenes
4055 CacheUserName(null, acd); 4146 CacheUserName(null, acd);
4056 } 4147 }
4057 4148
4058 if (vialogin) 4149 if (CapsModule != null)
4059 { 4150 {
4060// CleanDroppedAttachments(); 4151 CapsModule.ActivateCaps(acd.circuitcode);
4061 4152 }
4062 // Make sure avatar position is in the region (why it wouldn't be is a mystery but do sanity checking)
4063 if (acd.startpos.X < 0) acd.startpos.X = 1f;
4064 if (acd.startpos.X >= RegionInfo.RegionSizeX) acd.startpos.X = RegionInfo.RegionSizeX - 1f;
4065 if (acd.startpos.Y < 0) acd.startpos.Y = 1f;
4066 if (acd.startpos.Y >= RegionInfo.RegionSizeY) acd.startpos.Y = RegionInfo.RegionSizeY - 1f;
4067
4068// m_log.DebugFormat(
4069// "[SCENE]: Found telehub object {0} for new user connection {1} to {2}",
4070// RegionInfo.RegionSettings.TelehubObject, acd.Name, Name);
4071
4072 // Honor Estate teleport routing via Telehubs excluding ViaHome and GodLike TeleportFlags
4073 if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero &&
4074 RegionInfo.EstateSettings.AllowDirectTeleport == false &&
4075 !viahome && !godlike)
4076 {
4077 SceneObjectGroup telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject);
4078
4079 if (telehub != null)
4080 {
4081 // Can have multiple SpawnPoints
4082 List<SpawnPoint> spawnpoints = RegionInfo.RegionSettings.SpawnPoints();
4083 if (spawnpoints.Count > 1)
4084 {
4085 // We have multiple SpawnPoints, Route the agent to a random or sequential one
4086 if (SpawnPointRouting == "random")
4087 acd.startpos = spawnpoints[Util.RandomClass.Next(spawnpoints.Count) - 1].GetLocation(
4088 telehub.AbsolutePosition,
4089 telehub.GroupRotation
4090 );
4091 else
4092 acd.startpos = spawnpoints[SpawnPoint()].GetLocation(
4093 telehub.AbsolutePosition,
4094 telehub.GroupRotation
4095 );
4096 }
4097 else if (spawnpoints.Count == 1)
4098 {
4099 // We have a single SpawnPoint and will route the agent to it
4100 acd.startpos = spawnpoints[0].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation);
4101 }
4102 else
4103 {
4104 m_log.DebugFormat(
4105 "[SCENE]: No spawnpoints defined for telehub {0} for {1} in {2}. Continuing.",
4106 RegionInfo.RegionSettings.TelehubObject, acd.Name, Name);
4107 }
4108 }
4109 else
4110 {
4111 m_log.DebugFormat(
4112 "[SCENE]: No telehub {0} found to direct {1} in {2}. Continuing.",
4113 RegionInfo.RegionSettings.TelehubObject, acd.Name, Name);
4114 }
4115 4153
4116 // Final permissions check; this time we don't allow changing the position 4154// if (vialogin)
4117 if (!IsPositionAllowed(acd.AgentID, acd.startpos, ref reason)) 4155// {
4118 { 4156// CleanDroppedAttachments();
4119 m_authenticateHandler.RemoveCircuit(acd.circuitcode); 4157// }
4120 return false;
4121 }
4122 4158
4123 return true; 4159 if(teleportFlags != (uint) TPFlags.Default)
4124 } 4160 {
4161 // Make sure root avatar position is in the region
4162 if (acd.startpos.X < 0)
4163 acd.startpos.X = 1f;
4164 else if (acd.startpos.X >= RegionInfo.RegionSizeX)
4165 acd.startpos.X = RegionInfo.RegionSizeX - 1f;
4166 if (acd.startpos.Y < 0)
4167 acd.startpos.Y = 1f;
4168 else if (acd.startpos.Y >= RegionInfo.RegionSizeY)
4169 acd.startpos.Y = RegionInfo.RegionSizeY - 1f;
4170 }
4171 // only check access, actual relocations will happen later on ScenePresence MakeRoot
4172 // allow child agents creation
4173// if(!godlike && teleportFlags != (uint) TPFlags.Default)
4174 if(teleportFlags != (uint) TPFlags.Default)
4175 {
4176 bool checkTeleHub;
4177
4178 // don't check hubs if via home or via lure
4179 if((teleportFlags & (uint) TPFlags.ViaHome) != 0
4180 || (teleportFlags & (uint) TPFlags.ViaLure) != 0)
4181 checkTeleHub = false;
4182 else
4183 checkTeleHub = vialogin
4184 || (TelehubAllowLandmarks == true ? false : ((teleportFlags & (uint)TPFlags.ViaLandmark) != 0 ))
4185 || (teleportFlags & (uint) TPFlags.ViaLocation) != 0;
4125 4186
4126 // Honor parcel landing type and position. 4187 if(!CheckLandPositionAccess(acd.AgentID, true, checkTeleHub, acd.startpos, out reason))
4127 if (land != null)
4128 { 4188 {
4129 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 4189 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
4130 { 4190 return false;
4131 acd.startpos = land.LandData.UserLocation;
4132
4133 // Final permissions check; this time we don't allow changing the position
4134 if (!IsPositionAllowed(acd.AgentID, acd.startpos, ref reason))
4135 {
4136 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
4137 return false;
4138 }
4139 }
4140 } 4191 }
4141 } 4192 }
4142 4193
@@ -4162,12 +4213,13 @@ namespace OpenSim.Region.Framework.Scenes
4162 { 4213 {
4163 if (posX < 0) 4214 if (posX < 0)
4164 posX = 0; 4215 posX = 0;
4165 else if (posX >= (float)RegionInfo.RegionSizeX) 4216
4166 posX = (float)RegionInfo.RegionSizeX - 0.001f; 4217 else if (posX >= RegionInfo.RegionSizeX)
4218 posX = RegionInfo.RegionSizeX - 0.5f;
4167 if (posY < 0) 4219 if (posY < 0)
4168 posY = 0; 4220 posY = 0;
4169 else if (posY >= (float)RegionInfo.RegionSizeY) 4221 else if (posY >= RegionInfo.RegionSizeY)
4170 posY = (float)RegionInfo.RegionSizeY - 0.001f; 4222 posY = RegionInfo.RegionSizeY - 0.5f;
4171 4223
4172 reason = String.Empty; 4224 reason = String.Empty;
4173 if (Permissions.IsGod(agentID)) 4225 if (Permissions.IsGod(agentID))
@@ -4183,14 +4235,14 @@ namespace OpenSim.Region.Framework.Scenes
4183 if (banned || restricted) 4235 if (banned || restricted)
4184 { 4236 {
4185 ILandObject nearestParcel = GetNearestAllowedParcel(agentID, posX, posY); 4237 ILandObject nearestParcel = GetNearestAllowedParcel(agentID, posX, posY);
4238 Vector2? newPosition = null;
4186 if (nearestParcel != null) 4239 if (nearestParcel != null)
4187 { 4240 {
4188 //Move agent to nearest allowed 4241 //Move agent to nearest allowed
4189 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel); 4242// Vector2 newPosition = GetParcelSafeCorner(nearestParcel);
4190 posX = newPosition.X; 4243 newPosition = nearestParcel.GetNearestPoint(new Vector3(posX, posY,0));
4191 posY = newPosition.Y;
4192 } 4244 }
4193 else 4245 if(newPosition == null)
4194 { 4246 {
4195 if (banned) 4247 if (banned)
4196 { 4248 {
@@ -4203,6 +4255,11 @@ namespace OpenSim.Region.Framework.Scenes
4203 } 4255 }
4204 return false; 4256 return false;
4205 } 4257 }
4258 else
4259 {
4260 posX = newPosition.Value.X;
4261 posY = newPosition.Value.Y;
4262 }
4206 } 4263 }
4207 reason = ""; 4264 reason = "";
4208 return true; 4265 return true;
@@ -4213,7 +4270,7 @@ namespace OpenSim.Region.Framework.Scenes
4213 /// </summary> 4270 /// </summary>
4214 /// <param name="agent">Circuit Data of the Agent we're verifying</param> 4271 /// <param name="agent">Circuit Data of the Agent we're verifying</param>
4215 /// <param name="reason">Outputs the reason for the false response on this string</param> 4272 /// <param name="reason">Outputs the reason for the false response on this string</param>
4216 /// <returns>True if the user has a session on the grid. False if it does not. False will 4273 /// <returns>True if the user has a session on the grid. False if it does not. False will
4217 /// also return a reason.</returns> 4274 /// also return a reason.</returns>
4218 public virtual bool VerifyUserPresence(AgentCircuitData agent, out string reason) 4275 public virtual bool VerifyUserPresence(AgentCircuitData agent, out string reason)
4219 { 4276 {
@@ -4242,14 +4299,16 @@ namespace OpenSim.Region.Framework.Scenes
4242 /// </summary> 4299 /// </summary>
4243 /// <param name="agent">The circuit data for the agent</param> 4300 /// <param name="agent">The circuit data for the agent</param>
4244 /// <param name="reason">outputs the reason to this string</param> 4301 /// <param name="reason">outputs the reason to this string</param>
4245 /// <returns>True if the region accepts this agent. False if it does not. False will 4302 /// <returns>True if the region accepts this agent. False if it does not. False will
4246 /// also return a reason.</returns> 4303 /// also return a reason.</returns>
4247 protected virtual bool AuthorizeUser(AgentCircuitData agent, bool bypassAccessControl, out string reason) 4304 protected virtual bool AuthorizeUser(AgentCircuitData agent, bool bypassAccessControl, out string reason)
4248 { 4305 {
4249 reason = String.Empty; 4306 reason = String.Empty;
4250 4307
4251 if (!m_strictAccessControl) return true; 4308 if (!m_strictAccessControl)
4252 if (Permissions.IsGod(agent.AgentID)) return true; 4309 return true;
4310 if (Permissions.IsGod(agent.AgentID))
4311 return true;
4253 4312
4254 if (AuthorizationService != null) 4313 if (AuthorizationService != null)
4255 { 4314 {
@@ -4269,98 +4328,85 @@ namespace OpenSim.Region.Framework.Scenes
4269 // the root is done elsewhere (QueryAccess) 4328 // the root is done elsewhere (QueryAccess)
4270 if (!bypassAccessControl) 4329 if (!bypassAccessControl)
4271 { 4330 {
4272 if (RegionInfo.EstateSettings != null) 4331 if(RegionInfo.EstateSettings == null)
4273 { 4332 {
4274 if (RegionInfo.EstateSettings.IsBanned(agent.AgentID)) 4333 // something is broken? let it get in
4275 { 4334 m_log.ErrorFormat("[CONNECTION BEGIN]: Estate Settings is null!");
4276 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 4335 return true;
4277 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
4278 reason = String.Format("Denied access to region {0}: You have been banned from that region.",
4279 RegionInfo.RegionName);
4280 return false;
4281 }
4282 } 4336 }
4283 else 4337
4338 // check estate ban
4339 int flags = GetUserFlags(agent.AgentID);
4340 if (RegionInfo.EstateSettings.IsBanned(agent.AgentID, flags))
4284 { 4341 {
4285 m_log.ErrorFormat("[CONNECTION BEGIN]: Estate Settings is null!"); 4342 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
4343 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
4344 reason = String.Format("Denied access to region {0}: You have been banned from that region.",
4345 RegionInfo.RegionName);
4346 return false;
4286 } 4347 }
4287 4348
4288 List<UUID> agentGroups = new List<UUID>(); 4349 // public access
4350 if (RegionInfo.EstateSettings.PublicAccess)
4351 return true;
4352
4353 // in access list / owner / manager
4354 if (RegionInfo.EstateSettings.HasAccess(agent.AgentID))
4355 return true;
4289 4356
4290 if (m_groupsModule != null) 4357 // finally test groups
4358 bool groupAccess = false;
4359
4360 // some say GOTO is ugly
4361 if(m_groupsModule == null) // if no groups refuse
4362 goto Label_GroupsDone;
4363
4364 UUID[] estateGroups = RegionInfo.EstateSettings.EstateGroups;
4365
4366 if(estateGroups == null)
4291 { 4367 {
4292 GroupMembershipData[] GroupMembership = m_groupsModule.GetMembershipData(agent.AgentID); 4368 m_log.ErrorFormat("[CONNECTION BEGIN]: Estate GroupMembership is null!");
4369 goto Label_GroupsDone;
4370 }
4293 4371
4294 if (GroupMembership != null) 4372 if(estateGroups.Length == 0)
4295 { 4373 goto Label_GroupsDone;
4296 for (int i = 0; i < GroupMembership.Length; i++) 4374
4297 agentGroups.Add(GroupMembership[i].GroupID); 4375 List<UUID> agentGroups = new List<UUID>();
4298 } 4376 GroupMembershipData[] GroupMembership = m_groupsModule.GetMembershipData(agent.AgentID);
4299 else 4377
4300 { 4378 if(GroupMembership == null)
4301 m_log.ErrorFormat("[CONNECTION BEGIN]: GroupMembership is null!"); 4379 {
4302 } 4380 m_log.ErrorFormat("[CONNECTION BEGIN]: GroupMembership is null!");
4381 goto Label_GroupsDone;
4303 } 4382 }
4304 4383
4305 bool groupAccess = false; 4384 if(GroupMembership.Length == 0)
4306 UUID[] estateGroups = RegionInfo.EstateSettings.EstateGroups; 4385 goto Label_GroupsDone;
4386
4387 for(int i = 0;i < GroupMembership.Length;i++)
4388 agentGroups.Add(GroupMembership[i].GroupID);
4307 4389
4308 if (estateGroups != null) 4390 foreach(UUID group in estateGroups)
4309 { 4391 {
4310 foreach (UUID group in estateGroups) 4392 if(agentGroups.Contains(group))
4311 { 4393 {
4312 if (agentGroups.Contains(group)) 4394 groupAccess = true;
4313 { 4395 break;
4314 groupAccess = true;
4315 break;
4316 }
4317 } 4396 }
4318 } 4397 }
4319 else
4320 {
4321 m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!");
4322 }
4323 4398
4324 if (!RegionInfo.EstateSettings.PublicAccess && 4399Label_GroupsDone:
4325 !RegionInfo.EstateSettings.HasAccess(agent.AgentID) && 4400 if (!groupAccess)
4326 !groupAccess)
4327 { 4401 {
4328 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the estate", 4402 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the estate",
4329 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 4403 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
4330 reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.", 4404 reason = String.Format("Denied access to private region {0}: You do not have access to that region.",
4331 RegionInfo.RegionName); 4405 RegionInfo.RegionName);
4332 return false; 4406 return false;
4333 } 4407 }
4334 } 4408 }
4335 4409
4336 // TODO: estate/region settings are not properly hooked up
4337 // to ILandObject.isRestrictedFromLand()
4338 // if (null != LandChannel)
4339 // {
4340 // // region seems to have local Id of 1
4341 // ILandObject land = LandChannel.GetLandObject(1);
4342 // if (null != land)
4343 // {
4344 // if (land.isBannedFromLand(agent.AgentID))
4345 // {
4346 // m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user has been banned from land",
4347 // agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
4348 // reason = String.Format("Denied access to private region {0}: You are banned from that region.",
4349 // RegionInfo.RegionName);
4350 // return false;
4351 // }
4352
4353 // if (land.isRestrictedFromLand(agent.AgentID))
4354 // {
4355 // m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region",
4356 // agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
4357 // reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.",
4358 // RegionInfo.RegionName);
4359 // return false;
4360 // }
4361 // }
4362 // }
4363
4364 return true; 4410 return true;
4365 } 4411 }
4366 4412
@@ -4449,7 +4495,7 @@ namespace OpenSim.Region.Framework.Scenes
4449// } 4495// }
4450 4496
4451 /// <summary> 4497 /// <summary>
4452 /// We've got an update about an agent that sees into this region, 4498 /// We've got an update about an agent that sees into this region,
4453 /// send it to ScenePresence for processing It's the full data. 4499 /// send it to ScenePresence for processing It's the full data.
4454 /// </summary> 4500 /// </summary>
4455 /// <param name="cAgentData">Agent that contains all of the relevant things about an agent. 4501 /// <param name="cAgentData">Agent that contains all of the relevant things about an agent.
@@ -4460,8 +4506,25 @@ namespace OpenSim.Region.Framework.Scenes
4460 m_log.DebugFormat( 4506 m_log.DebugFormat(
4461 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName); 4507 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName);
4462 4508
4509 if (!LoginsEnabled)
4510 {
4511// reason = "Logins Disabled";
4512 m_log.DebugFormat(
4513 "[SCENE]: update for {0} in {1} refused: Logins Disabled", cAgentData.AgentID, RegionInfo.RegionName);
4514 return false;
4515 }
4516 // We have to wait until the viewer contacts this region after receiving EAC.
4517 // That calls AddNewClient, which finally creates the ScenePresence
4518 int flags = GetUserFlags(cAgentData.AgentID);
4519 if (RegionInfo.EstateSettings.IsBanned(cAgentData.AgentID, flags))
4520 {
4521 m_log.DebugFormat("[SCENE]: Denying root agent entry to {0}: banned", cAgentData.AgentID);
4522 return false;
4523 }
4524
4463 // TODO: This check should probably be in QueryAccess(). 4525 // TODO: This check should probably be in QueryAccess().
4464 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, RegionInfo.RegionSizeX / 2, RegionInfo.RegionSizeY / 2); 4526 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID,
4527 (float)RegionInfo.RegionSizeX * 0.5f, (float)RegionInfo.RegionSizeY * 0.5f);
4465 if (nearestParcel == null) 4528 if (nearestParcel == null)
4466 { 4529 {
4467 m_log.InfoFormat( 4530 m_log.InfoFormat(
@@ -4472,20 +4535,26 @@ namespace OpenSim.Region.Framework.Scenes
4472 } 4535 }
4473 4536
4474 // We have to wait until the viewer contacts this region 4537 // We have to wait until the viewer contacts this region
4475 // after receiving the EnableSimulator HTTP Event Queue message (for the v1 teleport protocol) 4538 // after receiving the EnableSimulator HTTP Event Queue message (for the v1 teleport protocol)
4476 // or TeleportFinish (for the v2 teleport protocol). This triggers the viewer to send 4539 // or TeleportFinish (for the v2 teleport protocol). This triggers the viewer to send
4477 // a UseCircuitCode packet which in turn calls AddNewAgent which finally creates the ScenePresence. 4540 // a UseCircuitCode packet which in turn calls AddNewAgent which finally creates the ScenePresence.
4478 ScenePresence sp = WaitGetScenePresence(cAgentData.AgentID); 4541 ScenePresence sp = WaitGetScenePresence(cAgentData.AgentID);
4479 4542
4480 if (sp != null) 4543 if (sp != null)
4481 { 4544 {
4545 if (!sp.IsChildAgent)
4546 {
4547 m_log.WarnFormat("[SCENE]: Ignoring a child update on a root agent {0} {1} in {2}",
4548 sp.Name, sp.UUID, Name);
4549 return false;
4550 }
4482 if (cAgentData.SessionID != sp.ControllingClient.SessionId) 4551 if (cAgentData.SessionID != sp.ControllingClient.SessionId)
4483 { 4552 {
4484 m_log.WarnFormat( 4553 m_log.WarnFormat(
4485 "[SCENE]: Attempt to update agent {0} with invalid session id {1} (possibly from simulator in older version; tell them to update).", 4554 "[SCENE]: Attempt to update agent {0} with invalid session id {1} (possibly from simulator in older version; tell them to update).",
4486 sp.UUID, cAgentData.SessionID); 4555 sp.UUID, cAgentData.SessionID);
4487 4556
4488 Console.WriteLine(String.Format("[SCENE]: Attempt to update agent {0} ({1}) with invalid session id {2}", 4557 Console.WriteLine(String.Format("[SCENE]: Attempt to update agent {0} ({1}) with invalid session id {2}",
4489 sp.UUID, sp.ControllingClient.SessionId, cAgentData.SessionID)); 4558 sp.UUID, sp.ControllingClient.SessionId, cAgentData.SessionID));
4490 } 4559 }
4491 4560
@@ -4517,7 +4586,7 @@ namespace OpenSim.Region.Framework.Scenes
4517 } 4586 }
4518 4587
4519 /// <summary> 4588 /// <summary>
4520 /// We've got an update about an agent that sees into this region, 4589 /// We've got an update about an agent that sees into this region,
4521 /// send it to ScenePresence for processing It's only positional data 4590 /// send it to ScenePresence for processing It's only positional data
4522 /// </summary> 4591 /// </summary>
4523 /// <param name="cAgentData">AgentPosition that contains agent positional data so we can know what to send</param> 4592 /// <param name="cAgentData">AgentPosition that contains agent positional data so we can know what to send</param>
@@ -4525,7 +4594,7 @@ namespace OpenSim.Region.Framework.Scenes
4525 public virtual bool IncomingUpdateChildAgent(AgentPosition cAgentData) 4594 public virtual bool IncomingUpdateChildAgent(AgentPosition cAgentData)
4526 { 4595 {
4527// m_log.DebugFormat( 4596// m_log.DebugFormat(
4528// "[SCENE PRESENCE]: IncomingChildAgentDataUpdate POSITION for {0} in {1}, position {2}", 4597// "[SCENE PRESENCE]: IncomingChildAgentDataUpdate POSITION for {0} in {1}, position {2}",
4529// cAgentData.AgentID, Name, cAgentData.Position); 4598// cAgentData.AgentID, Name, cAgentData.Position);
4530 4599
4531 ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID); 4600 ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID);
@@ -4533,7 +4602,7 @@ namespace OpenSim.Region.Framework.Scenes
4533 { 4602 {
4534// if (childAgentUpdate.ControllingClient.SessionId != cAgentData.SessionID) 4603// if (childAgentUpdate.ControllingClient.SessionId != cAgentData.SessionID)
4535// // Only warn for now 4604// // Only warn for now
4536// m_log.WarnFormat("[SCENE]: Attempt at updating position of agent {0} with invalid session id {1}. Neighbor running older version?", 4605// m_log.WarnFormat("[SCENE]: Attempt at updating position of agent {0} with invalid session id {1}. Neighbor running older version?",
4537// childAgentUpdate.UUID, cAgentData.SessionID); 4606// childAgentUpdate.UUID, cAgentData.SessionID);
4538 4607
4539 // I can't imagine *yet* why we would get an update if the agent is a root agent.. 4608 // I can't imagine *yet* why we would get an update if the agent is a root agent..
@@ -4563,10 +4632,10 @@ namespace OpenSim.Region.Framework.Scenes
4563 /// <param name='agentID'></param> 4632 /// <param name='agentID'></param>
4564 protected virtual ScenePresence WaitGetScenePresence(UUID agentID) 4633 protected virtual ScenePresence WaitGetScenePresence(UUID agentID)
4565 { 4634 {
4566 int ntimes = 20; 4635 int ntimes = 120; // 30s
4567 ScenePresence sp = null; 4636 ScenePresence sp = null;
4568 while ((sp = GetScenePresence(agentID)) == null && (ntimes-- > 0)) 4637 while ((sp = GetScenePresence(agentID)) == null && (ntimes-- > 0))
4569 Thread.Sleep(1000); 4638 Thread.Sleep(250);
4570 4639
4571 if (sp == null) 4640 if (sp == null)
4572 m_log.WarnFormat( 4641 m_log.WarnFormat(
@@ -4593,7 +4662,7 @@ namespace OpenSim.Region.Framework.Scenes
4593 if (acd == null) 4662 if (acd == null)
4594 { 4663 {
4595 m_log.DebugFormat( 4664 m_log.DebugFormat(
4596 "[SCENE]: Request to close agent {0} but no such agent in scene {1}. May have been closed previously.", 4665 "[SCENE]: Request to close agent {0} but no such agent in scene {1}. May have been closed previously.",
4597 agentID, Name); 4666 agentID, Name);
4598 4667
4599 return false; 4668 return false;
@@ -4606,13 +4675,23 @@ namespace OpenSim.Region.Framework.Scenes
4606 else 4675 else
4607 { 4676 {
4608 m_log.WarnFormat( 4677 m_log.WarnFormat(
4609 "[SCENE]: Request to close agent {0} with invalid authorization token {1} in {2}", 4678 "[SCENE]: Request to close agent {0} with invalid authorization token {1} in {2}",
4610 agentID, auth_token, Name); 4679 agentID, auth_token, Name);
4611 } 4680 }
4612 4681
4613 return false; 4682 return false;
4614 } 4683 }
4615 4684
4685// public bool IncomingCloseAgent(UUID agentID)
4686// {
4687// return IncomingCloseAgent(agentID, false);
4688// }
4689
4690// public bool IncomingCloseChildAgent(UUID agentID)
4691// {
4692// return IncomingCloseAgent(agentID, true);
4693// }
4694
4616 /// <summary> 4695 /// <summary>
4617 /// Tell a single client to prepare to close. 4696 /// Tell a single client to prepare to close.
4618 /// </summary> 4697 /// </summary>
@@ -4675,8 +4754,22 @@ namespace OpenSim.Region.Framework.Scenes
4675 4754
4676 if (sp == null) 4755 if (sp == null)
4677 { 4756 {
4757 // If there is no scene presence, we may be handling a dead
4758 // client. These can keep an avatar from reentering a region
4759 // and since they don't get cleaned up they will stick
4760 // around until region restart. So, if there is no SP,
4761 // remove the client as well.
4762 IClientAPI client = null;
4763 if (m_clientManager.TryGetValue(agentID, out client))
4764 {
4765 m_clientManager.Remove(agentID);
4766 if (CapsModule != null)
4767 CapsModule.RemoveCaps(agentID, 0);
4768 m_log.DebugFormat( "[SCENE]: Dead client for agent ID {0} was cleaned up in {1}", agentID, Name);
4769 return true;
4770 }
4678 m_log.DebugFormat( 4771 m_log.DebugFormat(
4679 "[SCENE]: Called CloseClient() with agent ID {0} but no such presence is in {1}", 4772 "[SCENE]: Called CloseClient() with agent ID {0} but no such presence is in {1}",
4680 agentID, Name); 4773 agentID, Name);
4681 4774
4682 return false; 4775 return false;
@@ -4709,7 +4802,11 @@ namespace OpenSim.Region.Framework.Scenes
4709 sp.LifecycleState = ScenePresenceState.Removing; 4802 sp.LifecycleState = ScenePresenceState.Removing;
4710 } 4803 }
4711 4804
4712 sp.ControllingClient.Close(force); 4805 if (sp != null)
4806 {
4807 sp.ControllingClient.Close(force, force);
4808 return true;
4809 }
4713 4810
4714 return true; 4811 return true;
4715 } 4812 }
@@ -4728,16 +4825,34 @@ namespace OpenSim.Region.Framework.Scenes
4728 public void RequestTeleportLocation(IClientAPI remoteClient, string regionName, Vector3 position, 4825 public void RequestTeleportLocation(IClientAPI remoteClient, string regionName, Vector3 position,
4729 Vector3 lookat, uint teleportFlags) 4826 Vector3 lookat, uint teleportFlags)
4730 { 4827 {
4731 GridRegion region = GridService.GetRegionByName(RegionInfo.ScopeID, regionName); 4828 if (EntityTransferModule == null)
4829 {
4830 m_log.DebugFormat("[SCENE]: Unable to perform teleports: no AgentTransferModule is active");
4831 return;
4832 }
4732 4833
4733 if (region == null) 4834 ScenePresence sp = GetScenePresence(remoteClient.AgentId);
4835 if (sp == null || sp.IsDeleted || sp.IsInTransit)
4836 return;
4837
4838 ulong regionHandle = 0;
4839 if(regionName == RegionInfo.RegionName)
4840 regionHandle = RegionInfo.RegionHandle;
4841 else
4842 {
4843 GridRegion region = GridService.GetRegionByName(RegionInfo.ScopeID, regionName);
4844 if (region != null)
4845 regionHandle = region.RegionHandle;
4846 }
4847
4848 if(regionHandle == 0)
4734 { 4849 {
4735 // can't find the region: Tell viewer and abort 4850 // can't find the region: Tell viewer and abort
4736 remoteClient.SendTeleportFailed("The region '" + regionName + "' could not be found."); 4851 remoteClient.SendTeleportFailed("The region '" + regionName + "' could not be found.");
4737 return; 4852 return;
4738 } 4853 }
4739 4854
4740 RequestTeleportLocation(remoteClient, region.RegionHandle, position, lookat, teleportFlags); 4855 EntityTransferModule.Teleport(sp, regionHandle, position, lookat, teleportFlags);
4741 } 4856 }
4742 4857
4743 /// <summary> 4858 /// <summary>
@@ -4751,19 +4866,17 @@ namespace OpenSim.Region.Framework.Scenes
4751 public void RequestTeleportLocation(IClientAPI remoteClient, ulong regionHandle, Vector3 position, 4866 public void RequestTeleportLocation(IClientAPI remoteClient, ulong regionHandle, Vector3 position,
4752 Vector3 lookAt, uint teleportFlags) 4867 Vector3 lookAt, uint teleportFlags)
4753 { 4868 {
4754 ScenePresence sp = GetScenePresence(remoteClient.AgentId); 4869 if (EntityTransferModule == null)
4755 if (sp != null)
4756 { 4870 {
4757 if (EntityTransferModule != null) 4871 m_log.DebugFormat("[SCENE]: Unable to perform teleports: no AgentTransferModule is active");
4758 { 4872 return;
4759 EntityTransferModule.Teleport(sp, regionHandle, position, lookAt, teleportFlags);
4760 }
4761 else
4762 {
4763 m_log.DebugFormat("[SCENE]: Unable to perform teleports: no AgentTransferModule is active");
4764 sp.ControllingClient.SendTeleportFailed("Unable to perform teleports on this simulator.");
4765 }
4766 } 4873 }
4874
4875 ScenePresence sp = GetScenePresence(remoteClient.AgentId);
4876 if (sp == null || sp.IsDeleted || sp.IsInTransit)
4877 return;
4878
4879 EntityTransferModule.Teleport(sp, regionHandle, position, lookAt, teleportFlags);
4767 } 4880 }
4768 4881
4769 public bool CrossAgentToNewRegion(ScenePresence agent, bool isFlying) 4882 public bool CrossAgentToNewRegion(ScenePresence agent, bool isFlying)
@@ -4871,7 +4984,10 @@ namespace OpenSim.Region.Framework.Scenes
4871 4984
4872 public LandData GetLandData(float x, float y) 4985 public LandData GetLandData(float x, float y)
4873 { 4986 {
4874 return LandChannel.GetLandObject(x, y).LandData; 4987 ILandObject parcel = LandChannel.GetLandObject(x, y);
4988 if (parcel == null)
4989 return null;
4990 return parcel.LandData;
4875 } 4991 }
4876 4992
4877 /// <summary> 4993 /// <summary>
@@ -4886,72 +5002,69 @@ namespace OpenSim.Region.Framework.Scenes
4886 5002
4887 public LandData GetLandData(uint x, uint y) 5003 public LandData GetLandData(uint x, uint y)
4888 { 5004 {
4889 m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y); 5005// m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y);
4890 return LandChannel.GetLandObject((int)x, (int)y).LandData; 5006 ILandObject parcel = LandChannel.GetLandObject((int)x, (int)y);
5007 if (parcel == null)
5008 return null;
5009 return parcel.LandData;
4891 } 5010 }
4892 5011
4893 #endregion 5012 #endregion
4894 5013
4895 #region Script Engine 5014 #region Script Engine
4896 5015 public bool LSLScriptDanger(SceneObjectPart part, Vector3 pos)
4897 private bool ScriptDanger(SceneObjectPart part, Vector3 pos)
4898 { 5016 {
5017
4899 ILandObject parcel = LandChannel.GetLandObject(pos.X, pos.Y); 5018 ILandObject parcel = LandChannel.GetLandObject(pos.X, pos.Y);
4900 if (part != null) 5019 if (parcel == null)
4901 { 5020 return true;
4902 if (parcel != null) 5021
4903 { 5022 LandData ldata = parcel.LandData;
4904 if ((parcel.LandData.Flags & (uint)ParcelFlags.AllowOtherScripts) != 0) 5023 if (ldata == null)
4905 { 5024 return true;
4906 return true; 5025
4907 } 5026 uint landflags = ldata.Flags;
4908 else if ((part.OwnerID == parcel.LandData.OwnerID) || Permissions.IsGod(part.OwnerID)) 5027
4909 { 5028 uint mask = (uint)(ParcelFlags.CreateObjects | ParcelFlags.AllowAPrimitiveEntry);
4910 return true; 5029 if((landflags & mask) != mask)
4911 } 5030 return true;
4912 else if (((parcel.LandData.Flags & (uint)ParcelFlags.AllowGroupScripts) != 0) 5031
4913 && (parcel.LandData.GroupID != UUID.Zero) && (parcel.LandData.GroupID == part.GroupID)) 5032 if((landflags & (uint)ParcelFlags.AllowOtherScripts) != 0)
4914 { 5033 return false;
4915 return true;
4916 }
4917 else
4918 {
4919 return false;
4920 }
4921 }
4922 else
4923 {
4924 5034
4925 if (pos.X > 0f && pos.X < RegionInfo.RegionSizeX && pos.Y > 0f && pos.Y < RegionInfo.RegionSizeY) 5035 if(part == null)
4926 { 5036 return true;
4927 // The only time parcel != null when an object is inside a region is when 5037 if(part.GroupID == ldata.GroupID && (landflags & (uint)ParcelFlags.AllowGroupScripts) != 0)
4928 // there is nothing behind the landchannel. IE, no land plugin loaded.
4929 return true;
4930 }
4931 else
4932 {
4933 // The object is outside of this region. Stop piping events to it.
4934 return false;
4935 }
4936 }
4937 }
4938 else
4939 {
4940 return false; 5038 return false;
4941 } 5039
5040 return true;
4942 } 5041 }
4943 5042
4944 public bool ScriptDanger(uint localID, Vector3 pos) 5043 private bool ScriptDanger(SceneObjectPart part, Vector3 pos)
4945 { 5044 {
4946 SceneObjectPart part = GetSceneObjectPart(localID); 5045 if (part == null)
4947 if (part != null) 5046 return false;
5047
5048 ILandObject parcel = LandChannel.GetLandObject(pos.X, pos.Y);
5049 if (parcel != null)
4948 { 5050 {
4949 return ScriptDanger(part, pos); 5051 if ((parcel.LandData.Flags & (uint)ParcelFlags.AllowOtherScripts) != 0)
5052 return true;
5053
5054 if ((part.OwnerID == parcel.LandData.OwnerID) || Permissions.IsGod(part.OwnerID))
5055 return true;
5056
5057 if (((parcel.LandData.Flags & (uint)ParcelFlags.AllowGroupScripts) != 0)
5058 && (parcel.LandData.GroupID != UUID.Zero) && (parcel.LandData.GroupID == part.GroupID))
5059 return true;
4950 } 5060 }
4951 else 5061 else
4952 { 5062 {
4953 return false; 5063 if (pos.X > 0f && pos.X < RegionInfo.RegionSizeX && pos.Y > 0f && pos.Y < RegionInfo.RegionSizeY)
5064 return true;
4954 } 5065 }
5066
5067 return false;
4955 } 5068 }
4956 5069
4957 public bool PipeEventsForScript(uint localID) 5070 public bool PipeEventsForScript(uint localID)
@@ -5177,7 +5290,7 @@ namespace OpenSim.Region.Framework.Scenes
5177 /// Get a scene object group that contains the prim with the given local id 5290 /// Get a scene object group that contains the prim with the given local id
5178 /// </summary> 5291 /// </summary>
5179 /// <param name="localID"></param> 5292 /// <param name="localID"></param>
5180 /// <returns>null if no scene object group containing that prim is found</returns> 5293 /// <returns>null if no scene object group containing that prim is found</returns>
5181 public SceneObjectGroup GetGroupByPrim(uint localID) 5294 public SceneObjectGroup GetGroupByPrim(uint localID)
5182 { 5295 {
5183 return m_sceneGraph.GetGroupByPrim(localID); 5296 return m_sceneGraph.GetGroupByPrim(localID);
@@ -5187,7 +5300,7 @@ namespace OpenSim.Region.Framework.Scenes
5187 /// Get a scene object group that contains the prim with the given uuid 5300 /// Get a scene object group that contains the prim with the given uuid
5188 /// </summary> 5301 /// </summary>
5189 /// <param name="fullID"></param> 5302 /// <param name="fullID"></param>
5190 /// <returns>null if no scene object group containing that prim is found</returns> 5303 /// <returns>null if no scene object group containing that prim is found</returns>
5191 public SceneObjectGroup GetGroupByPrim(UUID fullID) 5304 public SceneObjectGroup GetGroupByPrim(UUID fullID)
5192 { 5305 {
5193 return m_sceneGraph.GetGroupByPrim(fullID); 5306 return m_sceneGraph.GetGroupByPrim(fullID);
@@ -5221,7 +5334,12 @@ namespace OpenSim.Region.Framework.Scenes
5221 /// <param name="action"></param> 5334 /// <param name="action"></param>
5222 public void ForEachClient(Action<IClientAPI> action) 5335 public void ForEachClient(Action<IClientAPI> action)
5223 { 5336 {
5224 m_clientManager.ForEachSync(action); 5337 m_clientManager.ForEach(action);
5338 }
5339
5340 public int GetNumberOfClients()
5341 {
5342 return m_clientManager.Count;
5225 } 5343 }
5226 5344
5227 public bool TryGetClient(UUID avatarID, out IClientAPI client) 5345 public bool TryGetClient(UUID avatarID, out IClientAPI client)
@@ -5264,6 +5382,7 @@ namespace OpenSim.Region.Framework.Scenes
5264 5382
5265 public void CleanTempObjects() 5383 public void CleanTempObjects()
5266 { 5384 {
5385 DateTime now = DateTime.UtcNow;
5267 EntityBase[] entities = GetEntities(); 5386 EntityBase[] entities = GetEntities();
5268 foreach (EntityBase obj in entities) 5387 foreach (EntityBase obj in entities)
5269 { 5388 {
@@ -5275,13 +5394,12 @@ namespace OpenSim.Region.Framework.Scenes
5275 { 5394 {
5276 if ((grp.RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) 5395 if ((grp.RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
5277 { 5396 {
5278 if (grp.RootPart.Expires <= DateTime.Now) 5397 if (grp.GetSittingAvatarsCount() == 0 && grp.RootPart.Expires <= now)
5279 DeleteSceneObject(grp, false); 5398 DeleteSceneObject(grp, false);
5280 } 5399 }
5281 } 5400 }
5282 } 5401 }
5283 } 5402 }
5284
5285 } 5403 }
5286 5404
5287 public void DeleteFromStorage(UUID uuid) 5405 public void DeleteFromStorage(UUID uuid)
@@ -5289,7 +5407,7 @@ namespace OpenSim.Region.Framework.Scenes
5289 SimulationDataService.RemoveObject(uuid, RegionInfo.RegionID); 5407 SimulationDataService.RemoveObject(uuid, RegionInfo.RegionID);
5290 } 5408 }
5291 5409
5292 public int GetHealth() 5410 public int GetHealth(out int flags, out string message)
5293 { 5411 {
5294 // Returns: 5412 // Returns:
5295 // 1 = sim is up and accepting http requests. The heartbeat has 5413 // 1 = sim is up and accepting http requests. The heartbeat has
@@ -5297,27 +5415,74 @@ namespace OpenSim.Region.Framework.Scenes
5297 // admin restart may succeed 5415 // admin restart may succeed
5298 // 5416 //
5299 // 2 = Sim is up and the heartbeat is running. The sim is likely 5417 // 2 = Sim is up and the heartbeat is running. The sim is likely
5300 // usable for people within and logins _may_ work 5418 // usable for people within
5419 //
5420 // 3 = Sim is up and one packet thread is running. Sim is
5421 // unstable and will not accept new logins
5301 // 5422 //
5302 // 3 = We have seen a new user enter within the past 4 minutes 5423 // 4 = Sim is up and both packet threads are running. Sim is
5424 // likely usable
5425 //
5426 // 5 = We have seen a new user enter within the past 4 minutes
5303 // which can be seen as positive confirmation of sim health 5427 // which can be seen as positive confirmation of sim health
5304 // 5428 //
5305 int health = 1; // Start at 1, means we're up 5429 int health = 1; // Start at 1, means we're up
5306 5430
5307 if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) < 1000) 5431 flags = 0;
5308 health += 1; 5432 message = String.Empty;
5433
5434 CheckHeartbeat();
5435
5436 if (m_firstHeartbeat || (m_lastIncoming == 0 && m_lastOutgoing == 0))
5437 {
5438 // We're still starting
5439 // 0 means "in startup", it can't happen another way, since
5440 // to get here, we must be able to accept http connections
5441 return 0;
5442 }
5443
5444 if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) < 2000)
5445 {
5446 health+=1;
5447 flags |= 1;
5448 }
5449
5450 if (Util.EnvironmentTickCountSubtract(m_lastIncoming) < 2000)
5451 {
5452 health+=1;
5453 flags |= 2;
5454 }
5455
5456 if (Util.EnvironmentTickCountSubtract(m_lastOutgoing) < 2000)
5457 {
5458 health+=1;
5459 flags |= 4;
5460 }
5461 /*
5309 else 5462 else
5463 {
5464int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
5465System.Diagnostics.Process proc = new System.Diagnostics.Process();
5466proc.EnableRaisingEvents=false;
5467proc.StartInfo.FileName = "/bin/kill";
5468proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
5469proc.Start();
5470proc.WaitForExit();
5471Thread.Sleep(1000);
5472Environment.Exit(1);
5473 }
5474 */
5475
5476 if (flags != 7)
5310 return health; 5477 return health;
5311 5478
5312 // A login in the last 4 mins? We can't be doing too badly 5479 // A login in the last 4 mins? We can't be doing too badly
5313 // 5480 //
5314 if ((Util.EnvironmentTickCountSubtract(m_LastLogin)) < 240000) 5481 if (Util.EnvironmentTickCountSubtract(m_LastLogin) < 240000)
5315 health++; 5482 health++;
5316 else 5483 else
5317 return health; 5484 return health;
5318 5485
5319// CheckHeartbeat();
5320
5321 return health; 5486 return health;
5322 } 5487 }
5323 5488
@@ -5405,7 +5570,7 @@ namespace OpenSim.Region.Framework.Scenes
5405 bool wasUsingPhysics = ((jointProxyObject.Flags & PrimFlags.Physics) != 0); 5570 bool wasUsingPhysics = ((jointProxyObject.Flags & PrimFlags.Physics) != 0);
5406 if (wasUsingPhysics) 5571 if (wasUsingPhysics)
5407 { 5572 {
5408 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 5573 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
5409 } 5574 }
5410 } 5575 }
5411 5576
@@ -5508,14 +5673,14 @@ namespace OpenSim.Region.Framework.Scenes
5508 return (((vsn.X * xdiff) + (vsn.Y * ydiff)) / (-1 * vsn.Z)) + p0.Z; 5673 return (((vsn.X * xdiff) + (vsn.Y * ydiff)) / (-1 * vsn.Z)) + p0.Z;
5509 } 5674 }
5510 5675
5511// private void CheckHeartbeat() 5676 private void CheckHeartbeat()
5512// { 5677 {
5513// if (m_firstHeartbeat) 5678 if (m_firstHeartbeat)
5514// return; 5679 return;
5515// 5680
5516// if (Util.EnvironmentTickCountSubtract(m_lastFrameTick) > 2000) 5681 if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) > 5000)
5517// StartTimer(); 5682 Start();
5518// } 5683 }
5519 5684
5520 public override ISceneObject DeserializeObject(string representation) 5685 public override ISceneObject DeserializeObject(string representation)
5521 { 5686 {
@@ -5534,27 +5699,26 @@ namespace OpenSim.Region.Framework.Scenes
5534 5699
5535 public Vector3 GetNearestAllowedPosition(ScenePresence avatar, ILandObject excludeParcel) 5700 public Vector3 GetNearestAllowedPosition(ScenePresence avatar, ILandObject excludeParcel)
5536 { 5701 {
5537 ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, excludeParcel); 5702 Vector3 pos = avatar.AbsolutePosition;
5703
5704 ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, pos.X, pos.Y, excludeParcel);
5538 5705
5539 if (nearestParcel != null) 5706 if (nearestParcel != null)
5540 { 5707 {
5541 Vector3 dir = Vector3.Normalize(Vector3.Multiply(avatar.Velocity, -1)); 5708 Vector2? nearestPoint = null;
5542 //Try to get a location that feels like where they came from 5709 Vector3 dir = -avatar.Velocity;
5543 Vector3? nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel); 5710 float dirlen = dir.Length();
5544 if (nearestPoint != null) 5711 if(dirlen > 1.0f)
5545 { 5712 //Try to get a location that feels like where they came from
5546 m_log.Debug("Found a sane previous position based on velocity, sending them to: " + nearestPoint.ToString()); 5713 nearestPoint = nearestParcel.GetNearestPointAlongDirection(pos, dir);
5547 return nearestPoint.Value; 5714
5548 } 5715 if (nearestPoint == null)
5716 nearestPoint = nearestParcel.GetNearestPoint(pos);
5549 5717
5550 //Sometimes velocity might be zero (local teleport), so try finding point along path from avatar to center of nearest parcel
5551 Vector3 directionToParcelCenter = Vector3.Subtract(GetParcelCenterAtGround(nearestParcel), avatar.AbsolutePosition);
5552 dir = Vector3.Normalize(directionToParcelCenter);
5553 nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel);
5554 if (nearestPoint != null) 5718 if (nearestPoint != null)
5555 { 5719 {
5556 m_log.Debug("They had a zero velocity, sending them to: " + nearestPoint.ToString()); 5720 return GetPositionAtAvatarHeightOrGroundHeight(avatar,
5557 return nearestPoint.Value; 5721 nearestPoint.Value.X, nearestPoint.Value.Y);
5558 } 5722 }
5559 5723
5560 ILandObject dest = LandChannel.GetLandObject(avatar.lastKnownAllowedPosition.X, avatar.lastKnownAllowedPosition.Y); 5724 ILandObject dest = LandChannel.GetLandObject(avatar.lastKnownAllowedPosition.X, avatar.lastKnownAllowedPosition.Y);
@@ -5572,32 +5736,16 @@ namespace OpenSim.Region.Framework.Scenes
5572 //Go to the edge, this happens in teleporting to a region with no available parcels 5736 //Go to the edge, this happens in teleporting to a region with no available parcels
5573 Vector3 nearestRegionEdgePoint = GetNearestRegionEdgePosition(avatar); 5737 Vector3 nearestRegionEdgePoint = GetNearestRegionEdgePosition(avatar);
5574 5738
5575 //m_log.Debug("They are really in a place they don't belong, sending them to: " + nearestRegionEdgePoint.ToString()); 5739 //Debug.WriteLine("They are really in a place they don't belong, sending them to: " + nearestRegionEdgePoint.ToString());
5576
5577 return nearestRegionEdgePoint; 5740 return nearestRegionEdgePoint;
5578 } 5741 }
5579 5742
5580 private Vector3 GetParcelCenterAtGround(ILandObject parcel) 5743 private Vector3 GetParcelCenterAtGround(ILandObject parcel)
5581 { 5744 {
5582 Vector2 center = GetParcelCenter(parcel); 5745 Vector2 center = parcel.CenterPoint;
5583 return GetPositionAtGround(center.X, center.Y); 5746 return GetPositionAtGround(center.X, center.Y);
5584 } 5747 }
5585 5748
5586 private Vector3? GetNearestPointInParcelAlongDirectionFromPoint(Vector3 pos, Vector3 direction, ILandObject parcel)
5587 {
5588 Vector3 unitDirection = Vector3.Normalize(direction);
5589 //Making distance to search go through some sane limit of distance
5590 for (float distance = 0; distance < Math.Max(RegionInfo.RegionSizeX, RegionInfo.RegionSizeY) * 2; distance += .5f)
5591 {
5592 Vector3 testPos = Vector3.Add(pos, Vector3.Multiply(unitDirection, distance));
5593 if (parcel.ContainsPoint((int)testPos.X, (int)testPos.Y))
5594 {
5595 return testPos;
5596 }
5597 }
5598 return null;
5599 }
5600
5601 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y) 5749 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y)
5602 { 5750 {
5603 return GetNearestAllowedParcel(avatarId, x, y, null); 5751 return GetNearestAllowedParcel(avatarId, x, y, null);
@@ -5605,18 +5753,30 @@ namespace OpenSim.Region.Framework.Scenes
5605 5753
5606 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y, ILandObject excludeParcel) 5754 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y, ILandObject excludeParcel)
5607 { 5755 {
5608 List<ILandObject> all = AllParcels(); 5756 if(LandChannel == null)
5609 float minParcelDistance = float.MaxValue; 5757 return null;
5758
5759 List<ILandObject> all = LandChannel.AllParcels();
5760
5761 if(all == null || all.Count == 0)
5762 return null;
5763
5764 float minParcelDistanceSQ = float.MaxValue;
5610 ILandObject nearestParcel = null; 5765 ILandObject nearestParcel = null;
5766 Vector2 curCenter;
5767 float parcelDistanceSQ;
5611 5768
5612 foreach (var parcel in all) 5769 foreach (var parcel in all)
5613 { 5770 {
5614 if (!parcel.IsEitherBannedOrRestricted(avatarId) && parcel != excludeParcel) 5771 if (parcel != excludeParcel && !parcel.IsEitherBannedOrRestricted(avatarId))
5615 { 5772 {
5616 float parcelDistance = GetParcelDistancefromPoint(parcel, x, y); 5773 curCenter = parcel.CenterPoint;
5617 if (parcelDistance < minParcelDistance) 5774 curCenter.X -= x;
5775 curCenter.Y -= y;
5776 parcelDistanceSQ = curCenter.LengthSquared();
5777 if (parcelDistanceSQ < minParcelDistanceSQ)
5618 { 5778 {
5619 minParcelDistance = parcelDistance; 5779 minParcelDistanceSQ = parcelDistanceSQ;
5620 nearestParcel = parcel; 5780 nearestParcel = parcel;
5621 } 5781 }
5622 } 5782 }
@@ -5625,82 +5785,52 @@ namespace OpenSim.Region.Framework.Scenes
5625 return nearestParcel; 5785 return nearestParcel;
5626 } 5786 }
5627 5787
5628 private List<ILandObject> AllParcels() 5788 private Vector2 GetParcelSafeCorner(ILandObject parcel)
5629 {
5630 return LandChannel.AllParcels();
5631 }
5632
5633 private float GetParcelDistancefromPoint(ILandObject parcel, float x, float y)
5634 {
5635 return Vector2.Distance(new Vector2(x, y), GetParcelCenter(parcel));
5636 }
5637
5638 //calculate the average center point of a parcel
5639 private Vector2 GetParcelCenter(ILandObject parcel)
5640 { 5789 {
5641 int count = 0; 5790 Vector2 place = parcel.StartPoint;
5642 int avgx = 0; 5791 place.X += 2f;
5643 int avgy = 0; 5792 place.Y += 2f;
5644 for (int x = 0; x < RegionInfo.RegionSizeX; x++) 5793 return place;
5645 {
5646 for (int y = 0; y < RegionInfo.RegionSizeY; y++)
5647 {
5648 //Just keep a running average as we check if all the points are inside or not
5649 if (parcel.ContainsPoint(x, y))
5650 {
5651 if (count == 0)
5652 {
5653 avgx = x;
5654 avgy = y;
5655 }
5656 else
5657 {
5658 avgx = (avgx * count + x) / (count + 1);
5659 avgy = (avgy * count + y) / (count + 1);
5660 }
5661 count += 1;
5662 }
5663 }
5664 }
5665 return new Vector2(avgx, avgy);
5666 } 5794 }
5667 5795
5668 private Vector3 GetNearestRegionEdgePosition(ScenePresence avatar) 5796 private Vector3 GetNearestRegionEdgePosition(ScenePresence avatar)
5669 { 5797 {
5670 float xdistance = avatar.AbsolutePosition.X < RegionInfo.RegionSizeX / 2 5798 float posX = avatar.AbsolutePosition.X;
5671 ? avatar.AbsolutePosition.X : RegionInfo.RegionSizeX - avatar.AbsolutePosition.X; 5799 float posY = avatar.AbsolutePosition.Y;
5672 float ydistance = avatar.AbsolutePosition.Y < RegionInfo.RegionSizeY / 2 5800 float regionSizeX = RegionInfo.RegionSizeX;
5673 ? avatar.AbsolutePosition.Y : RegionInfo.RegionSizeY - avatar.AbsolutePosition.Y; 5801 float halfRegionSizeX = regionSizeX * 0.5f;
5802 float regionSizeY = RegionInfo.RegionSizeY;
5803 float halfRegionSizeY = regionSizeY * 0.5f;
5804
5805 float xdistance = posX < halfRegionSizeX ? posX : regionSizeX - posX;
5806 float ydistance = posY < halfRegionSizeY ? posY : regionSizeY - posY;
5674 5807
5675 //find out what vertical edge to go to 5808 //find out what vertical edge to go to
5676 if (xdistance < ydistance) 5809 if (xdistance < ydistance)
5677 { 5810 {
5678 if (avatar.AbsolutePosition.X < RegionInfo.RegionSizeX / 2) 5811 if (posX < halfRegionSizeX)
5679 { 5812 return GetPositionAtAvatarHeightOrGroundHeight(avatar, 0.5f, posY);
5680 return GetPositionAtAvatarHeightOrGroundHeight(avatar, 0.0f, avatar.AbsolutePosition.Y);
5681 }
5682 else 5813 else
5683 { 5814 return GetPositionAtAvatarHeightOrGroundHeight(avatar, regionSizeX - 0.5f, posY);
5684 return GetPositionAtAvatarHeightOrGroundHeight(avatar, RegionInfo.RegionSizeY, avatar.AbsolutePosition.Y);
5685 }
5686 } 5815 }
5687 //find out what horizontal edge to go to 5816 //find out what horizontal edge to go to
5688 else 5817 else
5689 { 5818 {
5690 if (avatar.AbsolutePosition.Y < RegionInfo.RegionSizeY / 2) 5819 if (posY < halfRegionSizeY)
5691 { 5820 return GetPositionAtAvatarHeightOrGroundHeight(avatar, posX, 0.5f);
5692 return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, 0.0f);
5693 }
5694 else 5821 else
5695 { 5822 return GetPositionAtAvatarHeightOrGroundHeight(avatar, posX, regionSizeY - 0.5f);
5696 return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, RegionInfo.RegionSizeY);
5697 }
5698 } 5823 }
5699 } 5824 }
5700 5825
5701 private Vector3 GetPositionAtAvatarHeightOrGroundHeight(ScenePresence avatar, float x, float y) 5826 private Vector3 GetPositionAtAvatarHeightOrGroundHeight(ScenePresence avatar, float x, float y)
5702 { 5827 {
5703 Vector3 ground = GetPositionAtGround(x, y); 5828 Vector3 ground = GetPositionAtGround(x, y);
5829 if(avatar.Appearance != null)
5830 ground.Z += avatar.Appearance.AvatarHeight * 0.5f;
5831 else
5832 ground.Z += 0.8f;
5833
5704 if (avatar.AbsolutePosition.Z > ground.Z) 5834 if (avatar.AbsolutePosition.Z > ground.Z)
5705 { 5835 {
5706 ground.Z = avatar.AbsolutePosition.Z; 5836 ground.Z = avatar.AbsolutePosition.Z;
@@ -5780,7 +5910,7 @@ namespace OpenSim.Region.Framework.Scenes
5780 g.GetAxisAlignedBoundingBoxRaw(out ominX, out omaxX, out ominY, out omaxY, out ominZ, out omaxZ); 5910 g.GetAxisAlignedBoundingBoxRaw(out ominX, out omaxX, out ominY, out omaxY, out ominZ, out omaxZ);
5781 5911
5782// m_log.DebugFormat( 5912// m_log.DebugFormat(
5783// "[SCENE]: For {0} found AxisAlignedBoundingBoxRaw {1}, {2}", 5913// "[SCENE]: For {0} found AxisAlignedBoundingBoxRaw {1}, {2}",
5784// g.Name, new Vector3(ominX, ominY, ominZ), new Vector3(omaxX, omaxY, omaxZ)); 5914// g.Name, new Vector3(ominX, ominY, ominZ), new Vector3(omaxX, omaxY, omaxZ));
5785 5915
5786 ominX += vec.X; 5916 ominX += vec.X;
@@ -5829,7 +5959,55 @@ namespace OpenSim.Region.Framework.Scenes
5829 mapModule.GenerateMaptile(); 5959 mapModule.GenerateMaptile();
5830 } 5960 }
5831 5961
5832 private void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e) 5962// public void CleanDroppedAttachments()
5963// {
5964// List<SceneObjectGroup> objectsToDelete =
5965// new List<SceneObjectGroup>();
5966//
5967// lock (m_cleaningAttachments)
5968// {
5969// ForEachSOG(delegate (SceneObjectGroup grp)
5970// {
5971// if (grp.RootPart.Shape.PCode == 0 && grp.RootPart.Shape.State != 0 && (!objectsToDelete.Contains(grp)))
5972// {
5973// UUID agentID = grp.OwnerID;
5974// if (agentID == UUID.Zero)
5975// {
5976// objectsToDelete.Add(grp);
5977// return;
5978// }
5979//
5980// ScenePresence sp = GetScenePresence(agentID);
5981// if (sp == null)
5982// {
5983// objectsToDelete.Add(grp);
5984// return;
5985// }
5986// }
5987// });
5988// }
5989//
5990// foreach (SceneObjectGroup grp in objectsToDelete)
5991// {
5992// m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID);
5993// DeleteSceneObject(grp, true);
5994// }
5995// }
5996
5997 public void ThreadAlive(int threadCode)
5998 {
5999 switch(threadCode)
6000 {
6001 case 1: // Incoming
6002 m_lastIncoming = Util.EnvironmentTickCount();
6003 break;
6004 case 2: // Incoming
6005 m_lastOutgoing = Util.EnvironmentTickCount();
6006 break;
6007 }
6008 }
6009
6010 public void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e)
5833 { 6011 {
5834 RegenerateMaptile(); 6012 RegenerateMaptile();
5835 6013
@@ -5861,13 +6039,16 @@ namespace OpenSim.Region.Framework.Scenes
5861 reason = string.Empty; 6039 reason = string.Empty;
5862 6040
5863 if (Permissions.IsGod(agentID)) 6041 if (Permissions.IsGod(agentID))
5864 {
5865 reason = String.Empty;
5866 return true; 6042 return true;
5867 }
5868 6043
5869 if (!AllowAvatarCrossing && !viaTeleport) 6044 if (!AllowAvatarCrossing && !viaTeleport)
6045 {
6046 reason = "Region Crossing not allowed";
5870 return false; 6047 return false;
6048 }
6049
6050 bool isAdmin = Permissions.IsAdministrator(agentID);
6051 bool isManager = Permissions.IsEstateManager(agentID);
5871 6052
5872 // FIXME: Root agent count is currently known to be inaccurate. This forces a recount before we check. 6053 // FIXME: Root agent count is currently known to be inaccurate. This forces a recount before we check.
5873 // However, the long term fix is to make sure root agent count is always accurate. 6054 // However, the long term fix is to make sure root agent count is always accurate.
@@ -5877,7 +6058,7 @@ namespace OpenSim.Region.Framework.Scenes
5877 6058
5878 if (num >= RegionInfo.RegionSettings.AgentLimit) 6059 if (num >= RegionInfo.RegionSettings.AgentLimit)
5879 { 6060 {
5880 if (!Permissions.IsAdministrator(agentID)) 6061 if (!(isAdmin || isManager))
5881 { 6062 {
5882 reason = "The region is full"; 6063 reason = "The region is full";
5883 6064
@@ -5915,6 +6096,7 @@ namespace OpenSim.Region.Framework.Scenes
5915 if (!AuthorizeUser(aCircuit, false, out reason)) 6096 if (!AuthorizeUser(aCircuit, false, out reason))
5916 { 6097 {
5917 //m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID); 6098 //m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
6099// reason = "Region authorization fail";
5918 return false; 6100 return false;
5919 } 6101 }
5920 } 6102 }
@@ -5925,52 +6107,101 @@ namespace OpenSim.Region.Framework.Scenes
5925 return false; 6107 return false;
5926 } 6108 }
5927 6109
5928 if (viaTeleport) 6110 // last check aditional land access restrictions and relocations
6111 // if crossing (viaTeleport false) check only the specified parcel
6112 return CheckLandPositionAccess(agentID, viaTeleport, true, position, out reason);
6113 }
6114
6115 // check access to land.
6116 public bool CheckLandPositionAccess(UUID agentID, bool NotCrossing, bool checkTeleHub, Vector3 position, out string reason)
6117 {
6118 reason = string.Empty;
6119
6120 if (Permissions.IsGod(agentID))
6121 return true;
6122
6123 // Permissions.IsAdministrator is the same as IsGod for now
6124// bool isAdmin = Permissions.IsAdministrator(agentID);
6125// if(isAdmin)
6126// return true;
6127
6128 // also honor estate managers access rights
6129 bool isManager = Permissions.IsEstateManager(agentID);
6130 if(isManager)
6131 return true;
6132
6133 if (NotCrossing)
5929 { 6134 {
5930 if (!RegionInfo.EstateSettings.AllowDirectTeleport) 6135 if (!RegionInfo.EstateSettings.AllowDirectTeleport)
5931 { 6136 {
5932 SceneObjectGroup telehub; 6137 SceneObjectGroup telehub;
5933 if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject)) != null) 6138 if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = GetSceneObjectGroup (RegionInfo.RegionSettings.TelehubObject)) != null && checkTeleHub)
5934 { 6139 {
5935 List<SpawnPoint> spawnPoints = RegionInfo.RegionSettings.SpawnPoints();
5936 bool banned = true; 6140 bool banned = true;
5937 foreach (SpawnPoint sp in spawnPoints) 6141 bool validTelehub = false;
6142 List<SpawnPoint> spawnPoints = RegionInfo.RegionSettings.SpawnPoints();
6143 Vector3 spawnPoint;
6144 ILandObject land = null;
6145 Vector3 telehubPosition = telehub.AbsolutePosition;
6146
6147 if(spawnPoints.Count == 0)
5938 { 6148 {
5939 Vector3 spawnPoint = sp.GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); 6149 // will this ever happen?
5940 ILandObject land = LandChannel.GetLandObject(spawnPoint.X, spawnPoint.Y); 6150 // if so use the telehub object position
5941 if (land == null) 6151 spawnPoint = telehubPosition;
5942 continue; 6152 land = LandChannel.GetLandObject(spawnPoint.X, spawnPoint.Y);
5943 if (land.IsEitherBannedOrRestricted(agentID)) 6153 if(land != null && !land.IsEitherBannedOrRestricted(agentID))
5944 continue; 6154 {
5945 banned = false; 6155 banned = false;
5946 break; 6156 validTelehub = true;
6157 }
6158 }
6159 else
6160 {
6161 Quaternion telehubRotation = telehub.GroupRotation;
6162 foreach (SpawnPoint spawn in spawnPoints)
6163 {
6164 spawnPoint = spawn.GetLocation(telehubPosition, telehubRotation);
6165 land = LandChannel.GetLandObject(spawnPoint.X, spawnPoint.Y);
6166 if (land == null)
6167 continue;
6168 validTelehub = true;
6169 if (!land.IsEitherBannedOrRestricted(agentID))
6170 {
6171 banned = false;
6172 break;
6173 }
6174 }
5947 } 6175 }
5948 6176
5949 if (banned) 6177 if(validTelehub)
5950 { 6178 {
5951 if (Permissions.IsAdministrator(agentID) == false || Permissions.IsGridGod(agentID) == false) 6179 if (banned)
5952 { 6180 {
5953 reason = "No suitable landing point found"; 6181 reason = "No suitable landing point found";
5954 return false; 6182 return false;
5955 } 6183 }
5956 reason = "Administrative access only"; 6184 else
5957 return true; 6185 return true;
5958 } 6186 }
6187 // possible broken telehub, fall into normal check
5959 } 6188 }
5960 } 6189 }
5961 6190
5962 float posX = 128.0f; 6191 float posX = position.X;
5963 float posY = 128.0f; 6192 float posY = position.Y;
5964 6193
6194 // allow position relocation
5965 if (!TestLandRestrictions(agentID, out reason, ref posX, ref posY)) 6195 if (!TestLandRestrictions(agentID, out reason, ref posX, ref posY))
5966 { 6196 {
5967 // m_log.DebugFormat("[SCENE]: Denying {0} because they are banned on all parcels", agentID); 6197 // m_log.DebugFormat("[SCENE]: Denying {0} because they are banned on all parcels", agentID);
5968 reason = "You are banned from the region on all parcels"; 6198 reason = "You dont have access to the region parcels";
5969 return false; 6199 return false;
5970 } 6200 }
5971 } 6201 }
5972 else // Walking 6202 else // check for query region crossing only
5973 { 6203 {
6204 // no relocation allowed on crossings
5974 ILandObject land = LandChannel.GetLandObject(position.X, position.Y); 6205 ILandObject land = LandChannel.GetLandObject(position.X, position.Y);
5975 if (land == null) 6206 if (land == null)
5976 { 6207 {
@@ -5991,11 +6222,48 @@ namespace OpenSim.Region.Framework.Scenes
5991 } 6222 }
5992 } 6223 }
5993 6224
5994 reason = String.Empty;
5995 return true; 6225 return true;
5996 } 6226 }
5997 6227
5998 /// <summary> 6228 public void StartTimerWatchdog()
6229 {
6230 m_timerWatchdog.Interval = 1000;
6231 m_timerWatchdog.Elapsed += TimerWatchdog;
6232 m_timerWatchdog.AutoReset = true;
6233 m_timerWatchdog.Start();
6234 }
6235
6236 public void TimerWatchdog(object sender, ElapsedEventArgs e)
6237 {
6238 CheckHeartbeat();
6239
6240 IEtcdModule etcd = RequestModuleInterface<IEtcdModule>();
6241 int flags;
6242 string message;
6243 if (etcd != null)
6244 {
6245 int health = GetHealth(out flags, out message);
6246 if (health != m_lastHealth)
6247 {
6248 m_lastHealth = health;
6249
6250 etcd.Store("Health", health.ToString(), 300000);
6251 etcd.Store("HealthFlags", flags.ToString(), 300000);
6252 }
6253
6254 int roots = 0;
6255 foreach (ScenePresence sp in GetScenePresences())
6256 if (!sp.IsChildAgent && !sp.IsNPC)
6257 roots++;
6258
6259 if (m_lastUsers != roots)
6260 {
6261 m_lastUsers = roots;
6262 etcd.Store("RootAgents", roots.ToString(), 300000);
6263 }
6264 }
6265 }
6266
5999 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the 6267 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the
6000 /// autopilot that moves an avatar to a sit target!. 6268 /// autopilot that moves an avatar to a sit target!.
6001 /// </summary> 6269 /// </summary>
@@ -6003,6 +6271,7 @@ namespace OpenSim.Region.Framework.Scenes
6003 /// This is not intended as a permament location for this method. 6271 /// This is not intended as a permament location for this method.
6004 /// </remarks> 6272 /// </remarks>
6005 /// <param name="presence"></param> 6273 /// <param name="presence"></param>
6274/* move to target is now done on presence update
6006 private void HandleOnSignificantClientMovement(ScenePresence presence) 6275 private void HandleOnSignificantClientMovement(ScenePresence presence)
6007 { 6276 {
6008 if (presence.MovingToTarget) 6277 if (presence.MovingToTarget)
@@ -6059,7 +6328,7 @@ namespace OpenSim.Region.Framework.Scenes
6059 } 6328 }
6060 } 6329 }
6061 } 6330 }
6062 6331*/
6063 // manage and select spawn points in sequence 6332 // manage and select spawn points in sequence
6064 public int SpawnPoint() 6333 public int SpawnPoint()
6065 { 6334 {
@@ -6074,8 +6343,13 @@ namespace OpenSim.Region.Framework.Scenes
6074 return m_SpawnPoint - 1; 6343 return m_SpawnPoint - 1;
6075 } 6344 }
6076 6345
6346 private void HandleGcCollect(string module, string[] args)
6347 {
6348 GC.Collect();
6349 }
6350
6077 /// <summary> 6351 /// <summary>
6078 /// Wrappers to get physics modules retrieve assets. 6352 /// Wrappers to get physics modules retrieve assets.
6079 /// </summary> 6353 /// </summary>
6080 /// <remarks> 6354 /// <remarks>
6081 /// Has to be done this way 6355 /// Has to be done this way
@@ -6144,5 +6418,21 @@ namespace OpenSim.Region.Framework.Scenes
6144 6418
6145 m_eventManager.TriggerExtraSettingChanged(this, name, String.Empty); 6419 m_eventManager.TriggerExtraSettingChanged(this, name, String.Empty);
6146 } 6420 }
6421
6422 public bool InTeleportTargetsCoolDown(UUID sourceID, UUID targetID, double timeout)
6423 {
6424 lock(TeleportTargetsCoolDown)
6425 {
6426 UUID lastSource = UUID.Zero;
6427 TeleportTargetsCoolDown.TryGetValue(targetID, out lastSource);
6428 if(lastSource == UUID.Zero)
6429 {
6430 TeleportTargetsCoolDown.Add(targetID, sourceID, timeout);
6431 return false;
6432 }
6433 TeleportTargetsCoolDown.AddOrUpdate(targetID, sourceID, timeout);
6434 return lastSource == sourceID;
6435 }
6436 }
6147 } 6437 }
6148} 6438}
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index 7ff3d40..e3e54e2 100644
--- a/OpenSim/Region/Framework/Scenes/SceneBase.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -57,7 +57,7 @@ namespace OpenSim.Region.Framework.Scenes
57 #region Fields 57 #region Fields
58 58
59 public string Name { get { return RegionInfo.RegionName; } } 59 public string Name { get { return RegionInfo.RegionName; } }
60 60
61 public IConfigSource Config 61 public IConfigSource Config
62 { 62 {
63 get { return GetConfig(); } 63 get { return GetConfig(); }
@@ -95,7 +95,7 @@ namespace OpenSim.Region.Framework.Scenes
95 /// The module commanders available from this scene 95 /// The module commanders available from this scene
96 /// </value> 96 /// </value>
97 protected Dictionary<string, ICommander> m_moduleCommanders = new Dictionary<string, ICommander>(); 97 protected Dictionary<string, ICommander> m_moduleCommanders = new Dictionary<string, ICommander>();
98 98
99 /// <value> 99 /// <value>
100 /// Registered classes that are capable of creating entities. 100 /// Registered classes that are capable of creating entities.
101 /// </value> 101 /// </value>
@@ -108,7 +108,7 @@ namespace OpenSim.Region.Framework.Scenes
108 protected uint m_lastAllocatedLocalId = 720000; 108 protected uint m_lastAllocatedLocalId = 720000;
109 109
110 private readonly Mutex _primAllocateMutex = new Mutex(false); 110 private readonly Mutex _primAllocateMutex = new Mutex(false);
111 111
112 protected readonly ClientManager m_clientManager = new ClientManager(); 112 protected readonly ClientManager m_clientManager = new ClientManager();
113 113
114 public bool LoginsEnabled 114 public bool LoginsEnabled
@@ -153,6 +153,7 @@ namespace OpenSim.Region.Framework.Scenes
153 } 153 }
154 154
155 public ITerrainChannel Heightmap; 155 public ITerrainChannel Heightmap;
156 public ITerrainChannel Bakedmap;
156 157
157 /// <value> 158 /// <value>
158 /// Allows retrieval of land information for this scene. 159 /// Allows retrieval of land information for this scene.
@@ -200,7 +201,7 @@ namespace OpenSim.Region.Framework.Scenes
200 /// If -1 then updates until shutdown. 201 /// If -1 then updates until shutdown.
201 /// </param> 202 /// </param>
202 /// <returns>true if update completed within minimum frame time, false otherwise.</returns> 203 /// <returns>true if update completed within minimum frame time, false otherwise.</returns>
203 public abstract bool Update(int frames); 204 public abstract void Update(int frames);
204 205
205 #endregion 206 #endregion
206 207
@@ -263,7 +264,7 @@ namespace OpenSim.Region.Framework.Scenes
263 public virtual RegionInfo RegionInfo { get; private set; } 264 public virtual RegionInfo RegionInfo { get; private set; }
264 265
265 #region admin stuff 266 #region admin stuff
266 267
267 public abstract void OtherRegionUp(GridRegion otherRegion); 268 public abstract void OtherRegionUp(GridRegion otherRegion);
268 269
269 public virtual string GetSimulatorVersion() 270 public virtual string GetSimulatorVersion()
@@ -286,7 +287,7 @@ namespace OpenSim.Region.Framework.Scenes
286 } 287 }
287 catch (Exception e) 288 catch (Exception e)
288 { 289 {
289 m_log.Error(string.Format("[SCENE]: SceneBase.cs: Close() - Failed with exception ", e)); 290 m_log.Error(string.Format("[SCENE]: SceneBase.cs: Close() - Failed with exception {0}", e));
290 } 291 }
291 } 292 }
292 293
@@ -306,7 +307,7 @@ namespace OpenSim.Region.Framework.Scenes
306 307
307 return myID; 308 return myID;
308 } 309 }
309 310
310 #region Module Methods 311 #region Module Methods
311 312
312 /// <summary> 313 /// <summary>
@@ -365,7 +366,7 @@ namespace OpenSim.Region.Framework.Scenes
365 if (m_moduleCommanders.ContainsKey(name)) 366 if (m_moduleCommanders.ContainsKey(name))
366 return m_moduleCommanders[name]; 367 return m_moduleCommanders[name];
367 } 368 }
368 369
369 return null; 370 return null;
370 } 371 }
371 372
@@ -415,7 +416,7 @@ namespace OpenSim.Region.Framework.Scenes
415 public void RegisterModuleInterface<M>(M mod) 416 public void RegisterModuleInterface<M>(M mod)
416 { 417 {
417// m_log.DebugFormat("[SCENE BASE]: Registering interface {0}", typeof(M)); 418// m_log.DebugFormat("[SCENE BASE]: Registering interface {0}", typeof(M));
418 419
419 List<Object> l = null; 420 List<Object> l = null;
420 if (!ModuleInterfaces.TryGetValue(typeof(M), out l)) 421 if (!ModuleInterfaces.TryGetValue(typeof(M), out l))
421 { 422 {
@@ -526,9 +527,9 @@ namespace OpenSim.Region.Framework.Scenes
526 return new T[] {}; 527 return new T[] {};
527 } 528 }
528 } 529 }
529 530
530 #endregion 531 #endregion
531 532
532 /// <summary> 533 /// <summary>
533 /// Call this from a region module to add a command to the OpenSim console. 534 /// Call this from a region module to add a command to the OpenSim console.
534 /// </summary> 535 /// </summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index b9526da..6304778 100644
--- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
@@ -66,7 +66,7 @@ namespace OpenSim.Region.Framework.Scenes
66 66
67 private void InformNeighborsThatRegionisUpCompleted(IAsyncResult iar) 67 private void InformNeighborsThatRegionisUpCompleted(IAsyncResult iar)
68 { 68 {
69 InformNeighbourThatRegionUpDelegate icon = (InformNeighbourThatRegionUpDelegate) iar.AsyncState; 69 InformNeighbourThatRegionUpDelegate icon = (InformNeighbourThatRegionUpDelegate)iar.AsyncState;
70 icon.EndInvoke(iar); 70 icon.EndInvoke(iar);
71 } 71 }
72 72
@@ -84,11 +84,11 @@ namespace OpenSim.Region.Framework.Scenes
84 if (neighbourService != null) 84 if (neighbourService != null)
85 neighbour = neighbourService.HelloNeighbour(regionhandle, region); 85 neighbour = neighbourService.HelloNeighbour(regionhandle, region);
86 else 86 else
87 m_log.DebugFormat( "{0} neighbour service provided for region {0} to inform neigbhours of status", LogHeader, m_scene.Name); 87 m_log.DebugFormat("{0} neighbour service provided for region {0} to inform neigbhours of status", LogHeader, m_scene.Name);
88 88
89 if (neighbour != null) 89 if (neighbour != null)
90 { 90 {
91 m_log.DebugFormat( "{0} Region {1} successfully informed neighbour {2} at {3}-{4} that it is up", 91 m_log.DebugFormat("{0} Region {1} successfully informed neighbour {2} at {3}-{4} that it is up",
92 LogHeader, m_scene.Name, neighbour.RegionName, Util.WorldToRegionLoc(x), Util.WorldToRegionLoc(y)); 92 LogHeader, m_scene.Name, neighbour.RegionName, Util.WorldToRegionLoc(x), Util.WorldToRegionLoc(y));
93 93
94 m_scene.EventManager.TriggerOnRegionUp(neighbour); 94 m_scene.EventManager.TriggerOnRegionUp(neighbour);
@@ -114,9 +114,9 @@ namespace OpenSim.Region.Framework.Scenes
114 { 114 {
115 OpenSim.Framework.RegionFlags? regionFlags = n.RegionFlags; 115 OpenSim.Framework.RegionFlags? regionFlags = n.RegionFlags;
116 116
117// m_log.DebugFormat( 117 // m_log.DebugFormat(
118// "{0}: Region flags for {1} as seen by {2} are {3}", 118 // "{0}: Region flags for {1} as seen by {2} are {3}",
119// LogHeader, n.RegionName, m_scene.Name, regionFlags != null ? regionFlags.ToString() : "not present"); 119 // LogHeader, n.RegionName, m_scene.Name, regionFlags != null ? regionFlags.ToString() : "not present");
120 120
121 // Robust services before 2015-01-14 do not return the regionFlags information. In this case, we could 121 // Robust services before 2015-01-14 do not return the regionFlags information. In this case, we could
122 // make a separate RegionFlags call but this would involve a network call for each neighbour. 122 // make a separate RegionFlags call but this would involve a network call for each neighbour.
@@ -132,7 +132,7 @@ namespace OpenSim.Region.Framework.Scenes
132 } 132 }
133 133
134 m_log.DebugFormat( 134 m_log.DebugFormat(
135 "{0} Informing {1} neighbours that region {2} is up", 135 "{0} Informing {1} neighbours that region {2} is up",
136 LogHeader, onlineNeighbours.Count, m_scene.Name); 136 LogHeader, onlineNeighbours.Count, m_scene.Name);
137 137
138 foreach (GridRegion n in onlineNeighbours) 138 foreach (GridRegion n in onlineNeighbours)
@@ -168,15 +168,15 @@ namespace OpenSim.Region.Framework.Scenes
168 168
169 private void SendChildAgentDataUpdateCompleted(IAsyncResult iar) 169 private void SendChildAgentDataUpdateCompleted(IAsyncResult iar)
170 { 170 {
171 SendChildAgentDataUpdateDelegate icon = (SendChildAgentDataUpdateDelegate) iar.AsyncState; 171 SendChildAgentDataUpdateDelegate icon = (SendChildAgentDataUpdateDelegate)iar.AsyncState;
172 icon.EndInvoke(iar); 172 icon.EndInvoke(iar);
173 } 173 }
174 174
175 public void SendChildAgentDataUpdate(AgentPosition cAgentData, ScenePresence presence) 175 public void SendChildAgentDataUpdate(AgentPosition cAgentData, ScenePresence presence)
176 { 176 {
177// m_log.DebugFormat( 177 // m_log.DebugFormat(
178// "[SCENE COMMUNICATION SERVICE]: Sending child agent position updates for {0} in {1}", 178 // "[SCENE COMMUNICATION SERVICE]: Sending child agent position updates for {0} in {1}",
179// presence.Name, m_scene.Name); 179 // presence.Name, m_scene.Name);
180 180
181 // This assumes that we know what our neighbors are. 181 // This assumes that we know what our neighbors are.
182 try 182 try
@@ -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 {
@@ -231,6 +234,13 @@ namespace OpenSim.Region.Framework.Scenes
231 234
232 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y); 235 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y);
233 236
237 if (destination == null)
238 {
239 m_log.DebugFormat(
240 "[SCENE COMMUNICATION SERVICE]: Sending close agent ID {0} FAIL, region with handle {1} not found", agentID, regionHandle);
241 return;
242 }
243
234 m_log.DebugFormat( 244 m_log.DebugFormat(
235 "[SCENE COMMUNICATION SERVICE]: Sending close agent ID {0} to {1}", agentID, destination.RegionName); 245 "[SCENE COMMUNICATION SERVICE]: Sending close agent ID {0} to {1}", agentID, destination.RegionName);
236 246
@@ -238,28 +248,29 @@ namespace OpenSim.Region.Framework.Scenes
238 } 248 }
239 249
240 /// <summary> 250 /// <summary>
241 /// Closes a child agents in a collection of regions. Does so asynchronously 251 /// Closes a child agents in a collection of regions. Does so asynchronously
242 /// so that the caller doesn't wait. 252 /// so that the caller doesn't wait.
243 /// </summary> 253 /// </summary>
244 /// <param name="agentID"></param> 254 /// <param name="agentID"></param>
245 /// <param name="regionslst"></param> 255 /// <param name="regionslst"></param>
246 public void SendCloseChildAgentConnections(UUID agentID, string auth_code, List<ulong> regionslst) 256 public void SendCloseChildAgentConnections(UUID agentID, string auth_code, List<ulong> regionslst)
247 { 257 {
248 foreach (ulong handle in regionslst) 258 if (regionslst.Count == 0)
259 return;
260
261 // use a single thread job for all
262 Util.FireAndForget(o =>
249 { 263 {
250 // We must take a copy here since handle is acts like a reference when used in an iterator. 264 foreach (ulong handle in regionslst)
251 // This leads to race conditions if directly passed to SendCloseChildAgent with more than one neighbour region. 265 {
252 ulong handleCopy = handle; 266 SendCloseChildAgent(agentID, handle, auth_code);
253 Util.FireAndForget( 267 }
254 o => SendCloseChildAgent(agentID, handleCopy, auth_code), 268 }, null, "SceneCommunicationService.SendCloseChildAgentConnections");
255 null,
256 "SceneCommunicationService.SendCloseChildAgentConnections");
257 }
258 } 269 }
259 270
260 public List<GridRegion> RequestNamedRegions(string name, int maxNumber) 271 public List<GridRegion> RequestNamedRegions(string name, int maxNumber)
261 { 272 {
262 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber); 273 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber);
263 } 274 }
264 } 275 }
265} \ No newline at end of file 276}
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index e0080f2..61a243d 100644..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
@@ -77,21 +87,21 @@ namespace OpenSim.Region.Framework.Scenes
77 protected int m_scriptLPS = 0; 87 protected int m_scriptLPS = 0;
78 88
79 protected internal PhysicsScene _PhyScene; 89 protected internal PhysicsScene _PhyScene;
80 90
81 /// <summary> 91 /// <summary>
82 /// Index the SceneObjectGroup for each part by the root part's UUID. 92 /// Index the SceneObjectGroup for each part by the root part's UUID.
83 /// </summary> 93 /// </summary>
84 protected internal Dictionary<UUID, SceneObjectGroup> SceneObjectGroupsByFullID = new Dictionary<UUID, SceneObjectGroup>(); 94 protected internal Dictionary<UUID, SceneObjectGroup> SceneObjectGroupsByFullID = new Dictionary<UUID, SceneObjectGroup>();
85 95
86 /// <summary> 96 /// <summary>
87 /// Index the SceneObjectGroup for each part by that part's UUID. 97 /// Index the SceneObjectGroup for each part by that part's UUID.
88 /// </summary> 98 /// </summary>
89 protected internal Dictionary<UUID, SceneObjectGroup> SceneObjectGroupsByFullPartID = new Dictionary<UUID, SceneObjectGroup>(); 99 protected internal Dictionary<UUID, SceneObjectGroup> SceneObjectGroupsByFullPartID = new Dictionary<UUID, SceneObjectGroup>();
90 100
91 /// <summary> 101 /// <summary>
92 /// Index the SceneObjectGroup for each part by that part's local ID. 102 /// Index the SceneObjectGroup for each part by that part's local ID.
93 /// </summary> 103 /// </summary>
94 protected internal Dictionary<uint, SceneObjectGroup> SceneObjectGroupsByLocalPartID = new Dictionary<uint, SceneObjectGroup>(); 104 protected internal Dictionary<uint, SceneObjectGroup> SceneObjectGroupsByLocalPartID = new Dictionary<uint, SceneObjectGroup>();
95 105
96 /// <summary> 106 /// <summary>
97 /// Lock to prevent object group update, linking, delinking and duplication operations from running concurrently. 107 /// Lock to prevent object group update, linking, delinking and duplication operations from running concurrently.
@@ -111,11 +121,11 @@ namespace OpenSim.Region.Framework.Scenes
111 121
112 public PhysicsScene PhysicsScene 122 public PhysicsScene PhysicsScene
113 { 123 {
114 get 124 get
115 { 125 {
116 if (_PhyScene == null) 126 if (_PhyScene == null)
117 _PhyScene = m_parentScene.RequestModuleInterface<PhysicsScene>(); 127 _PhyScene = m_parentScene.RequestModuleInterface<PhysicsScene>();
118 return _PhyScene; 128 return _PhyScene;
119 } 129 }
120 set 130 set
121 { 131 {
@@ -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();
@@ -200,13 +215,20 @@ namespace OpenSim.Region.Framework.Scenes
200 // the joint in the Scene does not exist in the PhysicsScene. 215 // the joint in the Scene does not exist in the PhysicsScene.
201 // 216 //
202 // To solve this, we have an event in the PhysicsScene that is fired when a joint 217 // To solve this, we have an event in the PhysicsScene that is fired when a joint
203 // has changed position (because one of its associated PhysicsActors has changed 218 // has changed position (because one of its associated PhysicsActors has changed
204 // position). 219 // position).
205 // 220 //
206 // Therefore, JointMoved and JointDeactivated events will be fired as a result of the following Simulate(). 221 // Therefore, JointMoved and JointDeactivated events will be fired as a result of the following Simulate().
222
207 return PhysicsScene.Simulate((float)elapsed); 223 return PhysicsScene.Simulate((float)elapsed);
208 } 224 }
209 225
226 protected internal void ProcessPhysicsPreSimulation()
227 {
228 if(PhysicsScene != null)
229 PhysicsScene.ProcessPreSimulation();
230 }
231
210 protected internal void UpdateScenePresenceMovement() 232 protected internal void UpdateScenePresenceMovement()
211 { 233 {
212 ForEachScenePresence(delegate(ScenePresence presence) 234 ForEachScenePresence(delegate(ScenePresence presence)
@@ -220,17 +242,32 @@ namespace OpenSim.Region.Framework.Scenes
220 coarseLocations = new List<Vector3>(); 242 coarseLocations = new List<Vector3>();
221 avatarUUIDs = new List<UUID>(); 243 avatarUUIDs = new List<UUID>();
222 244
245 // coarse locations are sent as BYTE, so limited to the 255m max of normal regions
246 // try to work around that scale down X and Y acording to region size, so reducing the resolution
247 //
248 // viewers need to scale up
249 float scaleX = (float)m_parentScene.RegionInfo.RegionSizeX / (float)Constants.RegionSize;
250 if (scaleX == 0)
251 scaleX = 1.0f;
252 scaleX = 1.0f / scaleX;
253 float scaleY = (float)m_parentScene.RegionInfo.RegionSizeY / (float)Constants.RegionSize;
254 if (scaleY == 0)
255 scaleY = 1.0f;
256 scaleY = 1.0f / scaleY;
257
223 List<ScenePresence> presences = GetScenePresences(); 258 List<ScenePresence> presences = GetScenePresences();
224 for (int i = 0; i < Math.Min(presences.Count, maxLocations); ++i) 259 for (int i = 0; i < Math.Min(presences.Count, maxLocations); ++i)
225 { 260 {
226 ScenePresence sp = presences[i]; 261 ScenePresence sp = presences[i];
227 262
228 // If this presence is a child agent, we don't want its coarse locations 263 // If this presence is a child agent, we don't want its coarse locations
229 if (sp.IsChildAgent) 264 if (sp.IsChildAgent)
230 continue; 265 continue;
266 Vector3 pos = sp.AbsolutePosition;
267 pos.X *= scaleX;
268 pos.Y *= scaleY;
231 269
232 coarseLocations.Add(sp.AbsolutePosition); 270 coarseLocations.Add(pos);
233
234 avatarUUIDs.Add(sp.UUID); 271 avatarUUIDs.Add(sp.UUID);
235 } 272 }
236 } 273 }
@@ -261,15 +298,55 @@ namespace OpenSim.Region.Framework.Scenes
261 protected internal bool AddRestoredSceneObject( 298 protected internal bool AddRestoredSceneObject(
262 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 299 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
263 { 300 {
301 // temporary checks to remove after varsize suport
302 float regionSizeX = m_parentScene.RegionInfo.RegionSizeX;
303 if (regionSizeX == 0)
304 regionSizeX = Constants.RegionSize;
305 float regionSizeY = m_parentScene.RegionInfo.RegionSizeY;
306 if (regionSizeY == 0)
307 regionSizeY = Constants.RegionSize;
308
309 // KF: Check for out-of-region, move inside and make static.
310 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
311 sceneObject.RootPart.GroupPosition.Y,
312 sceneObject.RootPart.GroupPosition.Z);
313 bool clampZ = m_parentScene.ClampNegativeZ;
314
315 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 && clampZ) ||
316 npos.X > regionSizeX ||
317 npos.Y > regionSizeY))
318 {
319 if (npos.X < 0.0) npos.X = 1.0f;
320 if (npos.Y < 0.0) npos.Y = 1.0f;
321 if (npos.Z < 0.0 && clampZ) npos.Z = 0.0f;
322 if (npos.X > regionSizeX) npos.X = regionSizeX - 1.0f;
323 if (npos.Y > regionSizeY) npos.Y = regionSizeY - 1.0f;
324
325 SceneObjectPart rootpart = sceneObject.RootPart;
326 rootpart.GroupPosition = npos;
327
328 foreach (SceneObjectPart part in sceneObject.Parts)
329 {
330 if (part == rootpart)
331 continue;
332 part.GroupPosition = npos;
333 }
334 rootpart.Velocity = Vector3.Zero;
335 rootpart.AngularVelocity = Vector3.Zero;
336 rootpart.Acceleration = Vector3.Zero;
337 }
338
339 bool ret = AddSceneObject(sceneObject, attachToBackup, sendClientUpdates);
340
264 if (attachToBackup && (!alreadyPersisted)) 341 if (attachToBackup && (!alreadyPersisted))
265 { 342 {
266 sceneObject.ForceInventoryPersistence(); 343 sceneObject.ForceInventoryPersistence();
267 sceneObject.HasGroupChanged = true; 344 sceneObject.HasGroupChanged = true;
268 } 345 }
269 346 sceneObject.InvalidateDeepEffectivePerms();
270 return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); 347 return ret;
271 } 348 }
272 349
273 /// <summary> 350 /// <summary>
274 /// Add a newly created object to the scene. This will both update the scene, and send information about the 351 /// Add a newly created object to the scene. This will both update the scene, and send information about the
275 /// new object to all clients interested in the scene. 352 /// new object to all clients interested in the scene.
@@ -284,18 +361,22 @@ namespace OpenSim.Region.Framework.Scenes
284 /// </returns> 361 /// </returns>
285 protected internal bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 362 protected internal bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
286 { 363 {
287 // Ensure that we persist this new scene object if it's not an 364
365 bool ret = AddSceneObject(sceneObject, attachToBackup, sendClientUpdates);
366
367 // Ensure that we persist this new scene object if it's not an
288 // attachment 368 // attachment
369
289 if (attachToBackup) 370 if (attachToBackup)
290 sceneObject.HasGroupChanged = true; 371 sceneObject.HasGroupChanged = true;
291 372
292 return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); 373 return ret;
293 } 374 }
294 375
295 /// <summary> 376 /// <summary>
296 /// Add a newly created object to the scene. 377 /// Add a newly created object to the scene.
297 /// </summary> 378 /// </summary>
298 /// 379 ///
299 /// This method does not send updates to the client - callers need to handle this themselves. 380 /// This method does not send updates to the client - callers need to handle this themselves.
300 /// Caller should also trigger EventManager.TriggerObjectAddedToScene 381 /// Caller should also trigger EventManager.TriggerObjectAddedToScene
301 /// <param name="sceneObject"></param> 382 /// <param name="sceneObject"></param>
@@ -307,26 +388,25 @@ namespace OpenSim.Region.Framework.Scenes
307 public bool AddNewSceneObject( 388 public bool AddNewSceneObject(
308 SceneObjectGroup sceneObject, bool attachToBackup, Vector3? pos, Quaternion? rot, Vector3 vel) 389 SceneObjectGroup sceneObject, bool attachToBackup, Vector3? pos, Quaternion? rot, Vector3 vel)
309 { 390 {
310 AddNewSceneObject(sceneObject, attachToBackup, false);
311
312 if (pos != null) 391 if (pos != null)
313 sceneObject.AbsolutePosition = (Vector3)pos; 392 sceneObject.AbsolutePosition = (Vector3)pos;
314 393
394 if (rot != null)
395 sceneObject.UpdateGroupRotationR((Quaternion)rot);
396
397 AddNewSceneObject(sceneObject, attachToBackup, false);
398
315 if (sceneObject.RootPart.Shape.PCode == (byte)PCode.Prim) 399 if (sceneObject.RootPart.Shape.PCode == (byte)PCode.Prim)
316 { 400 {
317 sceneObject.ClearPartAttachmentData(); 401 sceneObject.ClearPartAttachmentData();
318 } 402 }
319 403
320 if (rot != null)
321 sceneObject.UpdateGroupRotationR((Quaternion)rot);
322
323 PhysicsActor pa = sceneObject.RootPart.PhysActor; 404 PhysicsActor pa = sceneObject.RootPart.PhysActor;
324 if (pa != null && pa.IsPhysical && vel != Vector3.Zero) 405 if (pa != null && pa.IsPhysical && vel != Vector3.Zero)
325 { 406 {
326 sceneObject.RootPart.ApplyImpulse((vel * sceneObject.GetMass()), false); 407 sceneObject.RootPart.ApplyImpulse((vel * sceneObject.GetMass()), false);
327 sceneObject.Velocity = vel;
328 } 408 }
329 409
330 return true; 410 return true;
331 } 411 }
332 412
@@ -351,6 +431,11 @@ namespace OpenSim.Region.Framework.Scenes
351 /// </returns> 431 /// </returns>
352 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 432 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
353 { 433 {
434 if (sceneObject == null)
435 {
436 m_log.ErrorFormat("[SCENEGRAPH]: Tried to add null scene object");
437 return false;
438 }
354 if (sceneObject.UUID == UUID.Zero) 439 if (sceneObject.UUID == UUID.Zero)
355 { 440 {
356 m_log.ErrorFormat( 441 m_log.ErrorFormat(
@@ -383,9 +468,9 @@ namespace OpenSim.Region.Framework.Scenes
383 { 468 {
384 Vector3 scale = part.Shape.Scale; 469 Vector3 scale = part.Shape.Scale;
385 470
386 scale.X = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.X)); 471 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)); 472 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)); 473 scale.Z = Util.Clamp(scale.Z, m_parentScene.m_minNonphys, m_parentScene.m_maxNonphys);
389 474
390 part.Shape.Scale = scale; 475 part.Shape.Scale = scale;
391 } 476 }
@@ -406,36 +491,39 @@ namespace OpenSim.Region.Framework.Scenes
406 491
407 sceneObject.AttachToScene(m_parentScene); 492 sceneObject.AttachToScene(m_parentScene);
408 493
409 if (sendClientUpdates)
410 sceneObject.ScheduleGroupForFullUpdate();
411
412 Entities.Add(sceneObject); 494 Entities.Add(sceneObject);
413 495
414 if (attachToBackup)
415 sceneObject.AttachToBackup();
416
417 lock (SceneObjectGroupsByFullID) 496 lock (SceneObjectGroupsByFullID)
418 SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject; 497 SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject;
419 498
420 lock (SceneObjectGroupsByFullPartID) 499 foreach (SceneObjectPart part in parts)
421 { 500 {
422 foreach (SceneObjectPart part in parts) 501 lock (SceneObjectGroupsByFullPartID)
423 SceneObjectGroupsByFullPartID[part.UUID] = sceneObject; 502 SceneObjectGroupsByFullPartID[part.UUID] = sceneObject;
424 }
425 503
426 lock (SceneObjectGroupsByLocalPartID) 504 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; 505 SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject;
434 } 506 }
435 507
508 if (sendClientUpdates)
509 sceneObject.ScheduleGroupForFullUpdate();
510
511 if (attachToBackup)
512 sceneObject.AttachToBackup();
513
436 return true; 514 return true;
437 } 515 }
438 516
517 public void updateScenePartGroup(SceneObjectPart part, SceneObjectGroup grp)
518 {
519 // no tests, caller has responsability...
520 lock (SceneObjectGroupsByFullPartID)
521 SceneObjectGroupsByFullPartID[part.UUID] = grp;
522
523 lock (SceneObjectGroupsByLocalPartID)
524 SceneObjectGroupsByLocalPartID[part.LocalId] = grp;
525 }
526
439 /// <summary> 527 /// <summary>
440 /// Delete an object from the scene 528 /// Delete an object from the scene
441 /// </summary> 529 /// </summary>
@@ -461,6 +549,8 @@ namespace OpenSim.Region.Framework.Scenes
461 // that are part of the Scene Object being removed 549 // that are part of the Scene Object being removed
462 m_numTotalPrim -= grp.PrimCount; 550 m_numTotalPrim -= grp.PrimCount;
463 551
552 bool isPh = (grp.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics;
553 int nphysparts = 0;
464 // Go through all parts (primitives and meshes) of this Scene Object 554 // Go through all parts (primitives and meshes) of this Scene Object
465 foreach (SceneObjectPart part in grp.Parts) 555 foreach (SceneObjectPart part in grp.Parts)
466 { 556 {
@@ -471,30 +561,31 @@ namespace OpenSim.Region.Framework.Scenes
471 m_numMesh--; 561 m_numMesh--;
472 else 562 else
473 m_numPrim--; 563 m_numPrim--;
564
565 if(isPh && part.PhysicsShapeType != (byte)PhysShapeType.none)
566 nphysparts++;
474 } 567 }
475 568
476 if ((grp.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics) 569 if (nphysparts > 0 )
477 RemovePhysicalPrim(grp.PrimCount); 570 RemovePhysicalPrim(nphysparts);
478 } 571 }
479 572
573 bool ret = Entities.Remove(uuid);
574
480 lock (SceneObjectGroupsByFullID) 575 lock (SceneObjectGroupsByFullID)
481 SceneObjectGroupsByFullID.Remove(grp.UUID); 576 SceneObjectGroupsByFullID.Remove(grp.UUID);
482 577
483 lock (SceneObjectGroupsByFullPartID) 578 SceneObjectPart[] parts = grp.Parts;
579 for (int i = 0; i < parts.Length; i++)
484 { 580 {
485 SceneObjectPart[] parts = grp.Parts; 581 lock (SceneObjectGroupsByFullPartID)
486 for (int i = 0; i < parts.Length; i++)
487 SceneObjectGroupsByFullPartID.Remove(parts[i].UUID); 582 SceneObjectGroupsByFullPartID.Remove(parts[i].UUID);
488 }
489 583
490 lock (SceneObjectGroupsByLocalPartID) 584 lock (SceneObjectGroupsByLocalPartID)
491 {
492 SceneObjectPart[] parts = grp.Parts;
493 for (int i = 0; i < parts.Length; i++)
494 SceneObjectGroupsByLocalPartID.Remove(parts[i].LocalId); 585 SceneObjectGroupsByLocalPartID.Remove(parts[i].LocalId);
495 } 586 }
496 587
497 return Entities.Remove(uuid); 588 return ret;
498 } 589 }
499 590
500 /// <summary> 591 /// <summary>
@@ -509,6 +600,30 @@ namespace OpenSim.Region.Framework.Scenes
509 m_updateList[obj.UUID] = obj; 600 m_updateList[obj.UUID] = obj;
510 } 601 }
511 602
603 public void FireAttachToBackup(SceneObjectGroup obj)
604 {
605 if (OnAttachToBackup != null)
606 {
607 OnAttachToBackup(obj);
608 }
609 }
610
611 public void FireDetachFromBackup(SceneObjectGroup obj)
612 {
613 if (OnDetachFromBackup != null)
614 {
615 OnDetachFromBackup(obj);
616 }
617 }
618
619 public void FireChangeBackup(SceneObjectGroup obj)
620 {
621 if (OnChangeBackup != null)
622 {
623 OnChangeBackup(obj);
624 }
625 }
626
512 /// <summary> 627 /// <summary>
513 /// Process all pending updates 628 /// Process all pending updates
514 /// </summary> 629 /// </summary>
@@ -520,7 +635,7 @@ namespace OpenSim.Region.Framework.Scenes
520 { 635 {
521 List<SceneObjectGroup> updates; 636 List<SceneObjectGroup> updates;
522 637
523 // Some updates add more updates to the updateList. 638 // Some updates add more updates to the updateList.
524 // Get the current list of updates and clear the list before iterating 639 // Get the current list of updates and clear the list before iterating
525 lock (m_updateList) 640 lock (m_updateList)
526 { 641 {
@@ -600,7 +715,8 @@ namespace OpenSim.Region.Framework.Scenes
600 715
601 Entities[presence.UUID] = presence; 716 Entities[presence.UUID] = presence;
602 717
603 lock (m_presenceLock) 718 m_scenePresencesLock.EnterWriteLock();
719 try
604 { 720 {
605 m_numChildAgents++; 721 m_numChildAgents++;
606 722
@@ -626,6 +742,10 @@ namespace OpenSim.Region.Framework.Scenes
626 m_scenePresenceMap = newmap; 742 m_scenePresenceMap = newmap;
627 m_scenePresenceArray = newlist; 743 m_scenePresenceArray = newlist;
628 } 744 }
745 finally
746 {
747 m_scenePresencesLock.ExitWriteLock();
748 }
629 749
630 return presence; 750 return presence;
631 } 751 }
@@ -642,11 +762,12 @@ namespace OpenSim.Region.Framework.Scenes
642 agentID); 762 agentID);
643 } 763 }
644 764
645 lock (m_presenceLock) 765 m_scenePresencesLock.EnterWriteLock();
766 try
646 { 767 {
647 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 768 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
648 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 769 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
649 770
650 // Remove the presence reference from the dictionary 771 // Remove the presence reference from the dictionary
651 if (newmap.ContainsKey(agentID)) 772 if (newmap.ContainsKey(agentID))
652 { 773 {
@@ -664,6 +785,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); 785 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
665 } 786 }
666 } 787 }
788 finally
789 {
790 m_scenePresencesLock.ExitWriteLock();
791 }
667 } 792 }
668 793
669 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 794 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -754,7 +879,7 @@ namespace OpenSim.Region.Framework.Scenes
754 #endregion 879 #endregion
755 880
756 #region Get Methods 881 #region Get Methods
757 882
758 /// <summary> 883 /// <summary>
759 /// Get the controlling client for the given avatar, if there is one. 884 /// Get the controlling client for the given avatar, if there is one.
760 /// 885 ///
@@ -892,7 +1017,7 @@ namespace OpenSim.Region.Framework.Scenes
892 m_log.WarnFormat( 1017 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}.", 1018 "[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); 1019 sog.Name, sog.UUID, sog.LocalId, localID, m_parentScene.RegionInfo.RegionName);
895 1020 m_log.WarnFormat("stack: {0}", Environment.StackTrace);
896 SceneObjectGroupsByLocalPartID.Remove(localID); 1021 SceneObjectGroupsByLocalPartID.Remove(localID);
897 } 1022 }
898 } 1023 }
@@ -1066,11 +1191,11 @@ namespace OpenSim.Region.Framework.Scenes
1066 protected internal SceneObjectPart GetSceneObjectPart(uint localID) 1191 protected internal SceneObjectPart GetSceneObjectPart(uint localID)
1067 { 1192 {
1068 SceneObjectGroup group = GetGroupByPrim(localID); 1193 SceneObjectGroup group = GetGroupByPrim(localID);
1069 if (group == null) 1194 if (group == null || group.IsDeleted)
1070 return null; 1195 return null;
1071 return group.GetPart(localID); 1196 return group.GetPart(localID);
1072 } 1197 }
1073 1198
1074 /// <summary> 1199 /// <summary>
1075 /// Get a prim by name from the scene (will return the first 1200 /// Get a prim by name from the scene (will return the first
1076 /// found, if there are more than one prim with the same name) 1201 /// found, if there are more than one prim with the same name)
@@ -1089,7 +1214,7 @@ namespace OpenSim.Region.Framework.Scenes
1089 foreach (SceneObjectPart p in ((SceneObjectGroup)entity).Parts) 1214 foreach (SceneObjectPart p in ((SceneObjectGroup)entity).Parts)
1090 { 1215 {
1091// m_log.DebugFormat("[SCENE GRAPH]: Part {0} has name {1}", p.UUID, p.Name); 1216// m_log.DebugFormat("[SCENE GRAPH]: Part {0} has name {1}", p.UUID, p.Name);
1092 1217
1093 if (p.Name == name) 1218 if (p.Name == name)
1094 { 1219 {
1095 sop = p; 1220 sop = p;
@@ -1188,7 +1313,7 @@ namespace OpenSim.Region.Framework.Scenes
1188 /// <summary> 1313 /// <summary>
1189 /// Performs action on all scene presences. This can ultimately run the actions in parallel but 1314 /// Performs action on all scene presences. This can ultimately run the actions in parallel but
1190 /// any delegates passed in will need to implement their own locking on data they reference and 1315 /// any delegates passed in will need to implement their own locking on data they reference and
1191 /// modify outside of the scope of the delegate. 1316 /// modify outside of the scope of the delegate.
1192 /// </summary> 1317 /// </summary>
1193 /// <param name="action"></param> 1318 /// <param name="action"></param>
1194 public void ForEachScenePresence(Action<ScenePresence> action) 1319 public void ForEachScenePresence(Action<ScenePresence> action)
@@ -1223,11 +1348,57 @@ namespace OpenSim.Region.Framework.Scenes
1223 } 1348 }
1224 } 1349 }
1225 } 1350 }
1226 1351
1227 #endregion 1352 #endregion
1228 1353
1229 #region Client Event handlers 1354 #region Client Event handlers
1230 1355
1356 protected internal void ClientChangeObject(uint localID, object odata, IClientAPI remoteClient)
1357 {
1358 SceneObjectPart part = GetSceneObjectPart(localID);
1359 ObjectChangeData data = (ObjectChangeData)odata;
1360
1361 if (part != null)
1362 {
1363 SceneObjectGroup grp = part.ParentGroup;
1364 if (grp != null)
1365 {
1366 if (m_parentScene.Permissions.CanEditObject(grp, remoteClient))
1367 {
1368 // These two are exceptions SL makes in the interpretation
1369 // of the change flags. Must check them here because otherwise
1370 // the group flag (see below) would be lost
1371 if (data.change == ObjectChangeType.groupS)
1372 data.change = ObjectChangeType.primS;
1373 if (data.change == ObjectChangeType.groupPS)
1374 data.change = ObjectChangeType.primPS;
1375 part.StoreUndoState(data.change); // lets test only saving what we changed
1376 grp.doChangeObject(part, (ObjectChangeData)data);
1377 }
1378 else
1379 {
1380 // Is this any kind of group operation?
1381 if ((data.change & ObjectChangeType.Group) != 0)
1382 {
1383 // Is a move and/or rotation requested?
1384 if ((data.change & (ObjectChangeType.Position | ObjectChangeType.Rotation)) != 0)
1385 {
1386 // Are we allowed to move it?
1387 if (m_parentScene.Permissions.CanMoveObject(grp, remoteClient))
1388 {
1389 // Strip all but move and rotation from request
1390 data.change &= (ObjectChangeType.Group | ObjectChangeType.Position | ObjectChangeType.Rotation);
1391
1392 part.StoreUndoState(data.change);
1393 grp.doChangeObject(part, (ObjectChangeData)data);
1394 }
1395 }
1396 }
1397 }
1398 }
1399 }
1400 }
1401
1231 /// <summary> 1402 /// <summary>
1232 /// Update the scale of an individual prim. 1403 /// Update the scale of an individual prim.
1233 /// </summary> 1404 /// </summary>
@@ -1240,9 +1411,19 @@ namespace OpenSim.Region.Framework.Scenes
1240 1411
1241 if (part != null) 1412 if (part != null)
1242 { 1413 {
1243 if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)) 1414 if (m_parentScene.Permissions.CanEditObject(part.ParentGroup, remoteClient))
1244 { 1415 {
1416 bool physbuild = false;
1417 if (part.ParentGroup.RootPart.PhysActor != null)
1418 {
1419 part.ParentGroup.RootPart.PhysActor.Building = true;
1420 physbuild = true;
1421 }
1422
1245 part.Resize(scale); 1423 part.Resize(scale);
1424
1425 if (physbuild)
1426 part.ParentGroup.RootPart.PhysActor.Building = false;
1246 } 1427 }
1247 } 1428 }
1248 } 1429 }
@@ -1252,9 +1433,19 @@ namespace OpenSim.Region.Framework.Scenes
1252 SceneObjectGroup group = GetGroupByPrim(localID); 1433 SceneObjectGroup group = GetGroupByPrim(localID);
1253 if (group != null) 1434 if (group != null)
1254 { 1435 {
1255 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) 1436 if (m_parentScene.Permissions.CanEditObject(group, remoteClient))
1256 { 1437 {
1438 bool physbuild = false;
1439 if (group.RootPart.PhysActor != null)
1440 {
1441 group.RootPart.PhysActor.Building = true;
1442 physbuild = true;
1443 }
1444
1257 group.GroupResize(scale); 1445 group.GroupResize(scale);
1446
1447 if (physbuild)
1448 group.RootPart.PhysActor.Building = false;
1258 } 1449 }
1259 } 1450 }
1260 } 1451 }
@@ -1288,7 +1479,7 @@ namespace OpenSim.Region.Framework.Scenes
1288 SceneObjectGroup group = GetGroupByPrim(localID); 1479 SceneObjectGroup group = GetGroupByPrim(localID);
1289 if (group != null) 1480 if (group != null)
1290 { 1481 {
1291 if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId)) 1482 if (m_parentScene.Permissions.CanMoveObject(group, remoteClient))
1292 { 1483 {
1293 group.UpdateSingleRotation(rot, localID); 1484 group.UpdateSingleRotation(rot, localID);
1294 } 1485 }
@@ -1306,7 +1497,7 @@ namespace OpenSim.Region.Framework.Scenes
1306 SceneObjectGroup group = GetGroupByPrim(localID); 1497 SceneObjectGroup group = GetGroupByPrim(localID);
1307 if (group != null) 1498 if (group != null)
1308 { 1499 {
1309 if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId)) 1500 if (m_parentScene.Permissions.CanMoveObject(group, remoteClient))
1310 { 1501 {
1311 group.UpdateSingleRotation(rot, pos, localID); 1502 group.UpdateSingleRotation(rot, pos, localID);
1312 } 1503 }
@@ -1324,7 +1515,7 @@ namespace OpenSim.Region.Framework.Scenes
1324 SceneObjectGroup group = GetGroupByPrim(localID); 1515 SceneObjectGroup group = GetGroupByPrim(localID);
1325 if (group != null) 1516 if (group != null)
1326 { 1517 {
1327 if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId)) 1518 if (m_parentScene.Permissions.CanMoveObject(group, remoteClient))
1328 { 1519 {
1329 group.UpdateGroupRotationR(rot); 1520 group.UpdateGroupRotationR(rot);
1330 } 1521 }
@@ -1343,7 +1534,7 @@ namespace OpenSim.Region.Framework.Scenes
1343 SceneObjectGroup group = GetGroupByPrim(localID); 1534 SceneObjectGroup group = GetGroupByPrim(localID);
1344 if (group != null) 1535 if (group != null)
1345 { 1536 {
1346 if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId)) 1537 if (m_parentScene.Permissions.CanMoveObject(group, remoteClient))
1347 { 1538 {
1348 group.UpdateGroupRotationPR(pos, rot); 1539 group.UpdateGroupRotationPR(pos, rot);
1349 } 1540 }
@@ -1361,7 +1552,7 @@ namespace OpenSim.Region.Framework.Scenes
1361 SceneObjectGroup group = GetGroupByPrim(localID); 1552 SceneObjectGroup group = GetGroupByPrim(localID);
1362 if (group != null) 1553 if (group != null)
1363 { 1554 {
1364 if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId) || group.IsAttachment) 1555 if (m_parentScene.Permissions.CanMoveObject(group, remoteClient) || group.IsAttachment)
1365 { 1556 {
1366 group.UpdateSinglePosition(pos, localID); 1557 group.UpdateSinglePosition(pos, localID);
1367 } 1558 }
@@ -1376,30 +1567,24 @@ namespace OpenSim.Region.Framework.Scenes
1376 /// <param name="remoteClient"></param> 1567 /// <param name="remoteClient"></param>
1377 public void UpdatePrimGroupPosition(uint localId, Vector3 pos, IClientAPI remoteClient) 1568 public void UpdatePrimGroupPosition(uint localId, Vector3 pos, IClientAPI remoteClient)
1378 { 1569 {
1379 UpdatePrimGroupPosition(localId, pos, remoteClient.AgentId);
1380 }
1381
1382 /// <summary>
1383 /// Update the position of the given group.
1384 /// </summary>
1385 /// <param name="localId"></param>
1386 /// <param name="pos"></param>
1387 /// <param name="updatingAgentId"></param>
1388 public void UpdatePrimGroupPosition(uint localId, Vector3 pos, UUID updatingAgentId)
1389 {
1390 SceneObjectGroup group = GetGroupByPrim(localId); 1570 SceneObjectGroup group = GetGroupByPrim(localId);
1391 1571
1392 if (group != null) 1572 if (group != null)
1393 { 1573 {
1394 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1574 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1395 { 1575 {
1396 if (m_parentScene.AttachmentsModule != null) 1576 // Set the new attachment point data in the object
1397 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1577 byte attachmentPoint = (byte)group.AttachmentPoint;
1578 group.UpdateGroupPosition(pos);
1579 group.IsAttachment = false;
1580 group.AbsolutePosition = group.RootPart.AttachedPos;
1581 group.AttachmentPoint = attachmentPoint;
1582 group.HasGroupChanged = true;
1398 } 1583 }
1399 else 1584 else
1400 { 1585 {
1401 if (m_parentScene.Permissions.CanMoveObject(group.UUID, updatingAgentId) 1586 if (m_parentScene.Permissions.CanMoveObject(group, remoteClient)
1402 && m_parentScene.Permissions.CanObjectEntry(group.UUID, false, pos)) 1587 && m_parentScene.Permissions.CanObjectEntry(group, false, pos))
1403 { 1588 {
1404 group.UpdateGroupPosition(pos); 1589 group.UpdateGroupPosition(pos);
1405 } 1590 }
@@ -1419,13 +1604,16 @@ namespace OpenSim.Region.Framework.Scenes
1419 /// <param name="remoteClient"></param> 1604 /// <param name="remoteClient"></param>
1420 protected internal void UpdatePrimTexture(uint localID, byte[] texture, IClientAPI remoteClient) 1605 protected internal void UpdatePrimTexture(uint localID, byte[] texture, IClientAPI remoteClient)
1421 { 1606 {
1422 SceneObjectGroup group = GetGroupByPrim(localID); 1607 SceneObjectPart part = GetSceneObjectPart(localID);
1423 1608 if(part == null)
1424 if (group != null) 1609 return;
1610
1611 SceneObjectGroup group = part.ParentGroup;
1612 if (group != null && !group.IsDeleted)
1425 { 1613 {
1426 if (m_parentScene.Permissions.CanEditObject(group.UUID,remoteClient.AgentId)) 1614 if (m_parentScene.Permissions.CanEditObject(group, remoteClient))
1427 { 1615 {
1428 group.UpdateTextureEntry(localID, texture); 1616 part.UpdateTextureEntry(texture);
1429 } 1617 }
1430 } 1618 }
1431 } 1619 }
@@ -1447,11 +1635,12 @@ namespace OpenSim.Region.Framework.Scenes
1447 SceneObjectGroup group = GetGroupByPrim(localID); 1635 SceneObjectGroup group = GetGroupByPrim(localID);
1448 if (group != null) 1636 if (group != null)
1449 { 1637 {
1450 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) 1638 if (m_parentScene.Permissions.CanEditObject(group, remoteClient))
1451 { 1639 {
1452 // VolumeDetect can't be set via UI and will always be off when a change is made there 1640 // 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 1641 // now only change volume dtc if phantom off
1454 1642
1643 bool wantedPhys = UsePhysics;
1455 if (PhysData.PhysShapeType == PhysShapeType.invalid) // check for extraPhysics data 1644 if (PhysData.PhysShapeType == PhysShapeType.invalid) // check for extraPhysics data
1456 { 1645 {
1457 bool vdtc; 1646 bool vdtc;
@@ -1460,7 +1649,7 @@ namespace OpenSim.Region.Framework.Scenes
1460 else // else turn it off 1649 else // else turn it off
1461 vdtc = false; 1650 vdtc = false;
1462 1651
1463 group.UpdatePrimFlags(localID, UsePhysics, SetTemporary, SetPhantom, vdtc); 1652 group.UpdateFlags(UsePhysics, SetTemporary, SetPhantom, vdtc);
1464 } 1653 }
1465 else 1654 else
1466 { 1655 {
@@ -1468,77 +1657,21 @@ namespace OpenSim.Region.Framework.Scenes
1468 if (part != null) 1657 if (part != null)
1469 { 1658 {
1470 part.UpdateExtraPhysics(PhysData); 1659 part.UpdateExtraPhysics(PhysData);
1471 if (part.UpdatePhysRequired) 1660 if (remoteClient != null)
1472 remoteClient.SendPartPhysicsProprieties(part); 1661 remoteClient.SendPartPhysicsProprieties(part);
1473 } 1662 }
1474 } 1663 }
1475 }
1476 }
1477 }
1478
1479 /// <summary>
1480 /// Move the given object
1481 /// </summary>
1482 /// <param name="objectID"></param>
1483 /// <param name="offset"></param>
1484 /// <param name="pos"></param>
1485 /// <param name="remoteClient"></param>
1486 protected internal void MoveObject(UUID objectID, Vector3 offset, Vector3 pos, IClientAPI remoteClient, List<SurfaceTouchEventArgs> surfaceArgs)
1487 {
1488 SceneObjectGroup group = GetGroupByPrim(objectID);
1489 if (group != null)
1490 {
1491 if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId))// && PermissionsMngr.)
1492 {
1493 group.GrabMovement(objectID, offset, pos, remoteClient);
1494 }
1495 1664
1496 // This is outside the above permissions condition 1665 if (wantedPhys != group.UsesPhysics && remoteClient != null)
1497 // so that if the object is locked the client moving the object 1666 {
1498 // get's it's position on the simulator even if it was the same as before 1667 if(m_parentScene.m_linksetPhysCapacity != 0)
1499 // This keeps the moving user's client in sync with the rest of the world. 1668 remoteClient.SendAlertMessage("Object physics cancelled because it exceeds limits for physical prims, either size or number of primswith shape type not set to None");
1500 group.SendGroupTerseUpdate(); 1669 else
1501 } 1670 remoteClient.SendAlertMessage("Object physics cancelled because it exceeds size limits for physical prims");
1502 } 1671
1503 1672 group.RootPart.ScheduleFullUpdate();
1504 /// <summary> 1673 }
1505 /// Start spinning the given object
1506 /// </summary>
1507 /// <param name="objectID"></param>
1508 /// <param name="rotation"></param>
1509 /// <param name="remoteClient"></param>
1510 protected internal void SpinStart(UUID objectID, IClientAPI remoteClient)
1511 {
1512 SceneObjectGroup group = GetGroupByPrim(objectID);
1513 if (group != null)
1514 {
1515 if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId))// && PermissionsMngr.)
1516 {
1517 group.SpinStart(remoteClient);
1518 }
1519 }
1520 }
1521
1522 /// <summary>
1523 /// Spin the given object
1524 /// </summary>
1525 /// <param name="objectID"></param>
1526 /// <param name="rotation"></param>
1527 /// <param name="remoteClient"></param>
1528 protected internal void SpinObject(UUID objectID, Quaternion rotation, IClientAPI remoteClient)
1529 {
1530 SceneObjectGroup group = GetGroupByPrim(objectID);
1531 if (group != null)
1532 {
1533 if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId))// && PermissionsMngr.)
1534 {
1535 group.SpinMovement(rotation, remoteClient);
1536 } 1674 }
1537 // This is outside the above permissions condition
1538 // so that if the object is locked the client moving the object
1539 // get's it's position on the simulator even if it was the same as before
1540 // This keeps the moving user's client in sync with the rest of the world.
1541 group.SendGroupTerseUpdate();
1542 } 1675 }
1543 } 1676 }
1544 1677
@@ -1552,7 +1685,7 @@ namespace OpenSim.Region.Framework.Scenes
1552 SceneObjectGroup group = GetGroupByPrim(primLocalID); 1685 SceneObjectGroup group = GetGroupByPrim(primLocalID);
1553 if (group != null) 1686 if (group != null)
1554 { 1687 {
1555 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) 1688 if (m_parentScene.Permissions.CanEditObject(group, remoteClient))
1556 { 1689 {
1557 group.SetPartName(Util.CleanString(name), primLocalID); 1690 group.SetPartName(Util.CleanString(name), primLocalID);
1558 group.HasGroupChanged = true; 1691 group.HasGroupChanged = true;
@@ -1570,7 +1703,7 @@ namespace OpenSim.Region.Framework.Scenes
1570 SceneObjectGroup group = GetGroupByPrim(primLocalID); 1703 SceneObjectGroup group = GetGroupByPrim(primLocalID);
1571 if (group != null) 1704 if (group != null)
1572 { 1705 {
1573 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) 1706 if (m_parentScene.Permissions.CanEditObject(group, remoteClient))
1574 { 1707 {
1575 group.SetPartDescription(Util.CleanString(description), primLocalID); 1708 group.SetPartDescription(Util.CleanString(description), primLocalID);
1576 group.HasGroupChanged = true; 1709 group.HasGroupChanged = true;
@@ -1592,13 +1725,13 @@ namespace OpenSim.Region.Framework.Scenes
1592 SceneObjectGroup group = GetGroupByPrim(primLocalID); 1725 SceneObjectGroup group = GetGroupByPrim(primLocalID);
1593 if (group != null) 1726 if (group != null)
1594 { 1727 {
1595 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) 1728 if (m_parentScene.Permissions.CanEditObject(group, remoteClient))
1596 { 1729 {
1597 SceneObjectPart part = m_parentScene.GetSceneObjectPart(primLocalID); 1730 SceneObjectPart part = m_parentScene.GetSceneObjectPart(primLocalID);
1598 if (part != null) 1731 if (part != null)
1599 { 1732 {
1600 part.ClickAction = Convert.ToByte(clickAction); 1733 part.ClickAction = Convert.ToByte(clickAction);
1601 group.HasGroupChanged = true; 1734 group.HasGroupChanged = true;
1602 } 1735 }
1603 } 1736 }
1604 } 1737 }
@@ -1609,13 +1742,14 @@ namespace OpenSim.Region.Framework.Scenes
1609 SceneObjectGroup group = GetGroupByPrim(primLocalID); 1742 SceneObjectGroup group = GetGroupByPrim(primLocalID);
1610 if (group != null) 1743 if (group != null)
1611 { 1744 {
1612 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) 1745 if (m_parentScene.Permissions.CanEditObject(group, remoteClient))
1613 { 1746 {
1614 SceneObjectPart part = m_parentScene.GetSceneObjectPart(primLocalID); 1747 SceneObjectPart part = m_parentScene.GetSceneObjectPart(primLocalID);
1615 if (part != null) 1748 if (part != null)
1616 { 1749 {
1617 part.Material = Convert.ToByte(material); 1750 part.Material = Convert.ToByte(material);
1618 group.HasGroupChanged = true; 1751 group.HasGroupChanged = true;
1752 remoteClient.SendPartPhysicsProprieties(part);
1619 } 1753 }
1620 } 1754 }
1621 } 1755 }
@@ -1694,12 +1828,14 @@ namespace OpenSim.Region.Framework.Scenes
1694 return; 1828 return;
1695 1829
1696 Monitor.Enter(m_updateLock); 1830 Monitor.Enter(m_updateLock);
1831
1697 try 1832 try
1698 { 1833 {
1834
1699 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1835 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1700 1836
1701 // We do this in reverse to get the link order of the prims correct 1837 // We do this in reverse to get the link order of the prims correct
1702 for (int i = 0 ; i < children.Count ; i++) 1838 for (int i = 0; i < children.Count; i++)
1703 { 1839 {
1704 SceneObjectGroup child = children[i].ParentGroup; 1840 SceneObjectGroup child = children[i].ParentGroup;
1705 1841
@@ -1710,9 +1846,13 @@ namespace OpenSim.Region.Framework.Scenes
1710 // Make sure no child prim is set for sale 1846 // Make sure no child prim is set for sale
1711 // So that, on delink, no prims are unwittingly 1847 // So that, on delink, no prims are unwittingly
1712 // left for sale and sold off 1848 // left for sale and sold off
1713 child.RootPart.ObjectSaleType = 0; 1849
1714 child.RootPart.SalePrice = 10; 1850 if (child != null)
1715 childGroups.Add(child); 1851 {
1852 child.RootPart.ObjectSaleType = 0;
1853 child.RootPart.SalePrice = 10;
1854 childGroups.Add(child);
1855 }
1716 } 1856 }
1717 1857
1718 foreach (SceneObjectGroup child in childGroups) 1858 foreach (SceneObjectGroup child in childGroups)
@@ -1725,7 +1865,8 @@ namespace OpenSim.Region.Framework.Scenes
1725 1865
1726 // this is here so physics gets updated! 1866 // this is here so physics gets updated!
1727 // Don't remove! Bad juju! Stay away! or fix physics! 1867 // Don't remove! Bad juju! Stay away! or fix physics!
1728 child.AbsolutePosition = child.AbsolutePosition; 1868 // already done in LinkToGroup
1869// child.AbsolutePosition = child.AbsolutePosition;
1729 } 1870 }
1730 } 1871 }
1731 1872
@@ -1741,6 +1882,17 @@ namespace OpenSim.Region.Framework.Scenes
1741 } 1882 }
1742 finally 1883 finally
1743 { 1884 {
1885/*
1886 lock (SceneObjectGroupsByLocalPartID)
1887 {
1888 foreach (SceneObjectPart part in parentGroup.Parts)
1889 SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup;
1890 }
1891*/
1892 parentGroup.AdjustChildPrimPermissions(false);
1893 parentGroup.HasGroupChanged = true;
1894 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1895 parentGroup.ScheduleGroupForFullUpdate();
1744 Monitor.Exit(m_updateLock); 1896 Monitor.Exit(m_updateLock);
1745 } 1897 }
1746 } 1898 }
@@ -1761,42 +1913,50 @@ namespace OpenSim.Region.Framework.Scenes
1761 // 1913 //
1762 foreach (SceneObjectPart part in prims) 1914 foreach (SceneObjectPart part in prims)
1763 { 1915 {
1764 if (part != null) 1916 if(part == null)
1917 continue;
1918 SceneObjectGroup parentSOG = part.ParentGroup;
1919 if(parentSOG == null ||
1920 parentSOG.IsDeleted ||
1921 parentSOG.inTransit ||
1922 parentSOG.PrimCount == 1)
1923 continue;
1924
1925 if (!affectedGroups.Contains(parentSOG))
1765 { 1926 {
1766 if (part.KeyframeMotion != null) 1927 affectedGroups.Add(parentSOG);
1767 { 1928 if(parentSOG.RootPart.PhysActor != null)
1768 part.KeyframeMotion.Stop(); 1929 parentSOG.RootPart.PhysActor.Building = true;
1769 part.KeyframeMotion = null; 1930 }
1770 }
1771 if (part.ParentGroup.PrimCount != 1) // Skip single
1772 {
1773 if (part.LinkNum < 2) // Root
1774 {
1775 rootParts.Add(part);
1776 }
1777 else
1778 {
1779 part.LastOwnerID = part.ParentGroup.RootPart.LastOwnerID;
1780 childParts.Add(part);
1781 }
1782 1931
1783 SceneObjectGroup group = part.ParentGroup; 1932 if (part.KeyframeMotion != null)
1784 if (!affectedGroups.Contains(group)) 1933 {
1785 affectedGroups.Add(group); 1934 part.KeyframeMotion.Stop();
1786 } 1935 part.KeyframeMotion = null;
1936 }
1937
1938 if (part.LinkNum < 2) // Root
1939 {
1940 rootParts.Add(part);
1941 }
1942 else
1943 {
1944 part.LastOwnerID = part.ParentGroup.RootPart.LastOwnerID;
1945 part.RezzerID = part.ParentGroup.RootPart.RezzerID;
1946 childParts.Add(part);
1787 } 1947 }
1788 } 1948 }
1789 1949
1790 foreach (SceneObjectPart child in childParts) 1950 if (childParts.Count > 0)
1791 { 1951 {
1792 // Unlink all child parts from their groups 1952 foreach (SceneObjectPart child in childParts)
1793 // 1953 {
1794 child.ParentGroup.DelinkFromGroup(child, true); 1954 // Unlink all child parts from their groups
1795 1955 child.ParentGroup.DelinkFromGroup(child, true);
1796 // These are not in affected groups and will not be 1956 //child.ParentGroup is now other
1797 // handled further. Do the honors here. 1957 child.ParentGroup.HasGroupChanged = true;
1798 child.ParentGroup.HasGroupChanged = true; 1958 child.ParentGroup.ScheduleGroupForFullUpdate();
1799 child.ParentGroup.ScheduleGroupForFullUpdate(); 1959 }
1800 } 1960 }
1801 1961
1802 foreach (SceneObjectPart root in rootParts) 1962 foreach (SceneObjectPart root in rootParts)
@@ -1806,63 +1966,54 @@ namespace OpenSim.Region.Framework.Scenes
1806 // However, editing linked parts and unlinking may be different 1966 // However, editing linked parts and unlinking may be different
1807 // 1967 //
1808 SceneObjectGroup group = root.ParentGroup; 1968 SceneObjectGroup group = root.ParentGroup;
1809 1969
1810 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1970 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1971
1972 newSet.Remove(root);
1811 int numChildren = newSet.Count; 1973 int numChildren = newSet.Count;
1974 if(numChildren == 0)
1975 break;
1976
1977 foreach (SceneObjectPart p in newSet)
1978 group.DelinkFromGroup(p, false);
1979
1980 SceneObjectPart newRoot = newSet[0];
1812 1981
1813 // If there are prims left in a link set, but the root is 1982 // If there is more than one prim remaining, we
1814 // slated for unlink, we need to do this 1983 // need to re-link
1815 // 1984 //
1816 if (numChildren != 1) 1985 if (numChildren > 1)
1817 { 1986 {
1818 // Unlink the remaining set 1987 // Determine new root
1819 // 1988 //
1820 bool sendEventsToRemainder = true; 1989 newSet.RemoveAt(0);
1821 if (numChildren > 1) 1990 foreach (SceneObjectPart newChild in newSet)
1822 sendEventsToRemainder = false; 1991 newChild.ClearUpdateSchedule();
1823 1992
1824 foreach (SceneObjectPart p in newSet) 1993 LinkObjects(newRoot, newSet);
1825 { 1994 }
1826 if (p != group.RootPart) 1995 else
1827 group.DelinkFromGroup(p, sendEventsToRemainder); 1996 {
1828 } 1997 newRoot.TriggerScriptChangedEvent(Changed.LINK);
1829 1998 newRoot.ParentGroup.HasGroupChanged = true;
1830 // If there is more than one prim remaining, we 1999 newRoot.ParentGroup.InvalidatePartsLinkMaps();
1831 // need to re-link 2000 newRoot.ParentGroup.ScheduleGroupForFullUpdate();
1832 //
1833 if (numChildren > 2)
1834 {
1835 // Remove old root
1836 //
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
1847 // Determine new root
1848 //
1849 SceneObjectPart newRoot = newSet[0];
1850 newSet.RemoveAt(0);
1851
1852 foreach (SceneObjectPart newChild in newSet)
1853 newChild.ClearUpdateSchedule();
1854
1855 LinkObjects(newRoot, newSet);
1856 if (!affectedGroups.Contains(newRoot.ParentGroup))
1857 affectedGroups.Add(newRoot.ParentGroup);
1858 }
1859 } 2001 }
1860 } 2002 }
1861 2003
1862 // Finally, trigger events in the roots 2004 // trigger events in the roots
1863 // 2005 //
1864 foreach (SceneObjectGroup g in affectedGroups) 2006 foreach (SceneObjectGroup g in affectedGroups)
1865 { 2007 {
2008 if(g.RootPart.PhysActor != null)
2009 g.RootPart.PhysActor.Building = false;
2010 g.AdjustChildPrimPermissions(false);
2011 // Child prims that have been unlinked and deleted will
2012 // return unless the root is deleted. This will remove them
2013 // from the database. They will be rewritten immediately,
2014 // minus the rows for the unlinked child prims.
2015 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
2016 g.InvalidatePartsLinkMaps();
1866 g.TriggerScriptChangedEvent(Changed.LINK); 2017 g.TriggerScriptChangedEvent(Changed.LINK);
1867 g.HasGroupChanged = true; // Persist 2018 g.HasGroupChanged = true; // Persist
1868 g.ScheduleGroupForFullUpdate(); 2019 g.ScheduleGroupForFullUpdate();
@@ -1876,27 +2027,9 @@ namespace OpenSim.Region.Framework.Scenes
1876 2027
1877 protected internal void MakeObjectSearchable(IClientAPI remoteClient, bool IncludeInSearch, uint localID) 2028 protected internal void MakeObjectSearchable(IClientAPI remoteClient, bool IncludeInSearch, uint localID)
1878 { 2029 {
1879 UUID user = remoteClient.AgentId; 2030 SceneObjectGroup sog = GetGroupByPrim(localID);
1880 UUID objid = UUID.Zero; 2031 if(sog == null)
1881 SceneObjectPart obj = null; 2032 return;
1882
1883 EntityBase[] entityList = GetEntities();
1884 foreach (EntityBase ent in entityList)
1885 {
1886 if (ent is SceneObjectGroup)
1887 {
1888 SceneObjectGroup sog = ent as SceneObjectGroup;
1889
1890 foreach (SceneObjectPart part in sog.Parts)
1891 {
1892 if (part.LocalId == localID)
1893 {
1894 objid = part.UUID;
1895 obj = part;
1896 }
1897 }
1898 }
1899 }
1900 2033
1901 //Protip: In my day, we didn't call them searchable objects, we called them limited point-to-point joints 2034 //Protip: In my day, we didn't call them searchable objects, we called them limited point-to-point joints
1902 //aka ObjectFlags.JointWheel = IncludeInSearch 2035 //aka ObjectFlags.JointWheel = IncludeInSearch
@@ -1913,15 +2046,15 @@ namespace OpenSim.Region.Framework.Scenes
1913 // libomv will complain about PrimFlags.JointWheel being 2046 // libomv will complain about PrimFlags.JointWheel being
1914 // deprecated, so we 2047 // deprecated, so we
1915 #pragma warning disable 0612 2048 #pragma warning disable 0612
1916 if (IncludeInSearch && m_parentScene.Permissions.CanEditObject(objid, user)) 2049 if (IncludeInSearch && m_parentScene.Permissions.CanEditObject(sog, remoteClient))
1917 { 2050 {
1918 obj.ParentGroup.RootPart.AddFlag(PrimFlags.JointWheel); 2051 sog.RootPart.AddFlag(PrimFlags.JointWheel);
1919 obj.ParentGroup.HasGroupChanged = true; 2052 sog.HasGroupChanged = true;
1920 } 2053 }
1921 else if (!IncludeInSearch && m_parentScene.Permissions.CanMoveObject(objid,user)) 2054 else if (!IncludeInSearch && m_parentScene.Permissions.CanMoveObject(sog, remoteClient))
1922 { 2055 {
1923 obj.ParentGroup.RootPart.RemFlag(PrimFlags.JointWheel); 2056 sog.RootPart.RemFlag(PrimFlags.JointWheel);
1924 obj.ParentGroup.HasGroupChanged = true; 2057 sog.HasGroupChanged = true;
1925 } 2058 }
1926 #pragma warning restore 0612 2059 #pragma warning restore 0612
1927 } 2060 }
@@ -1936,120 +2069,86 @@ namespace OpenSim.Region.Framework.Scenes
1936 /// <param name="GroupID"></param> 2069 /// <param name="GroupID"></param>
1937 /// <param name="rot"></param> 2070 /// <param name="rot"></param>
1938 /// <returns>null if duplication fails, otherwise the duplicated object</returns> 2071 /// <returns>null if duplication fails, otherwise the duplicated object</returns>
1939 public SceneObjectGroup DuplicateObject( 2072 /// <summary>
1940 uint originalPrimID, Vector3 offset, uint flags, UUID AgentID, UUID GroupID, Quaternion rot) 2073 public SceneObjectGroup DuplicateObject(uint originalPrimID, Vector3 offset, UUID AgentID, UUID GroupID, Quaternion rot, bool createSelected)
1941 { 2074 {
1942 Monitor.Enter(m_updateLock); 2075// m_log.DebugFormat(
2076// "[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}",
2077// originalPrimID, offset, AgentID);
1943 2078
1944 try 2079 SceneObjectGroup original = GetGroupByPrim(originalPrimID);
2080 if (original != null)
1945 { 2081 {
1946 // m_log.DebugFormat( 2082 if (m_parentScene.Permissions.CanDuplicateObject(original, AgentID))
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 { 2083 {
1953 m_log.WarnFormat( 2084 SceneObjectGroup copy = original.Copy(true);
1954 "[SCENEGRAPH]: Attempt to duplicate nonexistent prim id {0} by {1}", originalPrimID, AgentID); 2085 copy.AbsolutePosition = copy.AbsolutePosition + offset;
1955 2086
1956 return null; 2087 SceneObjectPart[] parts = copy.Parts;
1957 }
1958
1959 if (!m_parentScene.Permissions.CanDuplicateObject(
1960 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 {
1968 copy.SetOwnerId(AgentID);
1969 copy.SetRootPartOwner(copy.RootPart, AgentID, GroupID);
1970 2088
1971 SceneObjectPart[] partList = copy.Parts; 2089 m_numTotalPrim += parts.Length;
1972 2090
1973 if (m_parentScene.Permissions.PropagatePermissions()) 2091 if (original.OwnerID != AgentID)
1974 { 2092 {
1975 foreach (SceneObjectPart child in partList) 2093 copy.SetOwner(AgentID, GroupID);
2094
2095 if (m_parentScene.Permissions.PropagatePermissions())
1976 { 2096 {
1977 child.Inventory.ChangeInventoryOwner(AgentID); 2097 foreach (SceneObjectPart child in parts)
1978 child.TriggerScriptChangedEvent(Changed.OWNER); 2098 {
1979 child.ApplyNextOwnerPermissions(); 2099 child.Inventory.ChangeInventoryOwner(AgentID);
2100 child.TriggerScriptChangedEvent(Changed.OWNER);
2101 child.ApplyNextOwnerPermissions();
2102 }
2103 copy.InvalidateEffectivePerms();
1980 } 2104 }
1981 } 2105 }
1982 2106
1983 copy.RootPart.ObjectSaleType = 0; 2107 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()
1984 copy.RootPart.SalePrice = 10; 2108 Entities.Add(copy);
1985 }
1986 2109
1987 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 2110 lock (SceneObjectGroupsByFullID)
1988 Entities.Add(copy); 2111 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 2112
2010 // Since we copy from a source group that is in selected 2113 foreach (SceneObjectPart part in parts)
2011 // state, but the copy is shown deselected in the viewer, 2114 {
2012 // We need to clear the selection flag here, else that 2115 if (part.GetPrimType() == PrimType.SCULPT)
2013 // prim never gets persisted at all. The client doesn't 2116 m_numMesh++;
2014 // think it's selected, so it will never send a deselect... 2117 else
2015 copy.IsSelected = false; 2118 m_numPrim++;
2016 2119
2017 m_numTotalPrim += copy.Parts.Length; 2120 lock (SceneObjectGroupsByFullPartID)
2121 SceneObjectGroupsByFullPartID[part.UUID] = copy;
2122 lock (SceneObjectGroupsByLocalPartID)
2123 SceneObjectGroupsByLocalPartID[part.LocalId] = copy;
2124 }
2018 2125
2019 // Go through all parts (primitives and meshes) of this Scene Object 2126 // PROBABLE END OF FIXME
2020 foreach (SceneObjectPart part in copy.Parts)
2021 {
2022 // Keep track of the total number of meshes or geometric primitives now in the scene;
2023 // determine which object this is based on its primitive type: sculpted (sculpt) prim refers to
2024 // a mesh and all other prims (i.e. box, sphere, etc) are geometric primitives
2025 if (part.GetPrimType() == PrimType.SCULPT)
2026 m_numMesh++;
2027 else
2028 m_numPrim++;
2029 }
2030 2127
2031 if (rot != Quaternion.Identity) 2128 copy.IsSelected = createSelected;
2032 { 2129
2033 copy.UpdateGroupRotationR(rot); 2130 if (rot != Quaternion.Identity)
2034 } 2131 copy.UpdateGroupRotationR(rot);
2035 2132
2036 copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 1); 2133 // required for physics to update it's position
2037 copy.HasGroupChanged = true; 2134 copy.ResetChildPrimPhysicsPositions();
2038 copy.ScheduleGroupForFullUpdate();
2039 copy.ResumeScripts();
2040 2135
2041 // required for physics to update it's position 2136 copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 1);
2042 copy.AbsolutePosition = copy.AbsolutePosition; 2137 copy.ResumeScripts();
2043 2138
2044 return copy; 2139 copy.HasGroupChanged = true;
2140 copy.ScheduleGroupForFullUpdate();
2141 return copy;
2142 }
2045 } 2143 }
2046 finally 2144 else
2047 { 2145 {
2048 Monitor.Exit(m_updateLock); 2146 m_log.WarnFormat("[SCENE]: Attempted to duplicate nonexistant prim id {0}", GroupID);
2049 } 2147 }
2148
2149 return null;
2050 } 2150 }
2051 2151
2052 /// <summary>
2053 /// Calculates the distance between two Vector3s 2152 /// Calculates the distance between two Vector3s
2054 /// </summary> 2153 /// </summary>
2055 /// <param name="v1"></param> 2154 /// <param name="v1"></param>
@@ -2067,6 +2166,6 @@ namespace OpenSim.Region.Framework.Scenes
2067 2166
2068 #endregion 2167 #endregion
2069 2168
2070 2169
2071 } 2170 }
2072} 2171}
diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs
index 28f7896..1e418df 100644
--- a/OpenSim/Region/Framework/Scenes/SceneManager.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs
@@ -91,19 +91,19 @@ namespace OpenSim.Region.Framework.Scenes
91 91
92 private static SceneManager m_instance = null; 92 private static SceneManager m_instance = null;
93 public static SceneManager Instance 93 public static SceneManager Instance
94 { 94 {
95 get { 95 get {
96 if (m_instance == null) 96 if (m_instance == null)
97 m_instance = new SceneManager(); 97 m_instance = new SceneManager();
98 return m_instance; 98 return m_instance;
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 });
227 207
228 if (Result != null) 208 if (s != null)
209 {
210 List<Scene> sceneList = Scenes;
211
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
@@ -359,7 +340,7 @@ namespace OpenSim.Region.Framework.Scenes
359 340
360 public bool TrySetCurrentScene(string regionName) 341 public bool TrySetCurrentScene(string regionName)
361 { 342 {
362 if ((String.Compare(regionName, "root") == 0) 343 if ((String.Compare(regionName, "root") == 0)
363 || (String.Compare(regionName, "..") == 0) 344 || (String.Compare(regionName, "..") == 0)
364 || (String.Compare(regionName, "/") == 0)) 345 || (String.Compare(regionName, "/") == 0))
365 { 346 {
@@ -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,74 +378,44 @@ 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
457 scene = null; 402 scene = null;
458 return false; 403 return false;
459 } 404 }
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
476 scene = null; 419 scene = null;
477 return false; 420 return false;
478 } 421 }
@@ -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..c20c81d 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();
@@ -115,78 +111,81 @@ namespace OpenSim.Region.Framework.Scenes
115 /// <param name="item">The user inventory item being added.</param> 111 /// <param name="item">The user inventory item being added.</param>
116 /// <param name="copyItemID">The item UUID that should be used by the new item.</param> 112 /// <param name="copyItemID">The item UUID that should be used by the new item.</param>
117 /// <returns></returns> 113 /// <returns></returns>
118 public bool AddInventoryItem(UUID agentID, uint localID, InventoryItemBase item, UUID copyItemID) 114 public bool AddInventoryItem(UUID agentID, uint localID, InventoryItemBase item, UUID copyItemID, bool withModRights = true)
119 { 115 {
120// m_log.DebugFormat( 116// m_log.DebugFormat(
121// "[PRIM INVENTORY]: Adding inventory item {0} from {1} to part with local ID {2}", 117// "[PRIM INVENTORY]: Adding inventory item {0} from {1} to part with local ID {2}",
122// item.Name, remoteClient.Name, localID); 118// item.Name, remoteClient.Name, localID);
123 119
124 UUID newItemId = (copyItemID != UUID.Zero) ? copyItemID : item.ID; 120 UUID newItemId = (copyItemID != UUID.Zero) ? copyItemID : item.ID;
125 121
126 SceneObjectPart part = GetPart(localID); 122 SceneObjectPart part = GetPart(localID);
127 if (part != null) 123 if (part == null)
128 { 124 {
129 TaskInventoryItem taskItem = new TaskInventoryItem(); 125 m_log.ErrorFormat(
130 126 "[PRIM INVENTORY]: " +
131 taskItem.ItemID = newItemId; 127 "Couldn't find prim local ID {0} in group {1}, {2} to add inventory item ID {3}",
132 taskItem.AssetID = item.AssetID; 128 localID, Name, UUID, newItemId);
133 taskItem.Name = item.Name; 129 return false;
134 taskItem.Description = item.Description; 130 }
135 taskItem.OwnerID = part.OwnerID; // Transfer ownership
136 taskItem.CreatorID = item.CreatorIdAsUuid;
137 taskItem.Type = item.AssetType;
138 taskItem.InvType = item.InvType;
139
140 if (agentID != part.OwnerID && m_scene.Permissions.PropagatePermissions())
141 {
142 taskItem.BasePermissions = item.BasePermissions &
143 item.NextPermissions;
144 taskItem.CurrentPermissions = item.CurrentPermissions &
145 item.NextPermissions;
146 taskItem.EveryonePermissions = item.EveryOnePermissions &
147 item.NextPermissions;
148 taskItem.GroupPermissions = item.GroupPermissions &
149 item.NextPermissions;
150 taskItem.NextPermissions = item.NextPermissions;
151 // We're adding this to a prim we don't own. Force
152 // owner change
153 taskItem.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm;
154 }
155 else
156 {
157 taskItem.BasePermissions = item.BasePermissions;
158 taskItem.CurrentPermissions = item.CurrentPermissions;
159 taskItem.EveryonePermissions = item.EveryOnePermissions;
160 taskItem.GroupPermissions = item.GroupPermissions;
161 taskItem.NextPermissions = item.NextPermissions;
162 }
163
164 taskItem.Flags = item.Flags;
165 131
166// m_log.DebugFormat( 132 TaskInventoryItem taskItem = new TaskInventoryItem();
167// "[PRIM INVENTORY]: Flags are 0x{0:X} for item {1} added to part {2} by {3}",
168// taskItem.Flags, taskItem.Name, localID, remoteClient.Name);
169
170 // TODO: These are pending addition of those fields to TaskInventoryItem
171// taskItem.SalePrice = item.SalePrice;
172// taskItem.SaleType = item.SaleType;
173 taskItem.CreationDate = (uint)item.CreationDate;
174 133
175 bool addFromAllowedDrop = agentID != part.OwnerID; 134 taskItem.ItemID = newItemId;
135 taskItem.AssetID = item.AssetID;
136 taskItem.Name = item.Name;
137 taskItem.Description = item.Description;
138 taskItem.OwnerID = part.OwnerID; // Transfer ownership
139 taskItem.CreatorID = item.CreatorIdAsUuid;
140 taskItem.Type = item.AssetType;
141 taskItem.InvType = item.InvType;
176 142
177 part.Inventory.AddInventoryItem(taskItem, addFromAllowedDrop); 143 if (agentID != part.OwnerID && m_scene.Permissions.PropagatePermissions())
144 {
145 taskItem.BasePermissions = item.BasePermissions &
146 item.NextPermissions;
147 taskItem.CurrentPermissions = item.CurrentPermissions &
148 item.NextPermissions;
149 taskItem.EveryonePermissions = item.EveryOnePermissions &
150 item.NextPermissions;
151 taskItem.GroupPermissions = item.GroupPermissions &
152 item.NextPermissions;
153 taskItem.NextPermissions = item.NextPermissions;
154 // We're adding this to a prim we don't own. Force
155 // owner change
156 taskItem.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm;
178 157
179 return true;
180 } 158 }
181 else 159 else
182 { 160 {
183 m_log.ErrorFormat( 161 taskItem.BasePermissions = item.BasePermissions;
184 "[PRIM INVENTORY]: " + 162 taskItem.CurrentPermissions = item.CurrentPermissions;
185 "Couldn't find prim local ID {0} in group {1}, {2} to add inventory item ID {3}", 163 taskItem.EveryonePermissions = item.EveryOnePermissions;
186 localID, Name, UUID, newItemId); 164 taskItem.GroupPermissions = item.GroupPermissions;
165 taskItem.NextPermissions = item.NextPermissions;
187 } 166 }
188 167
189 return false; 168 taskItem.Flags = item.Flags;
169
170// m_log.DebugFormat(
171// "[PRIM INVENTORY]: Flags are 0x{0:X} for item {1} added to part {2} by {3}",
172// taskItem.Flags, taskItem.Name, localID, remoteClient.Name);
173
174 // TODO: These are pending addition of those fields to TaskInventoryItem
175// taskItem.SalePrice = item.SalePrice;
176// taskItem.SaleType = item.SaleType;
177 taskItem.CreationDate = (uint)item.CreationDate;
178
179 bool addFromAllowedDrop;
180 if(withModRights)
181 addFromAllowedDrop = false;
182 else
183 addFromAllowedDrop = (part.ParentGroup.RootPart.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) != 0;
184
185 part.Inventory.AddInventoryItem(taskItem, addFromAllowedDrop);
186 part.ParentGroup.InvalidateEffectivePerms();
187 return true;
188
190 } 189 }
191 190
192 /// <summary> 191 /// <summary>
@@ -252,21 +251,201 @@ namespace OpenSim.Region.Framework.Scenes
252 return -1; 251 return -1;
253 } 252 }
254 253
255 public uint GetEffectivePermissions() 254 // new test code, to place in better place later
255 private object m_PermissionsLock = new object();
256 private bool m_EffectivePermsInvalid = true;
257 private bool m_DeepEffectivePermsInvalid = true;
258
259 // should called when parts chanced by their contents did not, so we know their cacche is valid
260 // in case of doubt call InvalidateDeepEffectivePerms(), it only costs a bit more cpu time
261 public void InvalidateEffectivePerms()
262 {
263 lock(m_PermissionsLock)
264 m_EffectivePermsInvalid = true;
265 }
266
267 // should called when parts chanced and their contents where accounted for
268 public void InvalidateDeepEffectivePerms()
269 {
270 lock(m_PermissionsLock)
271 {
272 m_DeepEffectivePermsInvalid = true;
273 m_EffectivePermsInvalid = true;
274 }
275 }
276
277 private uint m_EffectiveEveryOnePerms;
278 public uint EffectiveEveryOnePerms
279 {
280 get
281 {
282 lock(m_PermissionsLock)
283 {
284 if(m_EffectivePermsInvalid)
285 AggregatePerms();
286 return m_EffectiveEveryOnePerms;
287 }
288 }
289 }
290
291 private uint m_EffectiveGroupPerms;
292 public uint EffectiveGroupPerms
293 {
294 get
295 {
296 lock(m_PermissionsLock)
297 {
298 if(m_EffectivePermsInvalid)
299 AggregatePerms();
300 return m_EffectiveGroupPerms;
301 }
302 }
303 }
304
305 private uint m_EffectiveGroupOrEveryOnePerms;
306 public uint EffectiveGroupOrEveryOnePerms
307 {
308 get
309 {
310 lock(m_PermissionsLock)
311 {
312 if(m_EffectivePermsInvalid)
313 AggregatePerms();
314 return m_EffectiveGroupOrEveryOnePerms;
315 }
316 }
317 }
318
319 private uint m_EffectiveOwnerPerms;
320 public uint EffectiveOwnerPerms
321 {
322 get
323 {
324 lock(m_PermissionsLock)
325 {
326 if(m_EffectivePermsInvalid)
327 AggregatePerms();
328 return m_EffectiveOwnerPerms;
329 }
330 }
331 }
332
333 public void AggregatePerms()
334 {
335 lock(m_PermissionsLock)
336 {
337 // aux
338 const uint allmask = (uint)PermissionMask.AllEffective;
339 const uint movemodmask = (uint)(PermissionMask.Move | PermissionMask.Modify);
340 const uint copytransfermast = (uint)(PermissionMask.Copy | PermissionMask.Transfer);
341
342 uint basePerms = (RootPart.BaseMask & allmask) | (uint)PermissionMask.Move;
343 bool noBaseTransfer = (basePerms & (uint)PermissionMask.Transfer) == 0;
344
345 uint rootOwnerPerms = RootPart.OwnerMask;
346 uint owner = rootOwnerPerms;
347 uint rootGroupPerms = RootPart.GroupMask;
348 uint group = rootGroupPerms;
349 uint rootEveryonePerms = RootPart.EveryoneMask;
350 uint everyone = rootEveryonePerms;
351
352 bool needUpdate = false;
353 // date is time of writing april 30th 2017
354 bool newobj = (RootPart.CreationDate == 0 || RootPart.CreationDate > 1493574994);
355 SceneObjectPart[] parts = m_parts.GetArray();
356 for (int i = 0; i < parts.Length; i++)
357 {
358 SceneObjectPart part = parts[i];
359
360 if(m_DeepEffectivePermsInvalid)
361 part.AggregatedInnerPermsForGroup();
362
363 owner &= part.AggregatedInnerOwnerPerms;
364 group &= part.AggregatedInnerGroupPerms;
365 if(newobj)
366 group &= part.AggregatedInnerGroupPerms;
367 if(newobj)
368 everyone &= part.AggregatedInnerEveryonePerms;
369 }
370 // recover modify and move
371 rootOwnerPerms &= movemodmask;
372 owner |= rootOwnerPerms;
373 if((owner & copytransfermast) == 0)
374 owner |= (uint)PermissionMask.Transfer;
375
376 owner &= basePerms;
377 if(owner != m_EffectiveOwnerPerms)
378 {
379 needUpdate = true;
380 m_EffectiveOwnerPerms = owner;
381 }
382
383 uint ownertransfermask = owner & (uint)PermissionMask.Transfer;
384
385 // recover modify and move
386 rootGroupPerms &= movemodmask;
387 group |= rootGroupPerms;
388 if(noBaseTransfer)
389 group &=~(uint)PermissionMask.Copy;
390 else
391 group |= ownertransfermask;
392
393 uint groupOrEveryone = group;
394 uint tmpPerms = group & owner;
395 if(tmpPerms != m_EffectiveGroupPerms)
396 {
397 needUpdate = true;
398 m_EffectiveGroupPerms = tmpPerms;
399 }
400
401 // recover move
402 rootEveryonePerms &= (uint)PermissionMask.Move;
403 everyone |= rootEveryonePerms;
404 everyone &= ~(uint)PermissionMask.Modify;
405 if(noBaseTransfer)
406 everyone &=~(uint)PermissionMask.Copy;
407 else
408 everyone |= ownertransfermask;
409
410 groupOrEveryone |= everyone;
411
412 tmpPerms = everyone & owner;
413 if(tmpPerms != m_EffectiveEveryOnePerms)
414 {
415 needUpdate = true;
416 m_EffectiveEveryOnePerms = tmpPerms;
417 }
418
419 tmpPerms = groupOrEveryone & owner;
420 if(tmpPerms != m_EffectiveGroupOrEveryOnePerms)
421 {
422 needUpdate = true;
423 m_EffectiveGroupOrEveryOnePerms = tmpPerms;
424 }
425
426 m_DeepEffectivePermsInvalid = false;
427 m_EffectivePermsInvalid = false;
428
429 if(needUpdate)
430 RootPart.ScheduleFullUpdate();
431 }
432 }
433
434 public uint CurrentAndFoldedNextPermissions()
256 { 435 {
257 uint perms=(uint)(PermissionMask.Modify | 436 uint perms=(uint)(PermissionMask.Modify |
258 PermissionMask.Copy | 437 PermissionMask.Copy |
259 PermissionMask.Move | 438 PermissionMask.Move |
260 PermissionMask.Transfer) | 7; 439 PermissionMask.Transfer |
440 PermissionMask.FoldedMask);
261 441
262 uint ownerMask = 0x7fffffff; 442 uint ownerMask = RootPart.OwnerMask;
263 443
264 SceneObjectPart[] parts = m_parts.GetArray(); 444 SceneObjectPart[] parts = m_parts.GetArray();
265 for (int i = 0; i < parts.Length; i++) 445 for (int i = 0; i < parts.Length; i++)
266 { 446 {
267 SceneObjectPart part = parts[i]; 447 SceneObjectPart part = parts[i];
268// m_log.DebugFormat("[SCENE OBJECT GROUP INVENTORY]: Effective perms of {0} are {1}", part.Name, (OpenMetaverse.PermissionMask)part.OwnerMask); 448 ownerMask &= part.BaseMask;
269 ownerMask &= part.OwnerMask;
270 perms &= part.Inventory.MaskEffectivePermissions(); 449 perms &= part.Inventory.MaskEffectivePermissions();
271 } 450 }
272 451
@@ -276,17 +455,8 @@ namespace OpenSim.Region.Framework.Scenes
276 perms &= ~(uint)PermissionMask.Copy; 455 perms &= ~(uint)PermissionMask.Copy;
277 if ((ownerMask & (uint)PermissionMask.Transfer) == 0) 456 if ((ownerMask & (uint)PermissionMask.Transfer) == 0)
278 perms &= ~(uint)PermissionMask.Transfer; 457 perms &= ~(uint)PermissionMask.Transfer;
279 458 if ((ownerMask & (uint)PermissionMask.Export) == 0)
280 // If root prim permissions are applied here, this would screw 459 perms &= ~(uint)PermissionMask.Export;
281 // with in-inventory manipulation of the next owner perms
282 // in a major way. So, let's move this to the give itself.
283 // Yes. I know. Evil.
284// if ((ownerMask & RootPart.NextOwnerMask & (uint)PermissionMask.Modify) == 0)
285// perms &= ~((uint)PermissionMask.Modify >> 13);
286// if ((ownerMask & RootPart.NextOwnerMask & (uint)PermissionMask.Copy) == 0)
287// perms &= ~((uint)PermissionMask.Copy >> 13);
288// if ((ownerMask & RootPart.NextOwnerMask & (uint)PermissionMask.Transfer) == 0)
289// perms &= ~((uint)PermissionMask.Transfer >> 13);
290 460
291 return perms; 461 return perms;
292 } 462 }
@@ -323,18 +493,19 @@ namespace OpenSim.Region.Framework.Scenes
323 xmldoc.AppendChild(xmlnode); 493 xmldoc.AppendChild(xmlnode);
324 XmlElement rootElement = xmldoc.CreateElement("", "ScriptData", 494 XmlElement rootElement = xmldoc.CreateElement("", "ScriptData",
325 String.Empty); 495 String.Empty);
326 496
327 xmldoc.AppendChild(rootElement); 497 xmldoc.AppendChild(rootElement);
328 498
329 499
330 XmlElement wrapper = xmldoc.CreateElement("", "ScriptStates", 500 XmlElement wrapper = xmldoc.CreateElement("", "ScriptStates",
331 String.Empty); 501 String.Empty);
332 502
333 rootElement.AppendChild(wrapper); 503 rootElement.AppendChild(wrapper);
334 504
335 foreach (KeyValuePair<UUID, string> state in states) 505 foreach (KeyValuePair<UUID, string> state in states)
336 { 506 {
337 XmlDocument sdoc = new XmlDocument(); 507 XmlDocument sdoc = new XmlDocument();
508 sdoc.XmlResolver=null;
338 sdoc.LoadXml(state.Value); 509 sdoc.LoadXml(state.Value);
339 XmlNodeList rootL = sdoc.GetElementsByTagName("State"); 510 XmlNodeList rootL = sdoc.GetElementsByTagName("State");
340 XmlNode rootNode = rootL[0]; 511 XmlNode rootNode = rootL[0];
@@ -357,7 +528,7 @@ namespace OpenSim.Region.Framework.Scenes
357 return; 528 return;
358 529
359 IScriptModule scriptModule = null; 530 IScriptModule scriptModule = null;
360 531
361 foreach (IScriptModule sm in s.RequestModuleInterfaces<IScriptModule>()) 532 foreach (IScriptModule sm in s.RequestModuleInterfaces<IScriptModule>())
362 { 533 {
363 if (sm.ScriptEngineName == s.DefaultScriptEngine) 534 if (sm.ScriptEngineName == s.DefaultScriptEngine)
@@ -370,6 +541,7 @@ namespace OpenSim.Region.Framework.Scenes
370 return; 541 return;
371 542
372 XmlDocument doc = new XmlDocument(); 543 XmlDocument doc = new XmlDocument();
544 doc.XmlResolver=null;
373 try 545 try
374 { 546 {
375 doc.LoadXml(objXMLData); 547 doc.LoadXml(objXMLData);
@@ -396,7 +568,7 @@ namespace OpenSim.Region.Framework.Scenes
396 return; 568 return;
397 569
398 XmlElement dataE = (XmlElement)dataL[0]; 570 XmlElement dataE = (XmlElement)dataL[0];
399 571
400 foreach (XmlNode n in dataE.ChildNodes) 572 foreach (XmlNode n in dataE.ChildNodes)
401 { 573 {
402 XmlElement stateE = (XmlElement)n; 574 XmlElement stateE = (XmlElement)n;
@@ -408,6 +580,9 @@ namespace OpenSim.Region.Framework.Scenes
408 580
409 public void ResumeScripts() 581 public void ResumeScripts()
410 { 582 {
583 if (m_scene.RegionInfo.RegionSettings.DisableScripts)
584 return;
585
411 SceneObjectPart[] parts = m_parts.GetArray(); 586 SceneObjectPart[] parts = m_parts.GetArray();
412 for (int i = 0; i < parts.Length; i++) 587 for (int i = 0; i < parts.Length; i++)
413 parts[i].Inventory.ResumeScripts(); 588 parts[i].Inventory.ResumeScripts();
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index d08237e..21311b0 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -30,6 +30,7 @@ using 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;
@@ -45,6 +46,7 @@ using OpenSim.Services.Interfaces;
45 46
46namespace OpenSim.Region.Framework.Scenes 47namespace OpenSim.Region.Framework.Scenes
47{ 48{
49
48 [Flags] 50 [Flags]
49 public enum scriptEvents 51 public enum scriptEvents
50 { 52 {
@@ -77,17 +79,18 @@ namespace OpenSim.Region.Framework.Scenes
77 touch_end = 536870912, 79 touch_end = 536870912,
78 touch_start = 2097152, 80 touch_start = 2097152,
79 transaction_result = 33554432, 81 transaction_result = 33554432,
80 object_rez = 4194304 82 object_rez = 4194304,
83 anytouch = touch | touch_end | touch_start
81 } 84 }
82 85
83 struct scriptPosTarget 86 public struct scriptPosTarget
84 { 87 {
85 public Vector3 targetPos; 88 public Vector3 targetPos;
86 public float tolerance; 89 public float tolerance;
87 public uint handle; 90 public uint handle;
88 } 91 }
89 92
90 struct scriptRotTarget 93 public struct scriptRotTarget
91 { 94 {
92 public Quaternion targetRot; 95 public Quaternion targetRot;
93 public float tolerance; 96 public float tolerance;
@@ -109,11 +112,11 @@ namespace OpenSim.Region.Framework.Scenes
109 STATUS_ROTATE_X = 0x002, 112 STATUS_ROTATE_X = 0x002,
110 STATUS_ROTATE_Y = 0x004, 113 STATUS_ROTATE_Y = 0x004,
111 STATUS_ROTATE_Z = 0x008, 114 STATUS_ROTATE_Z = 0x008,
115 NOT_STATUS_ROTATE_X = 0xFD,
116 NOT_STATUS_ROTATE_Y = 0xFB,
117 NOT_STATUS_ROTATE_Z = 0xF7
112 } 118 }
113 119
114 // This flag has the same purpose as InventoryItemFlags.ObjectSlamPerm
115 public static readonly uint SLAM = 16;
116
117 // private PrimCountTaintedDelegate handlerPrimCountTainted = null; 120 // private PrimCountTaintedDelegate handlerPrimCountTainted = null;
118 121
119 /// <summary> 122 /// <summary>
@@ -121,8 +124,11 @@ namespace OpenSim.Region.Framework.Scenes
121 /// since the group's last persistent backup 124 /// since the group's last persistent backup
122 /// </summary> 125 /// </summary>
123 private bool m_hasGroupChanged = false; 126 private bool m_hasGroupChanged = false;
124 private long timeFirstChanged; 127 private long timeFirstChanged = 0;
125 private long timeLastChanged; 128 private long timeLastChanged = 0;
129 private long m_maxPersistTime = 0;
130 private long m_minPersistTime = 0;
131// private Random m_rand;
126 132
127 /// <summary> 133 /// <summary>
128 /// This indicates whether the object has changed such that it needs to be repersisted to permenant storage 134 /// This indicates whether the object has changed such that it needs to be repersisted to permenant storage
@@ -139,12 +145,47 @@ namespace OpenSim.Region.Framework.Scenes
139 { 145 {
140 if (value) 146 if (value)
141 { 147 {
142 timeLastChanged = DateTime.Now.Ticks; 148
149 if (Backup)
150 {
151 m_scene.SceneGraph.FireChangeBackup(this);
152 }
153 timeLastChanged = DateTime.UtcNow.Ticks;
143 if (!m_hasGroupChanged) 154 if (!m_hasGroupChanged)
144 timeFirstChanged = DateTime.Now.Ticks; 155 timeFirstChanged = DateTime.UtcNow.Ticks;
156 if (m_rootPart != null && m_scene != null)
157 {
158/*
159 if (m_rand == null)
160 {
161 byte[] val = new byte[16];
162 m_rootPart.UUID.ToBytes(val, 0);
163 m_rand = new Random(BitConverter.ToInt32(val, 0));
164 }
165 */
166 if (m_scene.GetRootAgentCount() == 0)
167 {
168 //If the region is empty, this change has been made by an automated process
169 //and thus we delay the persist time by a random amount between 1.5 and 2.5.
170
171// float factor = 1.5f + (float)(m_rand.NextDouble());
172 float factor = 2.0f;
173 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * factor);
174 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * factor);
175 }
176 else
177 {
178 //If the region is not empty, we want to obey the minimum and maximum persist times
179 //but add a random factor so we stagger the object persistance a little
180// m_maxPersistTime = (long)((float)m_scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5
181// m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0
182 m_maxPersistTime = m_scene.m_persistAfter;
183 m_minPersistTime = m_scene.m_dontPersistBefore;
184 }
185 }
145 } 186 }
146 m_hasGroupChanged = value; 187 m_hasGroupChanged = value;
147 188
148// m_log.DebugFormat( 189// m_log.DebugFormat(
149// "[SCENE OBJECT GROUP]: HasGroupChanged set to {0} for {1} {2}", m_hasGroupChanged, Name, LocalId); 190// "[SCENE OBJECT GROUP]: HasGroupChanged set to {0} for {1} {2}", m_hasGroupChanged, Name, LocalId);
150 } 191 }
@@ -153,7 +194,7 @@ namespace OpenSim.Region.Framework.Scenes
153 } 194 }
154 195
155 private bool m_groupContainsForeignPrims = false; 196 private bool m_groupContainsForeignPrims = false;
156 197
157 /// <summary> 198 /// <summary>
158 /// Whether the group contains prims that came from a different group. This happens when 199 /// Whether the group contains prims that came from a different group. This happens when
159 /// linking or delinking groups. The implication is that until the group is persisted, 200 /// linking or delinking groups. The implication is that until the group is persisted,
@@ -172,6 +213,7 @@ namespace OpenSim.Region.Framework.Scenes
172 get { return m_groupContainsForeignPrims; } 213 get { return m_groupContainsForeignPrims; }
173 } 214 }
174 215
216 public bool HasGroupChangedDueToDelink { get; set; }
175 217
176 private bool isTimeToPersist() 218 private bool isTimeToPersist()
177 { 219 {
@@ -181,8 +223,19 @@ namespace OpenSim.Region.Framework.Scenes
181 return false; 223 return false;
182 if (m_scene.ShuttingDown) 224 if (m_scene.ShuttingDown)
183 return true; 225 return true;
184 long currentTime = DateTime.Now.Ticks; 226
185 if (currentTime - timeLastChanged > m_scene.m_dontPersistBefore || currentTime - timeFirstChanged > m_scene.m_persistAfter) 227 if (m_minPersistTime == 0 || m_maxPersistTime == 0)
228 {
229 m_maxPersistTime = m_scene.m_persistAfter;
230 m_minPersistTime = m_scene.m_dontPersistBefore;
231 }
232
233 long currentTime = DateTime.UtcNow.Ticks;
234
235 if (timeLastChanged == 0) timeLastChanged = currentTime;
236 if (timeFirstChanged == 0) timeFirstChanged = currentTime;
237
238 if (currentTime - timeLastChanged > m_minPersistTime || currentTime - timeFirstChanged > m_maxPersistTime)
186 return true; 239 return true;
187 return false; 240 return false;
188 } 241 }
@@ -240,6 +293,11 @@ namespace OpenSim.Region.Framework.Scenes
240 { 293 {
241 AttachmentPoint = 0; 294 AttachmentPoint = 0;
242 295
296 // Don't zap trees
297 if (RootPart.Shape.PCode == (byte)PCode.Tree ||
298 RootPart.Shape.PCode == (byte)PCode.NewTree)
299 return;
300
243 // Even though we don't use child part state parameters for attachments any more, we still need to set 301 // Even though we don't use child part state parameters for attachments any more, we still need to set
244 // these to zero since having them non-zero in rezzed scene objects will crash some clients. Even if 302 // these to zero since having them non-zero in rezzed scene objects will crash some clients. Even if
245 // we store them correctly, scene objects that we receive from elsewhere might not. 303 // we store them correctly, scene objects that we receive from elsewhere might not.
@@ -269,6 +327,7 @@ namespace OpenSim.Region.Framework.Scenes
269 get { return (RootPart.Flags & PrimFlags.Physics) != 0; } 327 get { return (RootPart.Flags & PrimFlags.Physics) != 0; }
270 } 328 }
271 329
330
272 /// <summary> 331 /// <summary>
273 /// Is this scene object temporary? 332 /// Is this scene object temporary?
274 /// </summary> 333 /// </summary>
@@ -285,9 +344,6 @@ namespace OpenSim.Region.Framework.Scenes
285 get { return RootPart.VolumeDetectActive; } 344 get { return RootPart.VolumeDetectActive; }
286 } 345 }
287 346
288 private Vector3 lastPhysGroupPos;
289 private Quaternion lastPhysGroupRot;
290
291 /// <summary> 347 /// <summary>
292 /// Is this entity set to be saved in persistent storage? 348 /// Is this entity set to be saved in persistent storage?
293 /// </summary> 349 /// </summary>
@@ -299,17 +355,29 @@ namespace OpenSim.Region.Framework.Scenes
299 protected SceneObjectPart m_rootPart; 355 protected SceneObjectPart m_rootPart;
300 // private Dictionary<UUID, scriptEvents> m_scriptEvents = new Dictionary<UUID, scriptEvents>(); 356 // private Dictionary<UUID, scriptEvents> m_scriptEvents = new Dictionary<UUID, scriptEvents>();
301 357
302 private Dictionary<uint, scriptPosTarget> m_targets = new Dictionary<uint, scriptPosTarget>(); 358 private SortedDictionary<uint, scriptPosTarget> m_targets = new SortedDictionary<uint, scriptPosTarget>();
303 private Dictionary<uint, scriptRotTarget> m_rotTargets = new Dictionary<uint, scriptRotTarget>(); 359 private SortedDictionary<uint, scriptRotTarget> m_rotTargets = new SortedDictionary<uint, scriptRotTarget>();
360
361 public SortedDictionary<uint, scriptPosTarget> AtTargets
362 {
363 get { return m_targets; }
364 }
365
366 public SortedDictionary<uint, scriptRotTarget> RotTargets
367 {
368 get { return m_rotTargets; }
369 }
304 370
305 private bool m_scriptListens_atTarget; 371 private bool m_scriptListens_atTarget;
306 private bool m_scriptListens_notAtTarget; 372 private bool m_scriptListens_notAtTarget;
307
308 private bool m_scriptListens_atRotTarget; 373 private bool m_scriptListens_atRotTarget;
309 private bool m_scriptListens_notAtRotTarget; 374 private bool m_scriptListens_notAtRotTarget;
310 375
376 public bool m_dupeInProgress = false;
311 internal Dictionary<UUID, string> m_savedScriptState; 377 internal Dictionary<UUID, string> m_savedScriptState;
312 378
379 public UUID MonitoringObject { get; set; }
380
313 #region Properties 381 #region Properties
314 382
315 /// <summary> 383 /// <summary>
@@ -344,6 +412,16 @@ namespace OpenSim.Region.Framework.Scenes
344 get { return m_parts.Count; } 412 get { return m_parts.Count; }
345 } 413 }
346 414
415// protected Quaternion m_rotation = Quaternion.Identity;
416//
417// public virtual Quaternion Rotation
418// {
419// get { return m_rotation; }
420// set {
421// m_rotation = value;
422// }
423// }
424
347 public Quaternion GroupRotation 425 public Quaternion GroupRotation
348 { 426 {
349 get { return m_rootPart.RotationOffset; } 427 get { return m_rootPart.RotationOffset; }
@@ -356,27 +434,27 @@ namespace OpenSim.Region.Framework.Scenes
356 Vector3 minScale = new Vector3(Constants.MaximumRegionSize, Constants.MaximumRegionSize, Constants.MaximumRegionSize); 434 Vector3 minScale = new Vector3(Constants.MaximumRegionSize, Constants.MaximumRegionSize, Constants.MaximumRegionSize);
357 Vector3 maxScale = Vector3.Zero; 435 Vector3 maxScale = Vector3.Zero;
358 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); 436 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
359 437
360 SceneObjectPart[] parts = m_parts.GetArray(); 438 SceneObjectPart[] parts = m_parts.GetArray();
361 for (int i = 0; i < parts.Length; i++) 439 for (int i = 0; i < parts.Length; i++)
362 { 440 {
363 SceneObjectPart part = parts[i]; 441 SceneObjectPart part = parts[i];
364 Vector3 partscale = part.Scale; 442 Vector3 partscale = part.Scale;
365 Vector3 partoffset = part.OffsetPosition; 443 Vector3 partoffset = part.OffsetPosition;
366 444
367 minScale.X = (partscale.X + partoffset.X < minScale.X) ? partscale.X + partoffset.X : minScale.X; 445 minScale.X = (partscale.X + partoffset.X < minScale.X) ? partscale.X + partoffset.X : minScale.X;
368 minScale.Y = (partscale.Y + partoffset.Y < minScale.Y) ? partscale.Y + partoffset.Y : minScale.Y; 446 minScale.Y = (partscale.Y + partoffset.Y < minScale.Y) ? partscale.Y + partoffset.Y : minScale.Y;
369 minScale.Z = (partscale.Z + partoffset.Z < minScale.Z) ? partscale.Z + partoffset.Z : minScale.Z; 447 minScale.Z = (partscale.Z + partoffset.Z < minScale.Z) ? partscale.Z + partoffset.Z : minScale.Z;
370 448
371 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X; 449 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X;
372 maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y; 450 maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y;
373 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z; 451 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z;
374 } 452 }
375 453
376 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; 454 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X;
377 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; 455 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y;
378 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z; 456 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z;
379 457
380 return finalScale; 458 return finalScale;
381 } 459 }
382 } 460 }
@@ -441,7 +519,7 @@ namespace OpenSim.Region.Framework.Scenes
441 /// <remarks> 519 /// <remarks>
442 /// This is necessary in some cases, particularly when a scene object has just crossed into a region and doesn't 520 /// This is necessary in some cases, particularly when a scene object has just crossed into a region and doesn't
443 /// have the IsAttachment property yet checked. 521 /// have the IsAttachment property yet checked.
444 /// 522 ///
445 /// FIXME: However, this should be fixed so that this property 523 /// FIXME: However, this should be fixed so that this property
446 /// propertly reflects the underlying status. 524 /// propertly reflects the underlying status.
447 /// </remarks> 525 /// </remarks>
@@ -451,13 +529,17 @@ namespace OpenSim.Region.Framework.Scenes
451 return (IsAttachment || 529 return (IsAttachment ||
452 (m_rootPart.Shape.PCode == (byte)PCodeEnum.Primitive && m_rootPart.Shape.State != 0)); 530 (m_rootPart.Shape.PCode == (byte)PCodeEnum.Primitive && m_rootPart.Shape.State != 0));
453 } 531 }
454 532
455 private struct avtocrossInfo 533 private struct avtocrossInfo
456 { 534 {
457 public ScenePresence av; 535 public ScenePresence av;
458 public uint ParentID; 536 public uint ParentID;
459 } 537 }
460 538
539
540 public bool inTransit = false;
541 private delegate SceneObjectGroup SOGCrossDelegate(SceneObjectGroup sog,Vector3 pos, TeleportObjectData tpData);
542
461 /// <summary> 543 /// <summary>
462 /// The absolute position of this scene object in the scene 544 /// The absolute position of this scene object in the scene
463 /// </summary> 545 /// </summary>
@@ -467,205 +549,547 @@ namespace OpenSim.Region.Framework.Scenes
467 set 549 set
468 { 550 {
469 Vector3 val = value; 551 Vector3 val = value;
552 if (Scene != null
553 && !Scene.PositionIsInCurrentRegion(val)
554 && !IsAttachmentCheckFull()
555 && !Scene.LoadingPrims
556 && !Scene.DisableObjectTransfer
557 )
558 {
559 if (!inTransit)
560 {
561 inTransit = true;
562 SOGCrossDelegate d = CrossAsync;
563 d.BeginInvoke(this, val, null, CrossAsyncCompleted, d);
564 }
565 return;
566 }
567
568 if (RootPart.GetStatusSandbox())
569 {
570 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
571 {
572 RootPart.ScriptSetPhysicsStatus(false);
573
574 if (Scene != null)
575 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"),
576 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false);
577
578 return;
579 }
580 }
581
582 bool triggerScriptEvent = m_rootPart.GroupPosition != val;
583 if (m_dupeInProgress || IsDeleted)
584 triggerScriptEvent = false;
585
586 m_rootPart.GroupPosition = val;
587
588 // Restuff the new GroupPosition into each child SOP of the linkset.
589 // this is needed because physics may not have linksets but just loose SOPs in world
590
591 SceneObjectPart[] parts = m_parts.GetArray();
592
593 foreach (SceneObjectPart part in parts)
594 {
595 if (part != m_rootPart)
596 part.GroupPosition = val;
597 }
598
599 foreach (ScenePresence av in m_sittingAvatars)
600 {
601 av.sitSOGmoved();
602 }
603
604 // now that position is changed tell it to scripts
605 if (triggerScriptEvent)
606 {
607 foreach (SceneObjectPart part in parts)
608 {
609 part.TriggerScriptChangedEvent(Changed.POSITION);
610 }
611 }
470 612
471 if (Scene != null) 613 if (Scene != null)
614 Scene.EventManager.TriggerParcelPrimCountTainted();
615
616 }
617 }
618
619 private SceneObjectGroup CrossAsync(SceneObjectGroup sog, Vector3 val, TeleportObjectData tpdata)
620 {
621 Scene sogScene = sog.m_scene;
622 SceneObjectPart root = sog.RootPart;
623
624 bool isTeleport = tpdata != null;
625
626 if(!isTeleport)
627 {
628 if (root.DIE_AT_EDGE)
472 { 629 {
473 if ( 630 try
474 !Scene.PositionIsInCurrentRegion(val)
475 && !IsAttachmentCheckFull()
476 && (!Scene.LoadingPrims)
477 )
478 { 631 {
479 IEntityTransferModule entityTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); 632 sogScene.DeleteSceneObject(sog, false);
480 EntityTransferContext ctx = new EntityTransferContext(); 633 }
481 Vector3 newpos = Vector3.Zero; 634 catch (Exception)
482 string failureReason = String.Empty; 635 {
483 OpenSim.Services.Interfaces.GridRegion destination = null; 636 m_log.Warn("[SCENE]: exception when trying to remove the prim that crossed the border.");
637 }
638 return sog;
639 }
484 640
485 if (m_rootPart.KeyframeMotion != null) 641 if (root.RETURN_AT_EDGE)
486 m_rootPart.KeyframeMotion.StartCrossingCheck(); 642 {
643 // We remove the object here
644 try
645 {
646 List<uint> localIDs = new List<uint>();
647 localIDs.Add(root.LocalId);
648 sogScene.AddReturn(sog.OwnerID, sog.Name, sog.AbsolutePosition,
649 "Returned at region cross");
650 sogScene.DeRezObjects(null, localIDs, UUID.Zero, DeRezAction.Return, UUID.Zero, false);
651 }
652 catch (Exception)
653 {
654 m_log.Warn("[SCENE]: exception when trying to return the prim that crossed the border.");
655 }
656 return sog;
657 }
658 }
487 659
488 bool canCross = true; 660// if(!m_scene.IsRunning)
489 foreach (ScenePresence av in GetSittingAvatars()) 661// return sog;
490 {
491 // We need to cross these agents. First, let's find
492 // out if any of them can't cross for some reason.
493 // We have to deny the crossing entirely if any
494 // of them are banned. Alternatively, we could
495 // unsit banned agents....
496 662
663 if (root.KeyframeMotion != null)
664 root.KeyframeMotion.StartCrossingCheck();
497 665
498 // We set the avatar position as being the object 666 if(root.PhysActor != null)
499 // position to get the region to send to 667 root.PhysActor.CrossingStart();
500 if ((destination = entityTransfer.GetDestination(m_scene, av.UUID, val, ctx, out newpos, out failureReason)) == null)
501 {
502 canCross = false;
503 break;
504 }
505 668
506 m_log.DebugFormat("[SCENE OBJECT]: Avatar {0} needs to be crossed to {1}", av.Name, destination.RegionName); 669 IEntityTransferModule entityTransfer = sogScene.RequestModuleInterface<IEntityTransferModule>();
507 }
508 670
509 if (canCross) 671 if (entityTransfer == null)
510 { 672 return sog;
511 // We unparent the SP quietly so that it won't
512 // be made to stand up
513 673
514 List<avtocrossInfo> avsToCross = new List<avtocrossInfo>(); 674 Vector3 newpos = Vector3.Zero;
675 OpenSim.Services.Interfaces.GridRegion destination = null;
515 676
516 foreach (ScenePresence av in GetSittingAvatars()) 677 destination = entityTransfer.GetObjectDestination(sog, val, out newpos);
517 { 678 if (destination == null)
518 avtocrossInfo avinfo = new avtocrossInfo(); 679 return sog;
519 SceneObjectPart parentPart = m_scene.GetSceneObjectPart(av.ParentID);
520 if (parentPart != null)
521 av.ParentUUID = parentPart.UUID;
522 680
523 avinfo.av = av; 681 if (sog.m_sittingAvatars.Count == 0)
524 avinfo.ParentID = av.ParentID; 682 {
525 avsToCross.Add(avinfo); 683 entityTransfer.CrossPrimGroupIntoNewRegion(destination, newpos, sog, !isTeleport, true);
684 return sog;
685 }
526 686
527 av.PrevSitOffset = av.OffsetPosition; 687 string reason = String.Empty;
528 av.ParentID = 0; 688 EntityTransferContext ctx = new EntityTransferContext();
529 }
530 689
531 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 690 Vector3 curPos = root.GroupPosition;
691 foreach (ScenePresence av in sog.m_sittingAvatars)
692 {
693 // We need to cross these agents. First, let's find
694 // out if any of them can't cross for some reason.
695 // We have to deny the crossing entirely if any
696 // of them are banned. Alternatively, we could
697 // unsit banned agents....
698
699 // We set the avatar position as being the object
700 // position to get the region to send to
701 if(av.IsNPC)
702 continue;
532 703
533 // Normalize 704 if(av.IsInTransit)
534 if (val.X >= m_scene.RegionInfo.RegionSizeX) 705 return sog;
535 val.X -= m_scene.RegionInfo.RegionSizeX;
536 if (val.Y >= m_scene.RegionInfo.RegionSizeY)
537 val.Y -= m_scene.RegionInfo.RegionSizeY;
538 if (val.X < 0)
539 val.X += m_scene.RegionInfo.RegionSizeX;
540 if (val.Y < 0)
541 val.Y += m_scene.RegionInfo.RegionSizeY;
542 706
543 // If it's deleted, crossing was successful 707 if(!entityTransfer.checkAgentAccessToRegion(av, destination, newpos, ctx, out reason))
544 if (IsDeleted) 708 return sog;
545 {
546 foreach (avtocrossInfo avinfo in avsToCross)
547 {
548 ScenePresence av = avinfo.av;
549 if (!av.IsInTransit) // just in case...
550 {
551 m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar {0} to {1}", av.Name, val);
552
553 av.IsInTransit = true;
554
555 // A temporary measure to allow regression tests to work.
556 // Quite possibly, all BeginInvoke() calls should be replaced by Util.FireAndForget
557 // or similar since BeginInvoke() always uses the system threadpool to launch
558 // threads rather than any replace threadpool that we might be using.
559 if (Util.FireAndForgetMethod == FireAndForgetMethod.RegressionTest)
560 {
561 entityTransfer.CrossAgentToNewRegionAsync(av, val, destination, av.Flying, ctx);
562 CrossAgentToNewRegionCompleted(av);
563 }
564 else
565 {
566 CrossAgentToNewRegionDelegate d = entityTransfer.CrossAgentToNewRegionAsync;
567 d.BeginInvoke(
568 av, val, destination, av.Flying, ctx,
569 ar => CrossAgentToNewRegionCompleted(d.EndInvoke(ar)), null);
570 }
571 }
572 else
573 {
574 m_log.DebugFormat("[SCENE OBJECT]: Not crossing avatar {0} to {1} because it's already in transit", av.Name, val);
575 }
576 }
577 709
578 return; 710 m_log.DebugFormat("[SCENE OBJECT]: Avatar {0} needs to be crossed to {1}", av.Name, destination.RegionName);
579 } 711 }
580 else // cross failed, put avas back ?? 712
713 // We unparent the SP quietly so that it won't
714 // be made to stand up
715
716 List<avtocrossInfo> avsToCross = new List<avtocrossInfo>();
717 List<ScenePresence> avsToCrossFar = new List<ScenePresence>();
718 ulong destHandle = destination.RegionHandle;
719 List<ScenePresence> sittingAvatars = GetSittingAvatars();
720 foreach (ScenePresence av in sittingAvatars)
721 {
722 byte cflags = 1;
723
724 avtocrossInfo avinfo = new avtocrossInfo();
725 SceneObjectPart parentPart = sogScene.GetSceneObjectPart(av.ParentID);
726 if (parentPart != null)
727 {
728 av.ParentUUID = parentPart.UUID;
729 if(parentPart.SitTargetAvatar == av.UUID)
730 cflags = 7; // low 3 bits set
731 else
732 cflags = 3;
733 }
734 if(!av.knowsNeighbourRegion(destHandle))
735 cflags |= 8;
736
737 // 1 is crossing
738 // 2 is sitting
739 // 4 is sitting at sittarget
740 // 8 far crossing
741
742 avinfo.av = av;
743 avinfo.ParentID = av.ParentID;
744 avsToCross.Add(avinfo);
745
746 if(!av.knowsNeighbourRegion(destHandle))
747 {
748 cflags |= 8;
749 avsToCrossFar.Add(av);
750 }
751
752 if(av.IsNPC)
753 av.crossingFlags = 0;
754 else
755 av.crossingFlags = cflags;
756
757 av.PrevSitOffset = av.OffsetPosition;
758 av.ParentID = 0;
759 }
760
761 Vector3 vel = root.Velocity;
762 Vector3 avel = root.AngularVelocity;
763 Vector3 acc = root.Acceleration;
764 Quaternion ori = root.RotationOffset;
765
766 if(isTeleport)
767 {
768 root.Stop();
769 sogScene.ForEachScenePresence(delegate(ScenePresence av)
770 {
771 av.ControllingClient.SendEntityUpdate(root,PrimUpdateFlags.SendInTransit);
772 av.ControllingClient.SendEntityTerseUpdateImmediate(root);
773 });
774
775 root.Velocity = tpdata.vel;
776 root.AngularVelocity = tpdata.avel;
777 root.Acceleration = tpdata.acc;
778 root.RotationOffset = tpdata.ori;
779 }
780
781 if (entityTransfer.CrossPrimGroupIntoNewRegion(destination, newpos, sog, true, false))
782 {
783 if(isTeleport)
784 {
785 sogScene.ForEachScenePresence(delegate(ScenePresence oav)
786 {
787 if(sittingAvatars.Contains(oav))
788 return;
789 if(oav.knowsNeighbourRegion(destHandle))
790 return;
791 oav.ControllingClient.SendEntityUpdate(root, PrimUpdateFlags.Kill);
792 foreach (ScenePresence sav in sittingAvatars)
793 {
794 sav.SendKillTo(oav);
795 }
796 });
797 }
798 bool crossedfar = false;
799 foreach (ScenePresence av in avsToCrossFar)
800 {
801 if(entityTransfer.CrossAgentCreateFarChild(av,destination, newpos, ctx))
802 crossedfar = true;
803 else
804 av.crossingFlags = 0;
805 }
806
807 if(crossedfar)
808 Thread.Sleep(1000);
809
810 foreach (avtocrossInfo avinfo in avsToCross)
811 {
812 ScenePresence av = avinfo.av;
813 av.IsInLocalTransit = true;
814 av.IsInTransit = true;
815 m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar {0} to {1}", av.Name, val);
816
817 if(av.crossingFlags > 0)
818 entityTransfer.CrossAgentToNewRegionAsync(av, newpos, destination, false, ctx);
819
820 if (av.IsChildAgent)
821 {
822 // avatar crossed do some extra cleanup
823 if (av.ParentUUID != UUID.Zero)
824 {
825 av.ClearControls();
826 av.ParentPart = null;
827 }
828 av.ParentUUID = UUID.Zero;
829 av.ParentPart = null;
830 // In any case
831 av.IsInTransit = false;
832 av.crossingFlags = 0;
833 m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", av.Firstname, av.Lastname);
834 }
835 else
836 {
837 // avatar cross failed we need do dedicated standUp
838 // part of it was done at CrossAgentToNewRegionAsync
839 // so for now just remove the sog controls
840 // this may need extra care
841 av.UnRegisterSeatControls(sog.UUID);
842 av.ParentUUID = UUID.Zero;
843 av.ParentPart = null;
844 Vector3 oldp = curPos;
845 oldp.X = Util.Clamp<float>(oldp.X, 0.5f, sog.m_scene.RegionInfo.RegionSizeX - 0.5f);
846 oldp.Y = Util.Clamp<float>(oldp.Y, 0.5f, sog.m_scene.RegionInfo.RegionSizeY - 0.5f);
847 av.AbsolutePosition = oldp;
848 av.crossingFlags = 0;
849 av.sitAnimation = "SIT";
850 av.IsInTransit = false;
851 if(av.Animator!= null)
852 av.Animator.SetMovementAnimations("STAND");
853 av.AddToPhysicalScene(false);
854 sogScene.ForEachScenePresence(delegate(ScenePresence oav)
581 { 855 {
582 foreach (avtocrossInfo avinfo in avsToCross) 856 if(sittingAvatars.Contains(oav))
857 return;
858 if(oav.knowsNeighbourRegion(destHandle))
859 av.SendAvatarDataToAgent(oav);
860 else
583 { 861 {
584 ScenePresence av = avinfo.av; 862 av.SendAvatarDataToAgent(oav);
585 av.ParentUUID = UUID.Zero; 863 av.SendAppearanceToAgent(oav);
586 av.ParentID = avinfo.ParentID; 864 if (av.Animator != null)
865 av.Animator.SendAnimPackToClient(oav.ControllingClient);
866 av.SendAttachmentsToAgentNF(oav); // not ok
587 } 867 }
588 } 868 });
589 } 869 m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} failed.", av.Firstname, av.Lastname);
590 else 870 }
591 { 871 }
592 if (m_rootPart.KeyframeMotion != null)
593 m_rootPart.KeyframeMotion.CrossingFailure();
594 872
595 if (RootPart.PhysActor != null) 873 if(crossedfar)
596 { 874 {
597 RootPart.PhysActor.CrossingFailure(); 875 Thread.Sleep(10000);
598 } 876 foreach (ScenePresence av in avsToCrossFar)
877 {
878 if(av.IsChildAgent)
879 {
880 av.Scene.CloseAgent(av.UUID, false);
599 } 881 }
600 882 else
601 Vector3 oldp = AbsolutePosition; 883 av.RemoveNeighbourRegion(destHandle);
602 val.X = Util.Clamp<float>(oldp.X, 0.5f, (float)m_scene.RegionInfo.RegionSizeX - 0.5f);
603 val.Y = Util.Clamp<float>(oldp.Y, 0.5f, (float)m_scene.RegionInfo.RegionSizeY - 0.5f);
604 val.Z = Util.Clamp<float>(oldp.Z, 0.5f, Constants.RegionHeight);
605 } 884 }
606 } 885 }
607 886 avsToCrossFar.Clear();
608 if (RootPart.GetStatusSandbox()) 887 avsToCross.Clear();
888 sog.RemoveScriptInstances(true);
889 sog.Clear();
890 return sog;
891 }
892 else
893 {
894 if(isTeleport)
609 { 895 {
610 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 896 if((tpdata.flags & OSTPOBJ_STOPONFAIL) == 0)
611 { 897 {
612 RootPart.ScriptSetPhysicsStatus(false); 898 root.Velocity = vel;
613 899 root.AngularVelocity = avel;
614 if (Scene != null) 900 root.Acceleration = acc;
615 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"),
616 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false);
617
618 return;
619 } 901 }
902 root.RotationOffset = ori;
903 }
904 foreach (avtocrossInfo avinfo in avsToCross)
905 {
906 ScenePresence av = avinfo.av;
907 av.ParentUUID = UUID.Zero;
908 av.ParentID = avinfo.ParentID;
909 av.crossingFlags = 0;
620 } 910 }
911 }
912 avsToCross.Clear();
913 return sog;
914 }
621 915
622 // Restuff the new GroupPosition into each SOP of the linkset. 916 public void CrossAsyncCompleted(IAsyncResult iar)
623 // This has the affect of resetting and tainting the physics actors. 917 {
624 SceneObjectPart[] parts = m_parts.GetArray(); 918 SOGCrossDelegate icon = (SOGCrossDelegate)iar.AsyncState;
625 for (int i = 0; i < parts.Length; i++) 919 SceneObjectGroup sog = icon.EndInvoke(iar);
626 parts[i].GroupPosition = val;
627 920
628 //if (m_rootPart.PhysActor != null) 921 if (!sog.IsDeleted)
629 //{ 922 {
630 //m_rootPart.PhysActor.Position = 923 SceneObjectPart rootp = sog.m_rootPart;
631 //new PhysicsVector(m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y, 924
632 //m_rootPart.GroupPosition.Z); 925 Vector3 oldp = rootp.GroupPosition;
633 //m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); 926 oldp.X = Util.Clamp<float>(oldp.X, 0.5f, sog.m_scene.RegionInfo.RegionSizeX - 0.5f);
634 //} 927 oldp.Y = Util.Clamp<float>(oldp.Y, 0.5f, sog.m_scene.RegionInfo.RegionSizeY - 0.5f);
635 928 rootp.GroupPosition = oldp;
636 if (Scene != null) 929
637 Scene.EventManager.TriggerParcelPrimCountTainted(); 930 rootp.Stop();
931
932 SceneObjectPart[] parts = sog.m_parts.GetArray();
933
934 foreach (SceneObjectPart part in parts)
935 {
936 if (part != rootp)
937 part.GroupPosition = oldp;
938 }
939
940 foreach (ScenePresence av in sog.m_sittingAvatars)
941 {
942 av.sitSOGmoved();
943 }
944
945 if (sog.m_rootPart.KeyframeMotion != null)
946 sog.m_rootPart.KeyframeMotion.CrossingFailure();
947
948 if (sog.RootPart.PhysActor != null)
949 sog.RootPart.PhysActor.CrossingFailure();
950
951 sog.inTransit = false;
952 AttachToBackup();
953 sog.ScheduleGroupForFullUpdate();
638 } 954 }
639 } 955 }
640 956
641 public override Vector3 Velocity 957 private class TeleportObjectData
642 { 958 {
643 get { return RootPart.Velocity; } 959 public int flags;
644 set { RootPart.Velocity = value; } 960 public Vector3 vel;
961 public Vector3 avel;
962 public Vector3 acc;
963 public Quaternion ori;
964 public UUID sourceID;
645 } 965 }
646 966
647 private void CrossAgentToNewRegionCompleted(ScenePresence agent) 967 // copy from LSL_constants.cs
968 const int OSTPOBJ_STOPATTARGET = 0x1; // stops at destination
969 const int OSTPOBJ_STOPONFAIL = 0x2; // stops at start if tp fails
970 const int OSTPOBJ_SETROT = 0x4; // the rotation is the final rotation, otherwise is a added rotation
971
972 public int TeleportObject(UUID sourceID, Vector3 targetPosition, Quaternion rotation, int flags)
648 { 973 {
649 //// If the cross was successful, this agent is a child agent 974 if(inTransit || IsDeleted || IsAttachmentCheckFull() || IsSelected || Scene == null)
650 if (agent.IsChildAgent) 975 return -1;
976
977 inTransit = true;
978
979 PhysicsActor pa = RootPart.PhysActor;
980 if(pa == null || RootPart.KeyframeMotion != null /*|| m_sittingAvatars.Count == 0*/)
651 { 981 {
652 if (agent.ParentUUID != UUID.Zero) 982 inTransit = false;
983 return -1;
984 }
985
986 bool stop = (flags & OSTPOBJ_STOPATTARGET) != 0;
987 bool setrot = (flags & OSTPOBJ_SETROT) != 0;
988
989 rotation.Normalize();
990
991 Quaternion currentRot = RootPart.RotationOffset;
992 if(setrot)
993 rotation = Quaternion.Conjugate(currentRot) * rotation;
994
995 bool dorot = setrot | (Math.Abs(rotation.W) < 0.99999);
996
997 Vector3 vel = Vector3.Zero;
998 Vector3 avel = Vector3.Zero;
999 Vector3 acc = Vector3.Zero;
1000
1001 if(!stop)
1002 {
1003 vel = RootPart.Velocity;
1004 avel = RootPart.AngularVelocity;
1005 acc = RootPart.Acceleration;
1006 }
1007 Quaternion ori = RootPart.RotationOffset;
1008
1009 if(dorot)
1010 {
1011 if(!stop)
653 { 1012 {
654 agent.ParentPart = null; 1013 vel *= rotation;
655// agent.ParentPosition = Vector3.Zero; 1014 avel *= rotation;
656// agent.ParentUUID = UUID.Zero; 1015 acc *= rotation;
657 } 1016 }
1017 ori *= rotation;
658 } 1018 }
659 1019
660 agent.ParentUUID = UUID.Zero; 1020 if(Scene.PositionIsInCurrentRegion(targetPosition))
661// agent.Reset(); 1021 {
662// else // Not successful 1022 if(Scene.InTeleportTargetsCoolDown(UUID, sourceID, 1.0))
663// agent.RestoreInCurrentScene(); 1023 {
1024 inTransit = false;
1025 return -2;
1026 }
1027
1028 Vector3 curPos = AbsolutePosition;
1029 ILandObject curLand = Scene.LandChannel.GetLandObject(curPos.X, curPos.Y);
1030 float posX = targetPosition.X;
1031 float posY = targetPosition.Y;
1032 ILandObject land = Scene.LandChannel.GetLandObject(posX, posY);
1033 if(land != null && land != curLand)
1034 {
1035 if(!Scene.Permissions.CanObjectEnterWithScripts(this, land))
1036 {
1037 inTransit = false;
1038 return -3;
1039 }
1040
1041 UUID agentID;
1042 foreach (ScenePresence av in m_sittingAvatars)
1043 {
1044 agentID = av.UUID;
1045 if(land.IsRestrictedFromLand(agentID) || land.IsBannedFromLand(agentID))
1046 {
1047 inTransit = false;
1048 return -4;
1049 }
1050 }
1051 }
664 1052
665 // In any case 1053 RootPart.Velocity = vel;
666 agent.IsInTransit = false; 1054 RootPart.AngularVelocity = avel;
1055 RootPart.Acceleration = acc;
1056 RootPart.RotationOffset = ori;
667 1057
668 m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname); 1058 Vector3 s = RootPart.Scale * RootPart.RotationOffset;
1059 float h = Scene.GetGroundHeight(posX, posY) + 0.5f * (float)Math.Abs(s.Z) + 0.01f;
1060 if(targetPosition.Z < h)
1061 targetPosition.Z = h;
1062
1063 inTransit = false;
1064 AbsolutePosition = targetPosition;
1065 RootPart.ScheduleTerseUpdate();
1066 return 1;
1067 }
1068
1069 if(Scene.InTeleportTargetsCoolDown(UUID, sourceID, 20.0))
1070 {
1071 inTransit = false;
1072 return -1;
1073 }
1074
1075 TeleportObjectData tdata = new TeleportObjectData();
1076 tdata.flags = flags;
1077 tdata.vel = vel;
1078 tdata.avel = avel;
1079 tdata.acc = acc;
1080 tdata.ori = ori;
1081 tdata.sourceID = sourceID;
1082
1083
1084 SOGCrossDelegate d = CrossAsync;
1085 d.BeginInvoke(this, targetPosition, tdata, CrossAsyncCompleted, d);
1086 return 0;
1087 }
1088
1089 public override Vector3 Velocity
1090 {
1091 get { return RootPart.Velocity; }
1092 set { RootPart.Velocity = value; }
669 } 1093 }
670 1094
671 public override uint LocalId 1095 public override uint LocalId
@@ -677,7 +1101,7 @@ namespace OpenSim.Region.Framework.Scenes
677 public override UUID UUID 1101 public override UUID UUID
678 { 1102 {
679 get { return m_rootPart.UUID; } 1103 get { return m_rootPart.UUID; }
680 set 1104 set
681 { 1105 {
682 lock (m_parts.SyncRoot) 1106 lock (m_parts.SyncRoot)
683 { 1107 {
@@ -694,6 +1118,12 @@ namespace OpenSim.Region.Framework.Scenes
694 set { m_rootPart.LastOwnerID = value; } 1118 set { m_rootPart.LastOwnerID = value; }
695 } 1119 }
696 1120
1121 public UUID RezzerID
1122 {
1123 get { return m_rootPart.RezzerID; }
1124 set { m_rootPart.RezzerID = value; }
1125 }
1126
697 public UUID OwnerID 1127 public UUID OwnerID
698 { 1128 {
699 get { return m_rootPart.OwnerID; } 1129 get { return m_rootPart.OwnerID; }
@@ -733,7 +1163,7 @@ namespace OpenSim.Region.Framework.Scenes
733 { 1163 {
734 get { return true; } 1164 get { return true; }
735 } 1165 }
736 1166
737 public bool IsSelected 1167 public bool IsSelected
738 { 1168 {
739 get { return m_isSelected; } 1169 get { return m_isSelected; }
@@ -742,6 +1172,11 @@ namespace OpenSim.Region.Framework.Scenes
742 m_isSelected = value; 1172 m_isSelected = value;
743 // Tell physics engine that group is selected 1173 // Tell physics engine that group is selected
744 1174
1175 // this is not right
1176 // but ode engines should only really need to know about root part
1177 // so they can put entire object simulation on hold and not colliding
1178 // keep as was for now
1179
745 PhysicsActor pa = m_rootPart.PhysActor; 1180 PhysicsActor pa = m_rootPart.PhysActor;
746 if (pa != null) 1181 if (pa != null)
747 { 1182 {
@@ -763,13 +1198,47 @@ namespace OpenSim.Region.Framework.Scenes
763 } 1198 }
764 } 1199 }
765 1200
1201 public void PartSelectChanged(bool partSelect)
1202 {
1203 // any part selected makes group selected
1204 if (m_isSelected == partSelect)
1205 return;
1206
1207 if (partSelect)
1208 {
1209 IsSelected = partSelect;
1210// if (!IsAttachment)
1211// ScheduleGroupForFullUpdate();
1212 }
1213 else
1214 {
1215 // bad bad bad 2 heavy for large linksets
1216 // since viewer does send lot of (un)selects
1217 // this needs to be replaced by a specific list or count ?
1218 // but that will require extra code in several places
1219
1220 SceneObjectPart[] parts = m_parts.GetArray();
1221 for (int i = 0; i < parts.Length; i++)
1222 {
1223 SceneObjectPart part = parts[i];
1224 if (part.IsSelected)
1225 return;
1226 }
1227 IsSelected = partSelect;
1228// if (!IsAttachment)
1229// {
1230// ScheduleGroupForFullUpdate();
1231// }
1232 }
1233 }
1234 // PlaySoundMasterPrim no longer in use to remove
766 private SceneObjectPart m_PlaySoundMasterPrim = null; 1235 private SceneObjectPart m_PlaySoundMasterPrim = null;
767 public SceneObjectPart PlaySoundMasterPrim 1236 public SceneObjectPart PlaySoundMasterPrim
768 { 1237 {
769 get { return m_PlaySoundMasterPrim; } 1238 get { return m_PlaySoundMasterPrim; }
770 set { m_PlaySoundMasterPrim = value; } 1239 set { m_PlaySoundMasterPrim = value; }
771 } 1240 }
772 1241 // PlaySoundSlavePrims no longer in use to remove
773 private List<SceneObjectPart> m_PlaySoundSlavePrims = new List<SceneObjectPart>(); 1242 private List<SceneObjectPart> m_PlaySoundSlavePrims = new List<SceneObjectPart>();
774 public List<SceneObjectPart> PlaySoundSlavePrims 1243 public List<SceneObjectPart> PlaySoundSlavePrims
775 { 1244 {
@@ -777,6 +1246,7 @@ namespace OpenSim.Region.Framework.Scenes
777 set { m_PlaySoundSlavePrims = value; } 1246 set { m_PlaySoundSlavePrims = value; }
778 } 1247 }
779 1248
1249 // LoopSoundMasterPrim no longer in use to remove
780 private SceneObjectPart m_LoopSoundMasterPrim = null; 1250 private SceneObjectPart m_LoopSoundMasterPrim = null;
781 public SceneObjectPart LoopSoundMasterPrim 1251 public SceneObjectPart LoopSoundMasterPrim
782 { 1252 {
@@ -784,6 +1254,7 @@ namespace OpenSim.Region.Framework.Scenes
784 set { m_LoopSoundMasterPrim = value; } 1254 set { m_LoopSoundMasterPrim = value; }
785 } 1255 }
786 1256
1257 // m_LoopSoundSlavePrims no longer in use to remove
787 private List<SceneObjectPart> m_LoopSoundSlavePrims = new List<SceneObjectPart>(); 1258 private List<SceneObjectPart> m_LoopSoundSlavePrims = new List<SceneObjectPart>();
788 public List<SceneObjectPart> LoopSoundSlavePrims 1259 public List<SceneObjectPart> LoopSoundSlavePrims
789 { 1260 {
@@ -791,6 +1262,8 @@ namespace OpenSim.Region.Framework.Scenes
791 set { m_LoopSoundSlavePrims = value; } 1262 set { m_LoopSoundSlavePrims = value; }
792 } 1263 }
793 1264
1265 private double m_lastCollisionSoundMS;
1266
794 /// <summary> 1267 /// <summary>
795 /// The UUID for the region this object is in. 1268 /// The UUID for the region this object is in.
796 /// </summary> 1269 /// </summary>
@@ -820,7 +1293,12 @@ namespace OpenSim.Region.Framework.Scenes
820 /// <remarks> 1293 /// <remarks>
821 /// If not applicable will be UUID.Zero 1294 /// If not applicable will be UUID.Zero
822 /// </remarks> 1295 /// </remarks>
823 public UUID FromPartID { get; set; } 1296 /// obsolete use RezzerID
1297 public UUID FromPartID
1298 {
1299 get { return RezzerID; }
1300 set {RezzerID = value; }
1301 }
824 1302
825 /// <summary> 1303 /// <summary>
826 /// The folder ID that this object was rezzed from, if applicable. 1304 /// The folder ID that this object was rezzed from, if applicable.
@@ -863,6 +1341,7 @@ namespace OpenSim.Region.Framework.Scenes
863 /// </summary> 1341 /// </summary>
864 public SceneObjectGroup() 1342 public SceneObjectGroup()
865 { 1343 {
1344 m_lastCollisionSoundMS = Util.GetTimeStampMS() + 1000.0;
866 } 1345 }
867 1346
868 /// <summary> 1347 /// <summary>
@@ -880,8 +1359,8 @@ namespace OpenSim.Region.Framework.Scenes
880 /// Constructor. This object is added to the scene later via AttachToScene() 1359 /// Constructor. This object is added to the scene later via AttachToScene()
881 /// </summary> 1360 /// </summary>
882 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 1361 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
883 :this(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)) 1362 {
884 { 1363 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
885 } 1364 }
886 1365
887 /// <summary> 1366 /// <summary>
@@ -907,7 +1386,7 @@ namespace OpenSim.Region.Framework.Scenes
907 if (itemid != UUID.Zero) 1386 if (itemid != UUID.Zero)
908 m_savedScriptState[itemid] = node.InnerXml; 1387 m_savedScriptState[itemid] = node.InnerXml;
909 } 1388 }
910 } 1389 }
911 } 1390 }
912 } 1391 }
913 1392
@@ -940,7 +1419,7 @@ namespace OpenSim.Region.Framework.Scenes
940 } 1419 }
941 else 1420 else
942 { 1421 {
943 m_log.WarnFormat("[SCENE OBJECT GROUP]: SavedScriptState element had no UUID in object {0}", Name); 1422 m_log.WarnFormat("[SCENE OBJECT GROUP]: SavedScriptState element had no UUID in object {0} id: {1}", Name,UUID);
944 } 1423 }
945 } 1424 }
946 else 1425 else
@@ -956,18 +1435,21 @@ namespace OpenSim.Region.Framework.Scenes
956 /// </summary> 1435 /// </summary>
957 public virtual void AttachToBackup() 1436 public virtual void AttachToBackup()
958 { 1437 {
959 if (CanBeBackedUp) 1438 if (IsAttachment) return;
1439 m_scene.SceneGraph.FireAttachToBackup(this);
1440
1441// if (InSceneBackup)
960 { 1442 {
961// m_log.DebugFormat( 1443// m_log.DebugFormat(
962// "[SCENE OBJECT GROUP]: Attaching object {0} {1} to scene presistence sweep", Name, UUID); 1444// "[SCENE OBJECT GROUP]: Attaching object {0} {1} to scene presistence sweep", Name, UUID);
963 1445
964 if (!Backup) 1446 if (!Backup)
965 m_scene.EventManager.OnBackup += ProcessBackup; 1447 m_scene.EventManager.OnBackup += ProcessBackup;
966 1448
967 Backup = true; 1449 Backup = true;
968 } 1450 }
969 } 1451 }
970 1452
971 /// <summary> 1453 /// <summary>
972 /// Attach this object to a scene. It will also now appear to agents. 1454 /// Attach this object to a scene. It will also now appear to agents.
973 /// </summary> 1455 /// </summary>
@@ -1018,6 +1500,10 @@ namespace OpenSim.Region.Framework.Scenes
1018 EntityIntersection result = new EntityIntersection(); 1500 EntityIntersection result = new EntityIntersection();
1019 1501
1020 SceneObjectPart[] parts = m_parts.GetArray(); 1502 SceneObjectPart[] parts = m_parts.GetArray();
1503
1504 // Find closest hit here
1505 float idist = float.MaxValue;
1506
1021 for (int i = 0; i < parts.Length; i++) 1507 for (int i = 0; i < parts.Length; i++)
1022 { 1508 {
1023 SceneObjectPart part = parts[i]; 1509 SceneObjectPart part = parts[i];
@@ -1032,11 +1518,6 @@ namespace OpenSim.Region.Framework.Scenes
1032 1518
1033 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters); 1519 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters);
1034 1520
1035 // This may need to be updated to the maximum draw distance possible..
1036 // We might (and probably will) be checking for prim creation from other sims
1037 // when the camera crosses the border.
1038 float idist = Constants.RegionSize;
1039
1040 if (inter.HitTF) 1521 if (inter.HitTF)
1041 { 1522 {
1042 // We need to find the closest prim to return to the testcaller along the ray 1523 // We need to find the closest prim to return to the testcaller along the ray
@@ -1047,10 +1528,11 @@ namespace OpenSim.Region.Framework.Scenes
1047 result.obj = part; 1528 result.obj = part;
1048 result.normal = inter.normal; 1529 result.normal = inter.normal;
1049 result.distance = inter.distance; 1530 result.distance = inter.distance;
1531
1532 idist = inter.distance;
1050 } 1533 }
1051 } 1534 }
1052 } 1535 }
1053
1054 return result; 1536 return result;
1055 } 1537 }
1056 1538
@@ -1062,25 +1544,27 @@ namespace OpenSim.Region.Framework.Scenes
1062 /// <returns></returns> 1544 /// <returns></returns>
1063 public void GetAxisAlignedBoundingBoxRaw(out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) 1545 public void GetAxisAlignedBoundingBoxRaw(out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ)
1064 { 1546 {
1065 maxX = -256f; 1547 maxX = float.MinValue;
1066 maxY = -256f; 1548 maxY = float.MinValue;
1067 maxZ = -256f; 1549 maxZ = float.MinValue;
1068 minX = 10000f; 1550 minX = float.MaxValue;
1069 minY = 10000f; 1551 minY = float.MaxValue;
1070 minZ = 10000f; 1552 minZ = float.MaxValue;
1071 1553
1072 SceneObjectPart[] parts = m_parts.GetArray(); 1554 SceneObjectPart[] parts = m_parts.GetArray();
1073 for (int i = 0; i < parts.Length; i++) 1555 foreach (SceneObjectPart part in parts)
1074 { 1556 {
1075 SceneObjectPart part = parts[i];
1076
1077 Vector3 worldPos = part.GetWorldPosition(); 1557 Vector3 worldPos = part.GetWorldPosition();
1078 Vector3 offset = worldPos - AbsolutePosition; 1558 Vector3 offset = worldPos - AbsolutePosition;
1079 Quaternion worldRot; 1559 Quaternion worldRot;
1080 if (part.ParentID == 0) 1560 if (part.ParentID == 0)
1561 {
1081 worldRot = part.RotationOffset; 1562 worldRot = part.RotationOffset;
1563 }
1082 else 1564 else
1565 {
1083 worldRot = part.GetWorldRotation(); 1566 worldRot = part.GetWorldRotation();
1567 }
1084 1568
1085 Vector3 frontTopLeft; 1569 Vector3 frontTopLeft;
1086 Vector3 frontTopRight; 1570 Vector3 frontTopRight;
@@ -1092,6 +1576,8 @@ namespace OpenSim.Region.Framework.Scenes
1092 Vector3 backBottomLeft; 1576 Vector3 backBottomLeft;
1093 Vector3 backBottomRight; 1577 Vector3 backBottomRight;
1094 1578
1579 // Vector3[] corners = new Vector3[8];
1580
1095 Vector3 orig = Vector3.Zero; 1581 Vector3 orig = Vector3.Zero;
1096 1582
1097 frontTopLeft.X = orig.X - (part.Scale.X / 2); 1583 frontTopLeft.X = orig.X - (part.Scale.X / 2);
@@ -1126,6 +1612,38 @@ namespace OpenSim.Region.Framework.Scenes
1126 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 1612 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
1127 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 1613 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
1128 1614
1615
1616
1617 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
1618 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
1619 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
1620 //m_log.InfoFormat("pre corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
1621 //m_log.InfoFormat("pre corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
1622 //m_log.InfoFormat("pre corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
1623 //m_log.InfoFormat("pre corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
1624 //m_log.InfoFormat("pre corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
1625
1626 //for (int i = 0; i < 8; i++)
1627 //{
1628 // corners[i] = corners[i] * worldRot;
1629 // corners[i] += offset;
1630
1631 // if (corners[i].X > maxX)
1632 // maxX = corners[i].X;
1633 // if (corners[i].X < minX)
1634 // minX = corners[i].X;
1635
1636 // if (corners[i].Y > maxY)
1637 // maxY = corners[i].Y;
1638 // if (corners[i].Y < minY)
1639 // minY = corners[i].Y;
1640
1641 // if (corners[i].Z > maxZ)
1642 // maxZ = corners[i].Y;
1643 // if (corners[i].Z < minZ)
1644 // minZ = corners[i].Z;
1645 //}
1646
1129 frontTopLeft = frontTopLeft * worldRot; 1647 frontTopLeft = frontTopLeft * worldRot;
1130 frontTopRight = frontTopRight * worldRot; 1648 frontTopRight = frontTopRight * worldRot;
1131 frontBottomLeft = frontBottomLeft * worldRot; 1649 frontBottomLeft = frontBottomLeft * worldRot;
@@ -1147,6 +1665,15 @@ namespace OpenSim.Region.Framework.Scenes
1147 backTopLeft += offset; 1665 backTopLeft += offset;
1148 backTopRight += offset; 1666 backTopRight += offset;
1149 1667
1668 //m_log.InfoFormat("corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
1669 //m_log.InfoFormat("corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
1670 //m_log.InfoFormat("corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
1671 //m_log.InfoFormat("corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
1672 //m_log.InfoFormat("corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
1673 //m_log.InfoFormat("corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
1674 //m_log.InfoFormat("corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
1675 //m_log.InfoFormat("corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
1676
1150 if (frontTopRight.X > maxX) 1677 if (frontTopRight.X > maxX)
1151 maxX = frontTopRight.X; 1678 maxX = frontTopRight.X;
1152 if (frontTopLeft.X > maxX) 1679 if (frontTopLeft.X > maxX)
@@ -1290,17 +1817,192 @@ namespace OpenSim.Region.Framework.Scenes
1290 1817
1291 #endregion 1818 #endregion
1292 1819
1820 private float? m_boundsRadius = null;
1821 public void InvalidBoundsRadius()
1822 {
1823 m_boundsRadius = null;
1824 }
1825
1826 private Vector3 m_boundsCenter;
1827 public Vector3 getBoundsCenter()
1828 {
1829 // math is done in GetBoundsRadius();
1830 if(m_boundsRadius == null)
1831 GetBoundsRadius();
1832 return m_boundsCenter;
1833 }
1834
1835 private float m_areaFactor;
1836 public float getAreaFactor()
1837 {
1838 // math is done in GetBoundsRadius();
1839 if(m_boundsRadius == null)
1840 GetBoundsRadius();
1841 return m_areaFactor;
1842 }
1843
1844 public float GetBoundsRadius()
1845 {
1846 // this may need more threading work
1847 if(m_boundsRadius == null)
1848 {
1849 float res = 0;
1850 float areaF = 0;
1851 SceneObjectPart p;
1852 SceneObjectPart[] parts;
1853 float partR;
1854 Vector3 offset = Vector3.Zero;
1855 lock (m_parts)
1856 {
1857 parts = m_parts.GetArray();
1858 }
1859
1860 int nparts = parts.Length;
1861 for (int i = 0; i < nparts; i++)
1862 {
1863 p = parts[i];
1864 partR = 0.5f * p.Scale.Length();
1865 if(p != RootPart)
1866 {
1867 partR += p.OffsetPosition.Length();
1868 offset += p.OffsetPosition;
1869 }
1870 if(partR > res)
1871 res = partR;
1872 if(p.maxSimpleArea() > areaF)
1873 areaF = p.maxSimpleArea();
1874 }
1875 if(parts.Length > 1)
1876 {
1877 offset /= parts.Length; // basicly geometric center
1878 offset = offset * RootPart.RotationOffset;
1879 }
1880
1881 areaF = 10.0f / areaF; // scale it
1882 areaF = Util.Clamp(areaF, 0.001f, 1000f); // clamp it
1883
1884 m_areaFactor = (float)Math.Sqrt(areaF);
1885 m_boundsCenter = offset;
1886 m_boundsRadius = res;
1887 return res;
1888 }
1889
1890 return m_boundsRadius.Value;
1891 }
1892
1893 public void GetResourcesCosts(SceneObjectPart apart,
1894 out float linksetResCost, out float linksetPhysCost, out float partCost, out float partPhysCost)
1895 {
1896 // this information may need to be cached
1897
1898 float cost;
1899 float tmpcost;
1900
1901 bool ComplexCost = false;
1902
1903 SceneObjectPart p;
1904 SceneObjectPart[] parts;
1905
1906 lock (m_parts)
1907 {
1908 parts = m_parts.GetArray();
1909 }
1910
1911 int nparts = parts.Length;
1912
1913
1914 for (int i = 0; i < nparts; i++)
1915 {
1916 p = parts[i];
1917
1918 if (p.UsesComplexCost)
1919 {
1920 ComplexCost = true;
1921 break;
1922 }
1923 }
1924
1925 if (ComplexCost)
1926 {
1927 linksetResCost = 0;
1928 linksetPhysCost = 0;
1929 partCost = 0;
1930 partPhysCost = 0;
1931
1932 for (int i = 0; i < nparts; i++)
1933 {
1934 p = parts[i];
1935
1936 cost = p.StreamingCost;
1937 tmpcost = p.SimulationCost;
1938 if (tmpcost > cost)
1939 cost = tmpcost;
1940 tmpcost = p.PhysicsCost;
1941 if (tmpcost > cost)
1942 cost = tmpcost;
1943
1944 linksetPhysCost += tmpcost;
1945 linksetResCost += cost;
1946
1947 if (p == apart)
1948 {
1949 partCost = cost;
1950 partPhysCost = tmpcost;
1951 }
1952 }
1953 }
1954 else
1955 {
1956 partPhysCost = 1.0f;
1957 partCost = 1.0f;
1958 linksetResCost = (float)nparts;
1959 linksetPhysCost = linksetResCost;
1960 }
1961 }
1962
1963 public void GetSelectedCosts(out float PhysCost, out float StreamCost, out float SimulCost)
1964 {
1965 SceneObjectPart p;
1966 SceneObjectPart[] parts;
1967
1968 lock (m_parts)
1969 {
1970 parts = m_parts.GetArray();
1971 }
1972
1973 int nparts = parts.Length;
1974
1975 PhysCost = 0;
1976 StreamCost = 0;
1977 SimulCost = 0;
1978
1979 for (int i = 0; i < nparts; i++)
1980 {
1981 p = parts[i];
1982
1983 StreamCost += p.StreamingCost;
1984 SimulCost += p.SimulationCost;
1985 PhysCost += p.PhysicsCost;
1986 }
1987 }
1988
1293 public void SaveScriptedState(XmlTextWriter writer) 1989 public void SaveScriptedState(XmlTextWriter writer)
1294 { 1990 {
1991 SaveScriptedState(writer, false);
1992 }
1993
1994 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1995 {
1295 XmlDocument doc = new XmlDocument(); 1996 XmlDocument doc = new XmlDocument();
1997 doc.XmlResolver=null;
1296 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1998 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
1297 1999
1298 SceneObjectPart[] parts = m_parts.GetArray(); 2000 SceneObjectPart[] parts = m_parts.GetArray();
1299 for (int i = 0; i < parts.Length; i++) 2001 for (int i = 0; i < parts.Length; i++)
1300 { 2002 {
1301 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(); 2003 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(oldIDs);
1302 foreach (KeyValuePair<UUID, string> kvp in pstates) 2004 foreach (KeyValuePair<UUID, string> kvp in pstates)
1303 states.Add(kvp.Key, kvp.Value); 2005 states[kvp.Key] = kvp.Value;
1304 } 2006 }
1305 2007
1306 if (states.Count > 0) 2008 if (states.Count > 0)
@@ -1319,6 +2021,73 @@ namespace OpenSim.Region.Framework.Scenes
1319 } 2021 }
1320 } 2022 }
1321 2023
2024 public byte GetAttachmentPoint()
2025 {
2026 return m_rootPart.Shape.State;
2027 }
2028
2029 public void DetachToGround()
2030 {
2031 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
2032 if (avatar == null)
2033 return;
2034 m_rootPart.Shape.LastAttachPoint = m_rootPart.Shape.State;
2035 m_rootPart.AttachedPos = m_rootPart.OffsetPosition;
2036 avatar.RemoveAttachment(this);
2037
2038 Vector3 detachedpos = new Vector3(127f,127f,127f);
2039 if (avatar == null)
2040 return;
2041
2042 detachedpos = avatar.AbsolutePosition;
2043 FromItemID = UUID.Zero;
2044
2045 AbsolutePosition = detachedpos;
2046 AttachedAvatar = UUID.Zero;
2047
2048 //SceneObjectPart[] parts = m_parts.GetArray();
2049 //for (int i = 0; i < parts.Length; i++)
2050 // parts[i].AttachedAvatar = UUID.Zero;
2051
2052 m_rootPart.SetParentLocalId(0);
2053 AttachmentPoint = (byte)0;
2054 // must check if buildind should be true or false here
2055// m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive,false);
2056 ApplyPhysics();
2057
2058 HasGroupChanged = true;
2059 RootPart.Rezzed = DateTime.Now;
2060 RootPart.RemFlag(PrimFlags.TemporaryOnRez);
2061 AttachToBackup();
2062 m_scene.EventManager.TriggerParcelPrimCountTainted();
2063 m_rootPart.ScheduleFullUpdate();
2064 m_rootPart.ClearUndoState();
2065 }
2066
2067 public void DetachToInventoryPrep()
2068 {
2069 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
2070 //Vector3 detachedpos = new Vector3(127f, 127f, 127f);
2071 if (avatar != null)
2072 {
2073 //detachedpos = avatar.AbsolutePosition;
2074 avatar.RemoveAttachment(this);
2075 }
2076
2077 AttachedAvatar = UUID.Zero;
2078
2079 /*SceneObjectPart[] parts = m_parts.GetArray();
2080 for (int i = 0; i < parts.Length; i++)
2081 parts[i].AttachedAvatar = UUID.Zero;*/
2082
2083 m_rootPart.SetParentLocalId(0);
2084 //m_rootPart.SetAttachmentPoint((byte)0);
2085 IsAttachment = false;
2086 AbsolutePosition = m_rootPart.AttachedPos;
2087 //m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_scene.m_physicalPrim);
2088 //AttachToBackup();
2089 //m_rootPart.ScheduleFullUpdate();
2090 }
1322 2091
1323 /// <summary> 2092 /// <summary>
1324 /// 2093 ///
@@ -1334,7 +2103,7 @@ namespace OpenSim.Region.Framework.Scenes
1334 { 2103 {
1335 return Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f); 2104 return Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f);
1336 } 2105 }
1337 2106
1338 /// <summary> 2107 /// <summary>
1339 /// Set a part to act as the root part for this scene object 2108 /// Set a part to act as the root part for this scene object
1340 /// </summary> 2109 /// </summary>
@@ -1349,7 +2118,7 @@ namespace OpenSim.Region.Framework.Scenes
1349 if (!IsAttachment) 2118 if (!IsAttachment)
1350 part.ParentID = 0; 2119 part.ParentID = 0;
1351 part.LinkNum = 0; 2120 part.LinkNum = 0;
1352 2121
1353 m_parts.Add(m_rootPart.UUID, m_rootPart); 2122 m_parts.Add(m_rootPart.UUID, m_rootPart);
1354 } 2123 }
1355 2124
@@ -1360,9 +2129,13 @@ namespace OpenSim.Region.Framework.Scenes
1360 public void AddPart(SceneObjectPart part) 2129 public void AddPart(SceneObjectPart part)
1361 { 2130 {
1362 part.SetParent(this); 2131 part.SetParent(this);
1363 part.LinkNum = m_parts.Add(part.UUID, part); 2132 m_parts.Add(part.UUID, part);
2133
2134 part.LinkNum = m_parts.Count;
2135
1364 if (part.LinkNum == 2) 2136 if (part.LinkNum == 2)
1365 RootPart.LinkNum = 1; 2137 RootPart.LinkNum = 1;
2138 InvalidatePartsLinkMaps();
1366 } 2139 }
1367 2140
1368 /// <summary> 2141 /// <summary>
@@ -1386,32 +2159,50 @@ namespace OpenSim.Region.Framework.Scenes
1386 parts[i].UUID = UUID.Random(); 2159 parts[i].UUID = UUID.Random();
1387 } 2160 }
1388 2161
2162 // helper provided for parts.
2163 public int GetSceneMaxUndo()
2164 {
2165 if (m_scene != null)
2166 return m_scene.MaxUndoCount;
2167 return 5;
2168 }
2169
1389 // justincc: I don't believe this hack is needed any longer, especially since the physics 2170 // justincc: I don't believe this hack is needed any longer, especially since the physics
1390 // parts of set AbsolutePosition were already commented out. By changing HasGroupChanged to false 2171 // parts of set AbsolutePosition were already commented out. By changing HasGroupChanged to false
1391 // this method was preventing proper reload of scene objects. 2172 // this method was preventing proper reload of scene objects.
1392 2173
1393 // dahlia: I had to uncomment it, without it meshing was failing on some prims and objects 2174 // dahlia: I had to uncomment it, without it meshing was failing on some prims and objects
1394 // at region startup 2175 // at region startup
1395 2176
1396 // teravus: After this was removed from the linking algorithm, Linked prims no longer collided 2177 // teravus: After this was removed from the linking algorithm, Linked prims no longer collided
1397 // properly when non-physical if they havn't been moved. This breaks ALL builds. 2178 // properly when non-physical if they havn't been moved. This breaks ALL builds.
1398 // see: http://opensimulator.org/mantis/view.php?id=3108 2179 // see: http://opensimulator.org/mantis/view.php?id=3108
1399 2180
1400 // Here's the deal, this is ABSOLUTELY CRITICAL so the physics scene gets the update about the 2181 // Here's the deal, this is ABSOLUTELY CRITICAL so the physics scene gets the update about the
1401 // position of linkset prims. IF YOU CHANGE THIS, YOU MUST TEST colliding with just linked and 2182 // position of linkset prims. IF YOU CHANGE THIS, YOU MUST TEST colliding with just linked and
1402 // unmoved prims! As soon as you move a Prim/group, it will collide properly because Absolute 2183 // unmoved prims! As soon as you move a Prim/group, it will collide properly because Absolute
1403 // Position has been set! 2184 // Position has been set!
1404 2185
1405 public void ResetChildPrimPhysicsPositions() 2186 public void ResetChildPrimPhysicsPositions()
1406 { 2187 {
1407 // Setting this SOG's absolute position also loops through and sets the positions 2188 // Setting this SOG's absolute position also loops through and sets the positions
1408 // of the SOP's in this SOG's linkset. This has the side affect of making sure 2189 // of the SOP's in this SOG's linkset. This has the side affect of making sure
1409 // the physics world matches the simulated world. 2190 // the physics world matches the simulated world.
1410 AbsolutePosition = AbsolutePosition; // could someone in the know please explain how this works? 2191 // AbsolutePosition = AbsolutePosition; // could someone in the know please explain how this works?
1411 2192
1412 // teravus: AbsolutePosition is NOT a normal property! 2193 // teravus: AbsolutePosition is NOT a normal property!
1413 // the code in the getter of AbsolutePosition is significantly different then the code in the setter! 2194 // the code in the getter of AbsolutePosition is significantly different then the code in the setter!
1414 // jhurliman: Then why is it a property instead of two methods? 2195 // jhurliman: Then why is it a property instead of two methods?
2196
2197 // do only what is supposed to do
2198 Vector3 groupPosition = m_rootPart.GroupPosition;
2199 SceneObjectPart[] parts = m_parts.GetArray();
2200
2201 foreach (SceneObjectPart part in parts)
2202 {
2203 if (part != m_rootPart)
2204 part.GroupPosition = groupPosition;
2205 }
1415 } 2206 }
1416 2207
1417 public UUID GetPartsFullID(uint localID) 2208 public UUID GetPartsFullID(uint localID)
@@ -1443,7 +2234,7 @@ namespace OpenSim.Region.Framework.Scenes
1443// "[SCENE OBJECT GROUP]: Processing OnGrabPart for {0} on {1} {2}, offsetPos {3}", 2234// "[SCENE OBJECT GROUP]: Processing OnGrabPart for {0} on {1} {2}, offsetPos {3}",
1444// remoteClient.Name, part.Name, part.LocalId, offsetPos); 2235// remoteClient.Name, part.Name, part.LocalId, offsetPos);
1445 2236
1446 part.StoreUndoState(); 2237// part.StoreUndoState();
1447 part.OnGrab(offsetPos, remoteClient); 2238 part.OnGrab(offsetPos, remoteClient);
1448 } 2239 }
1449 2240
@@ -1463,15 +2254,23 @@ namespace OpenSim.Region.Framework.Scenes
1463 /// <param name="silent">If true then deletion is not broadcast to clients</param> 2254 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1464 public void DeleteGroupFromScene(bool silent) 2255 public void DeleteGroupFromScene(bool silent)
1465 { 2256 {
2257 // We need to keep track of this state in case this group is still queued for backup.
2258 IsDeleted = true;
2259
2260 DetachFromBackup();
2261
2262 if(Scene == null) // should not happen unless restart/shutdown ?
2263 return;
2264
1466 SceneObjectPart[] parts = m_parts.GetArray(); 2265 SceneObjectPart[] parts = m_parts.GetArray();
1467 for (int i = 0; i < parts.Length; i++) 2266 for (int i = 0; i < parts.Length; i++)
1468 { 2267 {
1469 SceneObjectPart part = parts[i]; 2268 SceneObjectPart part = parts[i];
1470 2269
1471 Scene.ForEachScenePresence(sp => 2270 Scene.ForEachScenePresence(delegate(ScenePresence avatar)
1472 { 2271 {
1473 if (!sp.IsChildAgent && sp.ParentID == part.LocalId) 2272 if (!avatar.IsChildAgent && avatar.ParentID == part.LocalId && avatar.ParentUUID == UUID.Zero)
1474 sp.StandUp(); 2273 avatar.StandUp();
1475 2274
1476 if (!silent) 2275 if (!silent)
1477 { 2276 {
@@ -1479,9 +2278,14 @@ namespace OpenSim.Region.Framework.Scenes
1479 if (part == m_rootPart) 2278 if (part == m_rootPart)
1480 { 2279 {
1481 if (!IsAttachment 2280 if (!IsAttachment
1482 || AttachedAvatar == sp.UUID 2281 || AttachedAvatar == avatar.ControllingClient.AgentId
1483 || !HasPrivateAttachmentPoint) 2282 || !HasPrivateAttachmentPoint)
1484 sp.ControllingClient.SendKillObject(new List<uint> { part.LocalId }); 2283 {
2284 // Send a kill object immediately
2285 avatar.ControllingClient.SendKillObject(new List<uint> { part.LocalId });
2286 //direct enqueue another delayed kill
2287 avatar.ControllingClient.SendEntityUpdate(part,PrimUpdateFlags.Kill);
2288 }
1485 } 2289 }
1486 } 2290 }
1487 }); 2291 });
@@ -1499,6 +2303,12 @@ namespace OpenSim.Region.Framework.Scenes
1499 d.AddActiveScripts(count); 2303 d.AddActiveScripts(count);
1500 } 2304 }
1501 2305
2306 private const scriptEvents PhysicsNeeedSubsEvents = (
2307 scriptEvents.collision | scriptEvents.collision_start | scriptEvents.collision_end |
2308 scriptEvents.land_collision | scriptEvents.land_collision_start | scriptEvents.land_collision_end);
2309
2310 private scriptEvents lastRootPartPhysEvents = 0;
2311
1502 public void aggregateScriptEvents() 2312 public void aggregateScriptEvents()
1503 { 2313 {
1504 PrimFlags objectflagupdate = (PrimFlags)RootPart.GetEffectiveObjectFlags(); 2314 PrimFlags objectflagupdate = (PrimFlags)RootPart.GetEffectiveObjectFlags();
@@ -1535,6 +2345,20 @@ namespace OpenSim.Region.Framework.Scenes
1535 m_scene.RemoveGroupTarget(this); 2345 m_scene.RemoveGroupTarget(this);
1536 } 2346 }
1537 2347
2348 scriptEvents rootPartPhysEvents = RootPart.AggregateScriptEvents;
2349 rootPartPhysEvents &= PhysicsNeeedSubsEvents;
2350 if (rootPartPhysEvents != lastRootPartPhysEvents)
2351 {
2352 lastRootPartPhysEvents = rootPartPhysEvents;
2353 for (int i = 0; i < parts.Length; i++)
2354 {
2355 SceneObjectPart part = parts[i];
2356 if (part == null)
2357 continue;
2358 part.UpdatePhysicsSubscribedEvents();
2359 }
2360 }
2361
1538 ScheduleGroupForFullUpdate(); 2362 ScheduleGroupForFullUpdate();
1539 } 2363 }
1540 2364
@@ -1555,28 +2379,44 @@ namespace OpenSim.Region.Framework.Scenes
1555 /// </summary> 2379 /// </summary>
1556 public void ApplyPhysics() 2380 public void ApplyPhysics()
1557 { 2381 {
1558 // Apply physics to the root prim
1559 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive);
1560
1561 // Apply physics to child prims
1562 SceneObjectPart[] parts = m_parts.GetArray(); 2382 SceneObjectPart[] parts = m_parts.GetArray();
1563 if (parts.Length > 1) 2383 if (parts.Length > 1)
1564 { 2384 {
2385 ResetChildPrimPhysicsPositions();
2386
2387 // Apply physics to the root prim
2388 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, true);
2389
1565 for (int i = 0; i < parts.Length; i++) 2390 for (int i = 0; i < parts.Length; i++)
1566 { 2391 {
1567 SceneObjectPart part = parts[i]; 2392 SceneObjectPart part = parts[i];
1568 if (part.LocalId != m_rootPart.LocalId) 2393 if (part.LocalId != m_rootPart.LocalId)
1569 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive); 2394 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, true);
1570 } 2395 }
1571
1572 // Hack to get the physics scene geometries in the right spot 2396 // Hack to get the physics scene geometries in the right spot
1573 ResetChildPrimPhysicsPositions(); 2397// ResetChildPrimPhysicsPositions();
2398
2399 if (m_rootPart.PhysActor != null)
2400 m_rootPart.PhysActor.Building = false;
2401 }
2402 else
2403 {
2404 // Apply physics to the root prim
2405 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, false);
1574 } 2406 }
1575 } 2407 }
1576 2408
1577 public void SetOwnerId(UUID userId) 2409 public void SetOwnerId(UUID userId)
1578 { 2410 {
1579 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 2411 ForEachPart(delegate(SceneObjectPart part)
2412 {
2413 if (part.OwnerID != userId)
2414 {
2415 if(part.GroupID != part.OwnerID)
2416 part.LastOwnerID = part.OwnerID;
2417 part.OwnerID = userId;
2418 }
2419 });
1580 } 2420 }
1581 2421
1582 public void ForEachPart(Action<SceneObjectPart> whatToDo) 2422 public void ForEachPart(Action<SceneObjectPart> whatToDo)
@@ -1601,18 +2441,24 @@ namespace OpenSim.Region.Framework.Scenes
1601 return; 2441 return;
1602 } 2442 }
1603 2443
1604 if (IsDeleted || UUID == UUID.Zero) 2444 if (IsDeleted || inTransit || UUID == UUID.Zero)
1605 { 2445 {
1606// m_log.DebugFormat( 2446// m_log.DebugFormat(
1607// "[WATER WARS]: Ignoring backup of {0} {1} since object is marked as already deleted", Name, UUID); 2447// "[WATER WARS]: Ignoring backup of {0} {1} since object is marked as already deleted", Name, UUID);
1608 return; 2448 return;
1609 } 2449 }
1610 2450
2451 if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
2452 return;
2453
1611 // Since this is the top of the section of call stack for backing up a particular scene object, don't let 2454 // Since this is the top of the section of call stack for backing up a particular scene object, don't let
1612 // any exception propogate upwards. 2455 // any exception propogate upwards.
1613 try 2456 try
1614 { 2457 {
1615 if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart 2458 // if shutting down then there will be nothing to handle the return so leave till next restart
2459 if (!m_scene.ShuttingDown &&
2460 m_scene.LoginsEnabled && // We're starting up or doing maintenance, don't mess with things
2461 !m_scene.LoadingPrims) // Land may not be valid yet
1616 { 2462 {
1617 ILandObject parcel = m_scene.LandChannel.GetLandObject( 2463 ILandObject parcel = m_scene.LandChannel.GetLandObject(
1618 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); 2464 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y);
@@ -1627,18 +2473,33 @@ namespace OpenSim.Region.Framework.Scenes
1627 if ((DateTime.UtcNow - RootPart.Rezzed).TotalMinutes > 2473 if ((DateTime.UtcNow - RootPart.Rezzed).TotalMinutes >
1628 parcel.LandData.OtherCleanTime) 2474 parcel.LandData.OtherCleanTime)
1629 { 2475 {
2476 // don't autoreturn if we have a sitting avatar
2477 // mantis 7828 (but none the provided patchs)
2478
2479 if(GetSittingAvatarsCount() > 0)
2480 {
2481 // do not respect npcs
2482 List<ScenePresence> sitters = GetSittingAvatars();
2483 foreach(ScenePresence sp in sitters)
2484 {
2485 if(!sp.IsDeleted && !sp.IsNPC && sp.IsSatOnObject)
2486 return;
2487 }
2488 }
2489
1630 DetachFromBackup(); 2490 DetachFromBackup();
1631 m_log.DebugFormat( 2491 m_log.DebugFormat(
1632 "[SCENE OBJECT GROUP]: Returning object {0} due to parcel autoreturn", 2492 "[SCENE OBJECT GROUP]: Returning object {0} due to parcel autoreturn",
1633 RootPart.UUID); 2493 RootPart.UUID);
1634 m_scene.AddReturn(OwnerID == GroupID ? LastOwnerID : OwnerID, Name, AbsolutePosition, "parcel autoreturn"); 2494 m_scene.AddReturn(OwnerID == GroupID ? LastOwnerID : OwnerID, Name, AbsolutePosition, "parcel autoreturn");
1635 m_scene.DeRezObjects(null, new List<uint>() { RootPart.LocalId }, UUID.Zero, 2495 m_scene.DeRezObjects(null, new List<uint>() { RootPart.LocalId }, UUID.Zero,
1636 DeRezAction.Return, UUID.Zero); 2496 DeRezAction.Return, UUID.Zero, false);
1637 2497
1638 return; 2498 return;
1639 } 2499 }
1640 } 2500 }
1641 } 2501 }
2502
1642 } 2503 }
1643 2504
1644 if (m_scene.UseBackup && HasGroupChanged) 2505 if (m_scene.UseBackup && HasGroupChanged)
@@ -1646,10 +2507,31 @@ namespace OpenSim.Region.Framework.Scenes
1646 // don't backup while it's selected or you're asking for changes mid stream. 2507 // don't backup while it's selected or you're asking for changes mid stream.
1647 if (isTimeToPersist() || forcedBackup) 2508 if (isTimeToPersist() || forcedBackup)
1648 { 2509 {
2510 if (m_rootPart.PhysActor != null &&
2511 (!m_rootPart.PhysActor.IsPhysical))
2512 {
2513 // Possible ghost prim
2514 if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition)
2515 {
2516 foreach (SceneObjectPart part in m_parts.GetArray())
2517 {
2518 // Re-set physics actor positions and
2519 // orientations
2520 part.GroupPosition = m_rootPart.GroupPosition;
2521 }
2522 }
2523 }
1649// m_log.DebugFormat( 2524// m_log.DebugFormat(
1650// "[SCENE]: Storing {0}, {1} in {2}", 2525// "[SCENE]: Storing {0}, {1} in {2}",
1651// Name, UUID, m_scene.RegionInfo.RegionName); 2526// Name, UUID, m_scene.RegionInfo.RegionName);
1652 2527
2528 if (RootPart.Shape.PCode == 9 && RootPart.Shape.State != 0)
2529 {
2530 RootPart.Shape.LastAttachPoint = RootPart.Shape.State;
2531 RootPart.Shape.State = 0;
2532 ScheduleGroupForFullUpdate();
2533 }
2534
1653 SceneObjectGroup backup_group = Copy(false); 2535 SceneObjectGroup backup_group = Copy(false);
1654 backup_group.RootPart.Velocity = RootPart.Velocity; 2536 backup_group.RootPart.Velocity = RootPart.Velocity;
1655 backup_group.RootPart.Acceleration = RootPart.Acceleration; 2537 backup_group.RootPart.Acceleration = RootPart.Acceleration;
@@ -1659,13 +2541,21 @@ namespace OpenSim.Region.Framework.Scenes
1659 GroupContainsForeignPrims = false; 2541 GroupContainsForeignPrims = false;
1660 2542
1661 m_scene.EventManager.TriggerOnSceneObjectPreSave(backup_group, this); 2543 m_scene.EventManager.TriggerOnSceneObjectPreSave(backup_group, this);
2544
1662 datastore.StoreObject(backup_group, m_scene.RegionInfo.RegionID); 2545 datastore.StoreObject(backup_group, m_scene.RegionInfo.RegionID);
1663 2546
1664 backup_group.ForEachPart(delegate(SceneObjectPart part) 2547 backup_group.ForEachPart(delegate(SceneObjectPart part)
1665 { 2548 {
1666 part.Inventory.ProcessInventoryBackup(datastore); 2549 part.Inventory.ProcessInventoryBackup(datastore);
2550
2551 if(part.KeyframeMotion != null)
2552 {
2553 part.KeyframeMotion.Delete();
2554 part.KeyframeMotion = null;
2555 }
1667 }); 2556 });
1668 2557
2558 backup_group.Clear();
1669 backup_group = null; 2559 backup_group = null;
1670 } 2560 }
1671// else 2561// else
@@ -1679,7 +2569,7 @@ namespace OpenSim.Region.Framework.Scenes
1679 catch (Exception e) 2569 catch (Exception e)
1680 { 2570 {
1681 m_log.ErrorFormat( 2571 m_log.ErrorFormat(
1682 "[SCENE]: Storing of {0}, {1} in {2} failed with exception {3}{4}", 2572 "[SCENE]: Storing of {0}, {1} in {2} failed with exception {3}{4}",
1683 Name, UUID, m_scene.RegionInfo.RegionName, e.Message, e.StackTrace); 2573 Name, UUID, m_scene.RegionInfo.RegionName, e.Message, e.StackTrace);
1684 } 2574 }
1685 } 2575 }
@@ -1715,14 +2605,21 @@ namespace OpenSim.Region.Framework.Scenes
1715 /// <returns></returns> 2605 /// <returns></returns>
1716 public SceneObjectGroup Copy(bool userExposed) 2606 public SceneObjectGroup Copy(bool userExposed)
1717 { 2607 {
1718 // FIXME: This is dangerous since it's easy to forget to reset some references when necessary and end up 2608 m_dupeInProgress = true;
1719 // with bugs that only occur in some circumstances (e.g. crossing between regions on the same simulator
1720 // but not between regions on different simulators). Really, all copying should be done explicitly.
1721 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone(); 2609 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone();
1722 2610
1723 dupe.Backup = false;
1724 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); 2611 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>();
2612
2613 // a copy isnt backedup
2614 dupe.Backup = false;
2615 dupe.InvalidBoundsRadius();
2616
2617 // a copy is not in transit hopefully
2618 dupe.inTransit = false;
2619
2620 // new group as no sitting avatars
1725 dupe.m_sittingAvatars = new List<ScenePresence>(); 2621 dupe.m_sittingAvatars = new List<ScenePresence>();
2622
1726 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); 2623 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed);
1727 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; 2624 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum;
1728 2625
@@ -1730,12 +2627,12 @@ namespace OpenSim.Region.Framework.Scenes
1730 dupe.m_rootPart.TrimPermissions(); 2627 dupe.m_rootPart.TrimPermissions();
1731 2628
1732 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); 2629 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray());
1733 2630
1734 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 2631 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1735 { 2632 {
1736 return p1.LinkNum.CompareTo(p2.LinkNum); 2633 return p1.LinkNum.CompareTo(p2.LinkNum);
1737 } 2634 }
1738 ); 2635 );
1739 2636
1740 foreach (SceneObjectPart part in partList) 2637 foreach (SceneObjectPart part in partList)
1741 { 2638 {
@@ -1744,43 +2641,59 @@ namespace OpenSim.Region.Framework.Scenes
1744 { 2641 {
1745 newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); 2642 newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed);
1746 newPart.LinkNum = part.LinkNum; 2643 newPart.LinkNum = part.LinkNum;
1747 } 2644// if (userExposed)
2645 newPart.ParentID = dupe.m_rootPart.LocalId;
2646 }
1748 else 2647 else
1749 { 2648 {
1750 newPart = dupe.m_rootPart; 2649 newPart = dupe.m_rootPart;
1751 } 2650 }
2651/*
2652 bool isphys = ((newPart.Flags & PrimFlags.Physics) != 0);
2653 bool isphan = ((newPart.Flags & PrimFlags.Phantom) != 0);
1752 2654
1753 // Need to duplicate the physics actor as well 2655 // Need to duplicate the physics actor as well
1754 PhysicsActor originalPartPa = part.PhysActor; 2656 if (userExposed && (isphys || !isphan || newPart.VolumeDetectActive))
1755 if (originalPartPa != null && userExposed)
1756 { 2657 {
1757 PrimitiveBaseShape pbs = newPart.Shape; 2658 PrimitiveBaseShape pbs = newPart.Shape;
1758
1759 newPart.PhysActor 2659 newPart.PhysActor
1760 = m_scene.PhysicsScene.AddPrimShape( 2660 = m_scene.PhysicsScene.AddPrimShape(
1761 string.Format("{0}/{1}", newPart.Name, newPart.UUID), 2661 string.Format("{0}/{1}", newPart.Name, newPart.UUID),
1762 pbs, 2662 pbs,
1763 newPart.AbsolutePosition, 2663 newPart.AbsolutePosition,
1764 newPart.Scale, 2664 newPart.Scale,
1765 newPart.RotationOffset, 2665 newPart.GetWorldRotation(),
1766 originalPartPa.IsPhysical, 2666 isphys,
2667 isphan,
1767 newPart.LocalId); 2668 newPart.LocalId);
1768 2669
1769 newPart.DoPhysicsPropertyUpdate(originalPartPa.IsPhysical, true); 2670 newPart.DoPhysicsPropertyUpdate(isphys, true);
1770 } 2671 */
2672 if (userExposed)
2673 newPart.ApplyPhysics((uint)newPart.Flags,newPart.VolumeDetectActive,true);
2674// }
2675 // copy keyframemotion
1771 if (part.KeyframeMotion != null) 2676 if (part.KeyframeMotion != null)
1772 newPart.KeyframeMotion = part.KeyframeMotion.Copy(dupe); 2677 newPart.KeyframeMotion = part.KeyframeMotion.Copy(dupe);
1773 } 2678 }
1774 2679
1775 if (userExposed) 2680 if (userExposed)
1776 { 2681 {
1777 dupe.UpdateParentIDs(); 2682// done above dupe.UpdateParentIDs();
2683
2684 if (dupe.m_rootPart.PhysActor != null)
2685 dupe.m_rootPart.PhysActor.Building = false; // tell physics to finish building
2686
2687 dupe.InvalidateDeepEffectivePerms();
2688
1778 dupe.HasGroupChanged = true; 2689 dupe.HasGroupChanged = true;
1779 dupe.AttachToBackup(); 2690 dupe.AttachToBackup();
1780 2691
1781 ScheduleGroupForFullUpdate(); 2692 dupe.ScheduleGroupForFullUpdate();
1782 } 2693 }
1783 2694
2695 dupe.InvalidatePartsLinkMaps();
2696 m_dupeInProgress = false;
1784 return dupe; 2697 return dupe;
1785 } 2698 }
1786 2699
@@ -1792,7 +2705,13 @@ namespace OpenSim.Region.Framework.Scenes
1792 /// <param name="cGroupID"></param> 2705 /// <param name="cGroupID"></param>
1793 public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2706 public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1794 { 2707 {
1795 SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed)); 2708 SceneObjectPart newpart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed);
2709// SceneObjectPart newpart = part.Copy(part.LocalId, OwnerID, GroupID, 0, userExposed);
2710// newpart.LocalId = m_scene.AllocateLocalId();
2711
2712 SetRootPart(newpart);
2713 if (userExposed)
2714 RootPart.Velocity = Vector3.Zero; // In case source is moving
1796 } 2715 }
1797 2716
1798 public void ScriptSetPhysicsStatus(bool usePhysics) 2717 public void ScriptSetPhysicsStatus(bool usePhysics)
@@ -1803,35 +2722,22 @@ namespace OpenSim.Region.Framework.Scenes
1803 RootPart.KeyframeMotion.Stop(); 2722 RootPart.KeyframeMotion.Stop();
1804 RootPart.KeyframeMotion = null; 2723 RootPart.KeyframeMotion = null;
1805 } 2724 }
1806 UpdatePrimFlags(RootPart.LocalId, usePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2725 UpdateFlags(usePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
1807 } 2726 }
1808 2727
1809 public void ScriptSetTemporaryStatus(bool makeTemporary) 2728 public void ScriptSetTemporaryStatus(bool makeTemporary)
1810 { 2729 {
1811 UpdatePrimFlags(RootPart.LocalId, UsesPhysics, makeTemporary, IsPhantom, IsVolumeDetect); 2730 UpdateFlags(UsesPhysics, makeTemporary, IsPhantom, IsVolumeDetect);
1812 } 2731 }
1813 2732
1814 public void ScriptSetPhantomStatus(bool makePhantom) 2733 public void ScriptSetPhantomStatus(bool makePhantom)
1815 { 2734 {
1816 UpdatePrimFlags(RootPart.LocalId, UsesPhysics, IsTemporary, makePhantom, IsVolumeDetect); 2735 UpdateFlags(UsesPhysics, IsTemporary, makePhantom, IsVolumeDetect);
1817 } 2736 }
1818 2737
1819 public void ScriptSetVolumeDetect(bool makeVolumeDetect) 2738 public void ScriptSetVolumeDetect(bool makeVolumeDetect)
1820 { 2739 {
1821 UpdatePrimFlags(RootPart.LocalId, UsesPhysics, IsTemporary, IsPhantom, makeVolumeDetect); 2740 UpdateFlags(UsesPhysics, IsTemporary, IsPhantom, makeVolumeDetect);
1822
1823 /*
1824 ScriptSetPhantomStatus(false); // What ever it was before, now it's not phantom anymore
1825
1826 if (PhysActor != null) // Should always be the case now
1827 {
1828 PhysActor.SetVolumeDetect(param);
1829 }
1830 if (param != 0)
1831 AddFlag(PrimFlags.Phantom);
1832
1833 ScheduleFullUpdate();
1834 */
1835 } 2741 }
1836 2742
1837 public void applyImpulse(Vector3 impulse) 2743 public void applyImpulse(Vector3 impulse)
@@ -1850,13 +2756,14 @@ namespace OpenSim.Region.Framework.Scenes
1850 2756
1851 if (pa != null) 2757 if (pa != null)
1852 { 2758 {
1853 pa.AddForce(impulse, true); 2759 // false to be applied as a impulse
2760 pa.AddForce(impulse, false);
1854 m_scene.PhysicsScene.AddPhysicsActorTaint(pa); 2761 m_scene.PhysicsScene.AddPhysicsActorTaint(pa);
1855 } 2762 }
1856 } 2763 }
1857 } 2764 }
1858 2765
1859 public void applyAngularImpulse(Vector3 impulse) 2766 public void ApplyAngularImpulse(Vector3 impulse)
1860 { 2767 {
1861 PhysicsActor pa = RootPart.PhysActor; 2768 PhysicsActor pa = RootPart.PhysActor;
1862 2769
@@ -1864,21 +2771,8 @@ namespace OpenSim.Region.Framework.Scenes
1864 { 2771 {
1865 if (!IsAttachment) 2772 if (!IsAttachment)
1866 { 2773 {
1867 pa.AddAngularForce(impulse, true); 2774 // false to be applied as a impulse
1868 m_scene.PhysicsScene.AddPhysicsActorTaint(pa); 2775 pa.AddAngularForce(impulse, false);
1869 }
1870 }
1871 }
1872
1873 public void setAngularImpulse(Vector3 impulse)
1874 {
1875 PhysicsActor pa = RootPart.PhysActor;
1876
1877 if (pa != null)
1878 {
1879 if (!IsAttachment)
1880 {
1881 pa.Torque = impulse;
1882 m_scene.PhysicsScene.AddPhysicsActorTaint(pa); 2776 m_scene.PhysicsScene.AddPhysicsActorTaint(pa);
1883 } 2777 }
1884 } 2778 }
@@ -1886,20 +2780,10 @@ namespace OpenSim.Region.Framework.Scenes
1886 2780
1887 public Vector3 GetTorque() 2781 public Vector3 GetTorque()
1888 { 2782 {
1889 PhysicsActor pa = RootPart.PhysActor; 2783 return RootPart.Torque;
1890
1891 if (pa != null)
1892 {
1893 if (!IsAttachment)
1894 {
1895 Vector3 torque = pa.Torque;
1896 return torque;
1897 }
1898 }
1899
1900 return Vector3.Zero;
1901 } 2784 }
1902 2785
2786 // This is used by llMoveToTarget() in an attached object
1903 public void MoveToTarget(Vector3 target, float tau) 2787 public void MoveToTarget(Vector3 target, float tau)
1904 { 2788 {
1905 if (IsAttachment) 2789 if (IsAttachment)
@@ -1907,7 +2791,7 @@ namespace OpenSim.Region.Framework.Scenes
1907 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar); 2791 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1908 2792
1909 if (avatar != null) 2793 if (avatar != null)
1910 avatar.MoveToTarget(target, false, false); 2794 avatar.MoveToTarget(target, false, false, tau);
1911 } 2795 }
1912 else 2796 else
1913 { 2797 {
@@ -1929,21 +2813,73 @@ namespace OpenSim.Region.Framework.Scenes
1929 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar); 2813 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1930 2814
1931 if (avatar != null) 2815 if (avatar != null)
2816 {
1932 avatar.ResetMoveToTarget(); 2817 avatar.ResetMoveToTarget();
2818 }
1933 } 2819 }
1934 else 2820 else
1935 { 2821 {
1936 PhysicsActor pa = RootPart.PhysActor; 2822 PhysicsActor pa = RootPart.PhysActor;
1937 2823
1938 if (pa != null && pa.PIDActive) 2824 if (pa != null)
1939 {
1940 pa.PIDActive = false; 2825 pa.PIDActive = false;
1941 2826
1942 ScheduleGroupForTerseUpdate(); 2827 RootPart.ScheduleTerseUpdate(); // send a stop information
2828 }
2829 }
2830
2831 public void RotLookAt(Quaternion target, float strength, float damping)
2832 {
2833 if(IsDeleted)
2834 return;
2835
2836 // non physical is handle in LSL api
2837 if(!UsesPhysics || IsAttachment)
2838 return;
2839
2840 SceneObjectPart rootpart = m_rootPart;
2841 if (rootpart != null)
2842 {
2843/* physics still doesnt suport this
2844 if (rootpart.PhysActor != null)
2845 {
2846 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
2847 rootpart.PhysActor.APIDStrength = strength;
2848 rootpart.PhysActor.APIDDamping = damping;
2849 rootpart.PhysActor.APIDActive = true;
1943 } 2850 }
2851*/
2852 // so do it in rootpart
2853 rootpart.RotLookAt(target, strength, damping);
2854 }
2855 }
2856
2857 public void StartLookAt(Quaternion target, float strength, float damping)
2858 {
2859 if(IsDeleted)
2860 return;
2861
2862 // non physical is done by LSL APi
2863 if(!UsesPhysics || IsAttachment)
2864 return;
2865
2866 if (m_rootPart != null)
2867 m_rootPart.RotLookAt(target, strength, damping);
2868 }
2869
2870 public void StopLookAt()
2871 {
2872 SceneObjectPart rootpart = m_rootPart;
2873 if (rootpart != null)
2874 {
2875 if (rootpart.PhysActor != null)
2876 {
2877 rootpart.PhysActor.APIDActive = false;
2878 }
2879
2880 rootpart.StopLookAt();
1944 } 2881 }
1945 } 2882 }
1946
1947 /// <summary> 2883 /// <summary>
1948 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds. 2884 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds.
1949 /// </summary> 2885 /// </summary>
@@ -1952,7 +2888,15 @@ namespace OpenSim.Region.Framework.Scenes
1952 /// <param name="tau">Number of seconds over which to reach target</param> 2888 /// <param name="tau">Number of seconds over which to reach target</param>
1953 public void SetHoverHeight(float height, PIDHoverType hoverType, float tau) 2889 public void SetHoverHeight(float height, PIDHoverType hoverType, float tau)
1954 { 2890 {
1955 PhysicsActor pa = RootPart.PhysActor; 2891 PhysicsActor pa = null;
2892 if(IsAttachment)
2893 {
2894 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
2895 if (avatar != null)
2896 pa = avatar.PhysicsActor;
2897 }
2898 else
2899 pa = RootPart.PhysActor;
1956 2900
1957 if (pa != null) 2901 if (pa != null)
1958 { 2902 {
@@ -1960,7 +2904,7 @@ namespace OpenSim.Region.Framework.Scenes
1960 { 2904 {
1961 pa.PIDHoverHeight = height; 2905 pa.PIDHoverHeight = height;
1962 pa.PIDHoverType = hoverType; 2906 pa.PIDHoverType = hoverType;
1963 pa.PIDTau = tau; 2907 pa.PIDHoverTau = tau;
1964 pa.PIDHoverActive = true; 2908 pa.PIDHoverActive = true;
1965 } 2909 }
1966 else 2910 else
@@ -1971,25 +2915,33 @@ namespace OpenSim.Region.Framework.Scenes
1971 } 2915 }
1972 2916
1973 /// <summary> 2917 /// <summary>
1974 /// Set the owner of the root part. 2918 /// Set the owner of all linkset.
1975 /// </summary> 2919 /// </summary>
1976 /// <param name="part"></param>
1977 /// <param name="cAgentID"></param> 2920 /// <param name="cAgentID"></param>
1978 /// <param name="cGroupID"></param> 2921 /// <param name="cGroupID"></param>
1979 public void SetRootPartOwner(SceneObjectPart part, UUID cAgentID, UUID cGroupID) 2922 public void SetOwner(UUID cAgentID, UUID cGroupID)
1980 { 2923 {
1981 part.LastOwnerID = part.OwnerID; 2924 SceneObjectPart rpart = RootPart;
1982 part.OwnerID = cAgentID; 2925 UUID oldowner = rpart.OwnerID;
1983 part.GroupID = cGroupID; 2926 ForEachPart(delegate(SceneObjectPart part)
2927 {
2928 if(part.GroupID != part.OwnerID)
2929 part.LastOwnerID = part.OwnerID;
2930 part.OwnerID = cAgentID;
2931 part.GroupID = cGroupID;
2932 });
1984 2933
1985 if (part.OwnerID != cAgentID) 2934 if (oldowner != cAgentID)
1986 { 2935 {
1987 // Apply Next Owner Permissions if we're not bypassing permissions 2936 // Apply Next Owner Permissions if we're not bypassing permissions
1988 if (!m_scene.Permissions.BypassPermissions()) 2937 if (!m_scene.Permissions.BypassPermissions())
2938 {
1989 ApplyNextOwnerPermissions(); 2939 ApplyNextOwnerPermissions();
2940 InvalidateEffectivePerms();
2941 }
1990 } 2942 }
1991 2943
1992 part.ScheduleFullUpdate(); 2944 rpart.ScheduleFullUpdate();
1993 } 2945 }
1994 2946
1995 /// <summary> 2947 /// <summary>
@@ -2001,6 +2953,9 @@ namespace OpenSim.Region.Framework.Scenes
2001 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2953 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
2002 { 2954 {
2003 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2955 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
2956// SceneObjectPart newPart = part.Copy(part.LocalId, OwnerID, GroupID, m_parts.Count, userExposed);
2957// newPart.LocalId = m_scene.AllocateLocalId();
2958
2004 AddPart(newPart); 2959 AddPart(newPart);
2005 2960
2006 SetPartAsNonRoot(newPart); 2961 SetPartAsNonRoot(newPart);
@@ -2035,7 +2990,7 @@ namespace OpenSim.Region.Framework.Scenes
2035 public void ServiceObjectPropertiesFamilyRequest(IClientAPI remoteClient, UUID AgentID, uint RequestFlags) 2990 public void ServiceObjectPropertiesFamilyRequest(IClientAPI remoteClient, UUID AgentID, uint RequestFlags)
2036 { 2991 {
2037 remoteClient.SendObjectPropertiesFamilyData(RootPart, RequestFlags); 2992 remoteClient.SendObjectPropertiesFamilyData(RootPart, RequestFlags);
2038 2993
2039// remoteClient.SendObjectPropertiesFamilyData(RequestFlags, RootPart.UUID, RootPart.OwnerID, RootPart.GroupID, RootPart.BaseMask, 2994// remoteClient.SendObjectPropertiesFamilyData(RequestFlags, RootPart.UUID, RootPart.OwnerID, RootPart.GroupID, RootPart.BaseMask,
2040// RootPart.OwnerMask, RootPart.GroupMask, RootPart.EveryoneMask, RootPart.NextOwnerMask, 2995// RootPart.OwnerMask, RootPart.GroupMask, RootPart.EveryoneMask, RootPart.NextOwnerMask,
2041// RootPart.OwnershipCost, RootPart.ObjectSaleType, RootPart.SalePrice, RootPart.Category, 2996// RootPart.OwnershipCost, RootPart.ObjectSaleType, RootPart.SalePrice, RootPart.Category,
@@ -2050,6 +3005,7 @@ namespace OpenSim.Region.Framework.Scenes
2050 3005
2051 #endregion 3006 #endregion
2052 3007
3008
2053 public override void Update() 3009 public override void Update()
2054 { 3010 {
2055 // Check that the group was not deleted before the scheduled update 3011 // Check that the group was not deleted before the scheduled update
@@ -2057,7 +3013,7 @@ namespace OpenSim.Region.Framework.Scenes
2057 // an object has been deleted from a scene before update was processed. 3013 // an object has been deleted from a scene before update was processed.
2058 // A more fundamental overhaul of the update mechanism is required to eliminate all 3014 // A more fundamental overhaul of the update mechanism is required to eliminate all
2059 // the race conditions. 3015 // the race conditions.
2060 if (IsDeleted) 3016 if (IsDeleted || inTransit)
2061 return; 3017 return;
2062 3018
2063 // Even temporary objects take part in physics (e.g. temp-on-rez bullets) 3019 // Even temporary objects take part in physics (e.g. temp-on-rez bullets)
@@ -2065,31 +3021,36 @@ namespace OpenSim.Region.Framework.Scenes
2065 // return; 3021 // return;
2066 3022
2067 // If we somehow got here to updating the SOG and its root part is not scheduled for update, 3023 // If we somehow got here to updating the SOG and its root part is not scheduled for update,
2068 // check to see if the physical position or rotation warrant an update. 3024 // check to see if the physical position or rotation warrant an update.
3025/*
2069 if (m_rootPart.UpdateFlag == UpdateRequired.NONE) 3026 if (m_rootPart.UpdateFlag == UpdateRequired.NONE)
2070 { 3027 {
2071 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 3028 // rootpart SendScheduledUpdates will check if a update is needed
2072 3029 m_rootPart.UpdateFlag = UpdateRequired.TERSE;
2073 if (UsePhysics && !AbsolutePosition.ApproxEquals(lastPhysGroupPos, 0.02f)) 3030 }
2074 { 3031*/
2075 m_rootPart.UpdateFlag = UpdateRequired.TERSE; 3032 if (IsAttachment)
2076 lastPhysGroupPos = AbsolutePosition; 3033 {
2077 } 3034 ScenePresence sp = m_scene.GetScenePresence(AttachedAvatar);
2078 3035 if (sp != null)
2079 if (UsePhysics && !GroupRotation.ApproxEquals(lastPhysGroupRot, 0.1f))
2080 { 3036 {
2081 m_rootPart.UpdateFlag = UpdateRequired.TERSE; 3037 sp.SendAttachmentScheduleUpdate(this);
2082 lastPhysGroupRot = GroupRotation; 3038 return;
2083 } 3039 }
2084 } 3040 }
2085 3041
3042 // while physics doesn't suports LookAt, we do it in RootPart
3043 if (!IsSelected)
3044 RootPart.UpdateLookAt();
3045
3046 double now = Util.GetTimeStampMS();
3047 RootPart.SendScheduledUpdates(now);
2086 SceneObjectPart[] parts = m_parts.GetArray(); 3048 SceneObjectPart[] parts = m_parts.GetArray();
2087 for (int i = 0; i < parts.Length; i++) 3049 for (int i = 0; i < parts.Length; i++)
2088 { 3050 {
2089 SceneObjectPart part = parts[i]; 3051 SceneObjectPart part = parts[i];
2090 if (!IsSelected) 3052 if(part != RootPart)
2091 part.UpdateLookAt(); 3053 part.SendScheduledUpdates(now);
2092 part.SendScheduledUpdates();
2093 } 3054 }
2094 } 3055 }
2095 3056
@@ -2105,7 +3066,7 @@ namespace OpenSim.Region.Framework.Scenes
2105 { 3066 {
2106// if (IsAttachment) 3067// if (IsAttachment)
2107// m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, LocalId); 3068// m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, LocalId);
2108 3069
2109 checkAtTargets(); 3070 checkAtTargets();
2110 RootPart.ScheduleFullUpdate(); 3071 RootPart.ScheduleFullUpdate();
2111 3072
@@ -2144,15 +3105,24 @@ namespace OpenSim.Region.Framework.Scenes
2144 return; 3105 return;
2145 3106
2146// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 3107// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
2147
2148 RootPart.SendFullUpdateToAllClients();
2149 3108
3109 if (IsAttachment)
3110 {
3111 ScenePresence sp = m_scene.GetScenePresence(AttachedAvatar);
3112 if (sp != null)
3113 {
3114 sp.SendAttachmentUpdate(this,UpdateRequired.FULL);
3115 return;
3116 }
3117 }
3118
3119 RootPart.SendFullUpdateToAllClientsInternal();
2150 SceneObjectPart[] parts = m_parts.GetArray(); 3120 SceneObjectPart[] parts = m_parts.GetArray();
2151 for (int i = 0; i < parts.Length; i++) 3121 for (int i = 0; i < parts.Length; i++)
2152 { 3122 {
2153 SceneObjectPart part = parts[i]; 3123 SceneObjectPart part = parts[i];
2154 if (part != RootPart) 3124 if (part != RootPart)
2155 part.SendFullUpdateToAllClients(); 3125 part.SendFullUpdateToAllClientsInternal();
2156 } 3126 }
2157 } 3127 }
2158 3128
@@ -2164,7 +3134,7 @@ namespace OpenSim.Region.Framework.Scenes
2164 /// </summary> 3134 /// </summary>
2165 public void SendGroupRootTerseUpdate() 3135 public void SendGroupRootTerseUpdate()
2166 { 3136 {
2167 if (IsDeleted) 3137 if (IsDeleted || inTransit)
2168 return; 3138 return;
2169 3139
2170 RootPart.SendTerseUpdateToAllClients(); 3140 RootPart.SendTerseUpdateToAllClients();
@@ -2174,7 +3144,7 @@ namespace OpenSim.Region.Framework.Scenes
2174 { 3144 {
2175 if (m_scene == null) // Need to check here as it's null during object creation 3145 if (m_scene == null) // Need to check here as it's null during object creation
2176 return; 3146 return;
2177 3147
2178 m_scene.SceneGraph.AddToUpdateList(this); 3148 m_scene.SceneGraph.AddToUpdateList(this);
2179 } 3149 }
2180 3150
@@ -2183,12 +3153,22 @@ namespace OpenSim.Region.Framework.Scenes
2183 /// </summary> 3153 /// </summary>
2184 public void SendGroupTerseUpdate() 3154 public void SendGroupTerseUpdate()
2185 { 3155 {
2186 if (IsDeleted) 3156 if (IsDeleted || inTransit)
2187 return; 3157 return;
2188 3158
3159 if (IsAttachment)
3160 {
3161 ScenePresence sp = m_scene.GetScenePresence(AttachedAvatar);
3162 if (sp != null)
3163 {
3164 sp.SendAttachmentUpdate(this, UpdateRequired.TERSE);
3165 return;
3166 }
3167 }
3168
2189 SceneObjectPart[] parts = m_parts.GetArray(); 3169 SceneObjectPart[] parts = m_parts.GetArray();
2190 for (int i = 0; i < parts.Length; i++) 3170 for (int i = 0; i < parts.Length; i++)
2191 parts[i].SendTerseUpdateToAllClients(); 3171 parts[i].SendTerseUpdateToAllClientsInternal();
2192 } 3172 }
2193 3173
2194 /// <summary> 3174 /// <summary>
@@ -2296,9 +3276,41 @@ namespace OpenSim.Region.Framework.Scenes
2296 return; 3276 return;
2297 } 3277 }
2298 3278
3279 // physical prims count limit
3280 // not very eficient :(
3281
3282 if (UsesPhysics && m_scene.m_linksetPhysCapacity > 0 && (PrimCount + objectGroup.PrimCount) >
3283 m_scene.m_linksetPhysCapacity)
3284 {
3285 int cntr = 0;
3286 foreach (SceneObjectPart part in Parts)
3287 {
3288 if (part.PhysicsShapeType != (byte)PhysicsShapeType.None)
3289 cntr++;
3290 }
3291 foreach (SceneObjectPart part in objectGroup.Parts)
3292 {
3293 if (part.PhysicsShapeType != (byte)PhysicsShapeType.None)
3294 cntr++;
3295 }
3296
3297 if (cntr > m_scene.m_linksetPhysCapacity)
3298 {
3299 // cancel physics
3300 RootPart.Flags &= ~PrimFlags.Physics;
3301 ApplyPhysics();
3302 }
3303 }
3304
3305
2299 // 'linkPart' == the root of the group being linked into this group 3306 // 'linkPart' == the root of the group being linked into this group
2300 SceneObjectPart linkPart = objectGroup.m_rootPart; 3307 SceneObjectPart linkPart = objectGroup.m_rootPart;
2301 3308
3309 if (m_rootPart.PhysActor != null)
3310 m_rootPart.PhysActor.Building = true;
3311 if (linkPart.PhysActor != null)
3312 linkPart.PhysActor.Building = true;
3313
2302 // physics flags from group to be applied to linked parts 3314 // physics flags from group to be applied to linked parts
2303 bool grpusephys = UsesPhysics; 3315 bool grpusephys = UsesPhysics;
2304 bool grptemporary = IsTemporary; 3316 bool grptemporary = IsTemporary;
@@ -2307,7 +3319,7 @@ namespace OpenSim.Region.Framework.Scenes
2307 Vector3 oldGroupPosition = linkPart.GroupPosition; 3319 Vector3 oldGroupPosition = linkPart.GroupPosition;
2308 Quaternion oldRootRotation = linkPart.RotationOffset; 3320 Quaternion oldRootRotation = linkPart.RotationOffset;
2309 3321
2310 // A linked SOP remembers its location and rotation relative to the root of a group. 3322 // A linked SOP remembers its location and rotation relative to the root of a group.
2311 // Convert the root of the group being linked to be relative to the 3323 // Convert the root of the group being linked to be relative to the
2312 // root of the group being linked to. 3324 // root of the group being linked to.
2313 // Note: Some of the assignments have complex side effects. 3325 // Note: Some of the assignments have complex side effects.
@@ -2315,22 +3327,24 @@ namespace OpenSim.Region.Framework.Scenes
2315 // First move the new group's root SOP's position to be relative to ours 3327 // First move the new group's root SOP's position to be relative to ours
2316 // (radams1: Not sure if the multiple setting of OffsetPosition is required. If not, 3328 // (radams1: Not sure if the multiple setting of OffsetPosition is required. If not,
2317 // this code can be reordered to have a more logical flow.) 3329 // this code can be reordered to have a more logical flow.)
2318 linkPart.OffsetPosition = linkPart.GroupPosition - AbsolutePosition; 3330 linkPart.setOffsetPosition(linkPart.GroupPosition - AbsolutePosition);
2319 // Assign the new parent to the root of the old group 3331 // Assign the new parent to the root of the old group
2320 linkPart.ParentID = m_rootPart.LocalId; 3332 linkPart.ParentID = m_rootPart.LocalId;
2321 // Now that it's a child, it's group position is our root position 3333 // Now that it's a child, it's group position is our root position
2322 linkPart.GroupPosition = AbsolutePosition; 3334 linkPart.setGroupPosition(AbsolutePosition);
2323 3335
2324 Vector3 axPos = linkPart.OffsetPosition;
2325 // Rotate the linking root SOP's position to be relative to the new root prim 3336 // Rotate the linking root SOP's position to be relative to the new root prim
2326 Quaternion parentRot = m_rootPart.RotationOffset; 3337 Quaternion parentRot = m_rootPart.RotationOffset;
2327 axPos *= Quaternion.Inverse(parentRot);
2328 linkPart.OffsetPosition = axPos;
2329 3338
2330 // Make the linking root SOP's rotation relative to the new root prim 3339 // Make the linking root SOP's rotation relative to the new root prim
2331 Quaternion oldRot = linkPart.RotationOffset; 3340 Quaternion oldRot = linkPart.RotationOffset;
2332 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 3341 Quaternion newRot = Quaternion.Conjugate(parentRot) * oldRot;
2333 linkPart.RotationOffset = newRot; 3342 linkPart.setRotationOffset(newRot);
3343
3344 Vector3 axPos = linkPart.OffsetPosition;
3345 axPos *= Quaternion.Conjugate(parentRot);
3346 linkPart.OffsetPosition = axPos;
3347
2334 3348
2335 // If there is only one SOP in a SOG, the LinkNum is zero. I.e., not a linkset. 3349 // If there is only one SOP in a SOG, the LinkNum is zero. I.e., not a linkset.
2336 // Now that we know this SOG has at least two SOPs in it, the new root 3350 // Now that we know this SOG has at least two SOPs in it, the new root
@@ -2345,10 +3359,11 @@ namespace OpenSim.Region.Framework.Scenes
2345 if (insert) 3359 if (insert)
2346 { 3360 {
2347 linkNum = 2; 3361 linkNum = 2;
3362 int insertSize = objectGroup.PrimCount;
2348 foreach (SceneObjectPart part in Parts) 3363 foreach (SceneObjectPart part in Parts)
2349 { 3364 {
2350 if (part.LinkNum > 1) 3365 if (part.LinkNum > 1)
2351 part.LinkNum++; 3366 part.LinkNum += insertSize;
2352 } 3367 }
2353 } 3368 }
2354 else 3369 else
@@ -2360,10 +3375,12 @@ namespace OpenSim.Region.Framework.Scenes
2360 m_parts.Add(linkPart.UUID, linkPart); 3375 m_parts.Add(linkPart.UUID, linkPart);
2361 3376
2362 linkPart.SetParent(this); 3377 linkPart.SetParent(this);
3378 m_scene.updateScenePartGroup(linkPart, this);
3379
2363 linkPart.CreateSelected = true; 3380 linkPart.CreateSelected = true;
2364 3381
2365 // let physics know preserve part volume dtc messy since UpdatePrimFlags doesn't look to parent changes for now 3382 // let physics know preserve part volume dtc messy since UpdatePrimFlags doesn't look to parent changes for now
2366 linkPart.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (linkPart.Flags & PrimFlags.Phantom) != 0), linkPart.VolumeDetectActive); 3383 linkPart.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (linkPart.Flags & PrimFlags.Phantom) != 0), linkPart.VolumeDetectActive, true);
2367 3384
2368 // If the added SOP is physical, also tell the physics engine about the link relationship. 3385 // If the added SOP is physical, also tell the physics engine about the link relationship.
2369 if (linkPart.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical) 3386 if (linkPart.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical)
@@ -2373,15 +3390,16 @@ namespace OpenSim.Region.Framework.Scenes
2373 } 3390 }
2374 3391
2375 linkPart.LinkNum = linkNum++; 3392 linkPart.LinkNum = linkNum++;
3393 linkPart.UpdatePrimFlags(UsesPhysics, IsTemporary, IsPhantom, IsVolumeDetect, false);
2376 3394
2377 // Get a list of the SOP's in the old group in order of their linknum's. 3395 // Get a list of the SOP's in the source group in order of their linknum's.
2378 SceneObjectPart[] ogParts = objectGroup.Parts; 3396 SceneObjectPart[] ogParts = objectGroup.Parts;
2379 Array.Sort(ogParts, delegate(SceneObjectPart a, SceneObjectPart b) 3397 Array.Sort(ogParts, delegate(SceneObjectPart a, SceneObjectPart b)
2380 { 3398 {
2381 return a.LinkNum - b.LinkNum; 3399 return a.LinkNum - b.LinkNum;
2382 }); 3400 });
2383 3401
2384 // Add each of the SOP's from the old linkset to our linkset 3402 // Add each of the SOP's from the source linkset to our linkset
2385 for (int i = 0; i < ogParts.Length; i++) 3403 for (int i = 0; i < ogParts.Length; i++)
2386 { 3404 {
2387 SceneObjectPart part = ogParts[i]; 3405 SceneObjectPart part = ogParts[i];
@@ -2391,7 +3409,7 @@ namespace OpenSim.Region.Framework.Scenes
2391 3409
2392 // Update the physics flags for the newly added SOP 3410 // Update the physics flags for the newly added SOP
2393 // (Is this necessary? LinkNonRootPart() has already called UpdatePrimFlags but with different flags!??) 3411 // (Is this necessary? LinkNonRootPart() has already called UpdatePrimFlags but with different flags!??)
2394 part.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (part.Flags & PrimFlags.Phantom) != 0), part.VolumeDetectActive); 3412 part.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (part.Flags & PrimFlags.Phantom) != 0), part.VolumeDetectActive, true);
2395 3413
2396 // If the added SOP is physical, also tell the physics engine about the link relationship. 3414 // If the added SOP is physical, also tell the physics engine about the link relationship.
2397 if (part.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical) 3415 if (part.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical)
@@ -2420,11 +3438,17 @@ namespace OpenSim.Region.Framework.Scenes
2420 3438
2421 AttachToBackup(); 3439 AttachToBackup();
2422 3440
2423 // Here's the deal, this is ABSOLUTELY CRITICAL so the physics scene gets the update about the 3441 // Here's the deal, this is ABSOLUTELY CRITICAL so the physics scene gets the update about the
2424 // position of linkset prims. IF YOU CHANGE THIS, YOU MUST TEST colliding with just linked and 3442 // position of linkset prims. IF YOU CHANGE THIS, YOU MUST TEST colliding with just linked and
2425 // unmoved prims! 3443 // unmoved prims!
2426 ResetChildPrimPhysicsPositions(); 3444 ResetChildPrimPhysicsPositions();
2427 3445
3446 InvalidBoundsRadius();
3447 InvalidatePartsLinkMaps();
3448
3449 if (m_rootPart.PhysActor != null)
3450 m_rootPart.PhysActor.Building = false;
3451
2428 //HasGroupChanged = true; 3452 //HasGroupChanged = true;
2429 //ScheduleGroupForFullUpdate(); 3453 //ScheduleGroupForFullUpdate();
2430 } 3454 }
@@ -2492,7 +3516,10 @@ namespace OpenSim.Region.Framework.Scenes
2492// m_log.DebugFormat( 3516// m_log.DebugFormat(
2493// "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}", 3517// "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}",
2494// linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID); 3518// linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID);
2495 3519
3520 if (m_rootPart.PhysActor != null)
3521 m_rootPart.PhysActor.Building = true;
3522
2496 linkPart.ClearUndoState(); 3523 linkPart.ClearUndoState();
2497 3524
2498 Vector3 worldPos = linkPart.GetWorldPosition(); 3525 Vector3 worldPos = linkPart.GetWorldPosition();
@@ -2533,7 +3560,10 @@ namespace OpenSim.Region.Framework.Scenes
2533 // engine about the delink. Someday, linksets should be made first 3560 // engine about the delink. Someday, linksets should be made first
2534 // class objects in the physics engine interface). 3561 // class objects in the physics engine interface).
2535 if (linkPartPa != null) 3562 if (linkPartPa != null)
3563 {
2536 m_scene.PhysicsScene.RemovePrim(linkPartPa); 3564 m_scene.PhysicsScene.RemovePrim(linkPartPa);
3565 linkPart.PhysActor = null;
3566 }
2537 3567
2538 // We need to reset the child part's position 3568 // We need to reset the child part's position
2539 // ready for life as a separate object after being a part of another object 3569 // ready for life as a separate object after being a part of another object
@@ -2547,43 +3577,155 @@ namespace OpenSim.Region.Framework.Scenes
2547 linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition; 3577 linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition;
2548 linkPart.OffsetPosition = new Vector3(0, 0, 0); 3578 linkPart.OffsetPosition = new Vector3(0, 0, 0);
2549 */ 3579 */
2550 linkPart.GroupPosition = worldPos; 3580 linkPart.setGroupPosition(worldPos);
2551 linkPart.OffsetPosition = Vector3.Zero; 3581 linkPart.setOffsetPosition(Vector3.Zero);
2552 linkPart.RotationOffset = worldRot; 3582 linkPart.setRotationOffset(worldRot);
2553 3583
2554 // Create a new SOG to go around this unlinked and unattached SOP 3584 // Create a new SOG to go around this unlinked and unattached SOP
2555 SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart); 3585 SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart);
2556 3586
2557 m_scene.AddNewSceneObject(objectGroup, true); 3587 m_scene.AddNewSceneObject(objectGroup, true);
2558 3588
2559 if (sendEvents)
2560 linkPart.TriggerScriptChangedEvent(Changed.LINK);
2561
2562 linkPart.Rezzed = RootPart.Rezzed; 3589 linkPart.Rezzed = RootPart.Rezzed;
2563 3590
2564 // We must persist the delinked group to the database immediately, for safety. The problem 3591 // When we delete a group, we currently have to force persist to the database if the object id has changed
2565 // is that although in memory the new group has a new SceneGroupID, in the database it 3592 // (since delete works by deleting all rows which have a given object id)
2566 // still has the parent group's SceneGroupID (until the next backup). This means that if the 3593
2567 // parent group is deleted then the delinked group will also be deleted from the database. 3594 // this is as it seems to be in sl now
2568 // This problem will disappear if the region remains alive long enough for another backup, 3595 if(linkPart.PhysicsShapeType == (byte)PhysShapeType.none)
2569 // since at that time the delinked group's new SceneGroupID will be written to the database. 3596 linkPart.PhysicsShapeType = linkPart.DefaultPhysicsShapeType(); // root prims can't have type none for now
2570 // But if the region crashes before that then the prims will be permanently gone, and this must 3597
2571 // not happen. (We can't use a just-in-time trick like GroupContainsForeignPrims in this case 3598 if (m_rootPart.PhysActor != null)
2572 // because the delinked group doesn't know when the source group is deleted.) 3599 m_rootPart.PhysActor.Building = false;
2573 m_scene.ForceSceneObjectBackup(objectGroup); 3600
3601 objectGroup.HasGroupChangedDueToDelink = true;
3602
3603 InvalidBoundsRadius();
3604 InvalidatePartsLinkMaps();
3605 objectGroup.InvalidateEffectivePerms();
3606
3607 if (sendEvents)
3608 linkPart.TriggerScriptChangedEvent(Changed.LINK);
2574 3609
2575 return objectGroup; 3610 return objectGroup;
2576 } 3611 }
2577 3612
3613/* working on it
3614 public void DelinkFromGroup(List<SceneObjectPart> linkParts, bool sendEvents)
3615 {
3616// m_log.DebugFormat(
3617// "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}",
3618// linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID);
3619
3620 if(PrimCount == 1)
3621 return;
3622
3623 if (m_rootPart.PhysActor != null)
3624 m_rootPart.PhysActor.Building = true;
3625
3626 bool unlinkroot = false;
3627 foreach(SceneObjectPart linkPart in linkParts)
3628 {
3629 // first we only remove child parts
3630 if(linkPart.LocalId == m_rootPart.LocalId)
3631 {
3632 unlinkroot = true;
3633 continue;
3634 }
3635
3636 lock (m_parts.SyncRoot)
3637 if(!m_parts.Remove(linkPart.UUID))
3638 continue;
3639
3640 linkPart.ClearUndoState();
3641
3642 Vector3 worldPos = linkPart.GetWorldPosition();
3643 Quaternion worldRot = linkPart.GetWorldRotation();
3644
3645 linkPart.ParentID = 0;
3646 linkPart.LinkNum = 0;
3647
3648 PhysicsActor linkPartPa = linkPart.PhysActor;
3649
3650 // Remove the SOP from the physical scene.
3651 // If the new SOG is physical, it is re-created later.
3652 // (There is a problem here in that we have not yet told the physics
3653 // engine about the delink. Someday, linksets should be made first
3654 // class objects in the physics engine interface).
3655 if (linkPartPa != null)
3656 {
3657 m_scene.PhysicsScene.RemovePrim(linkPartPa);
3658 linkPart.PhysActor = null;
3659 }
3660
3661 linkPart.setGroupPosition(worldPos);
3662 linkPart.setOffsetPosition(Vector3.Zero);
3663 linkPart.setRotationOffset(worldRot);
3664
3665 // Create a new SOG to go around this unlinked and unattached SOP
3666 SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart);
3667
3668 m_scene.AddNewSceneObject(objectGroup, true);
3669
3670 linkPart.Rezzed = RootPart.Rezzed;
3671
3672 // this is as it seems to be in sl now
3673 if(linkPart.PhysicsShapeType == (byte)PhysShapeType.none)
3674 linkPart.PhysicsShapeType = linkPart.DefaultPhysicsShapeType(); // root prims can't have type none for now
3675
3676 objectGroup.HasGroupChangedDueToDelink = true;
3677 if (sendEvents)
3678 linkPart.TriggerScriptChangedEvent(Changed.LINK);
3679 }
3680
3681 if(unlinkroot)
3682 {
3683 //TODO
3684 }
3685
3686 lock (m_parts.SyncRoot)
3687 {
3688 SceneObjectPart[] parts = m_parts.GetArray();
3689 if (parts.Length == 1)
3690 {
3691 // Single prim left
3692 m_rootPart.LinkNum = 0;
3693 }
3694 else
3695 {
3696 m_rootPart.LinkNum = 1;
3697 int linknum = 2;
3698 for (int i = 1; i < parts.Length; i++)
3699 parts[i].LinkNum = linknum++;
3700 }
3701 }
3702
3703 InvalidBoundsRadius();
3704
3705 if (m_rootPart.PhysActor != null)
3706 m_rootPart.PhysActor.Building = false;
3707
3708 // When we delete a group, we currently have to force persist to the database if the object id has changed
3709 // (since delete works by deleting all rows which have a given object id)
3710
3711 Scene.SimulationDataService.RemoveObject(UUID, Scene.RegionInfo.RegionID);
3712 HasGroupChangedDueToDelink = true;
3713 TriggerScriptChangedEvent(Changed.LINK);
3714 return;
3715 }
3716*/
2578 /// <summary> 3717 /// <summary>
2579 /// Stop this object from being persisted over server restarts. 3718 /// Stop this object from being persisted over server restarts.
2580 /// </summary> 3719 /// </summary>
2581 /// <param name="objectGroup"></param> 3720 /// <param name="objectGroup"></param>
2582 public virtual void DetachFromBackup() 3721 public virtual void DetachFromBackup()
2583 { 3722 {
2584 if (Backup && Scene != null) 3723 if (m_scene != null)
2585 m_scene.EventManager.OnBackup -= ProcessBackup; 3724 {
2586 3725 m_scene.SceneGraph.FireDetachFromBackup(this);
3726 if (Backup)
3727 m_scene.EventManager.OnBackup -= ProcessBackup;
3728 }
2587 Backup = false; 3729 Backup = false;
2588 } 3730 }
2589 3731
@@ -2597,14 +3739,14 @@ namespace OpenSim.Region.Framework.Scenes
2597 Quaternion parentRot = oldGroupRotation; 3739 Quaternion parentRot = oldGroupRotation;
2598 Quaternion oldRot = part.RotationOffset; 3740 Quaternion oldRot = part.RotationOffset;
2599 3741
2600 // Move our position to not be relative to the old parent 3742 // Move our position in world
2601 Vector3 axPos = part.OffsetPosition; 3743 Vector3 axPos = part.OffsetPosition;
2602 axPos *= parentRot; 3744 axPos *= parentRot;
2603 part.OffsetPosition = axPos; 3745 Vector3 newPos = oldGroupPosition + axPos;
2604 part.GroupPosition = oldGroupPosition + part.OffsetPosition; 3746 part.setGroupPosition(newPos);
2605 part.OffsetPosition = Vector3.Zero; 3747 part.setOffsetPosition(Vector3.Zero);
2606 3748
2607 // Compution our rotation to be not relative to the old parent 3749 // Compution our rotation in world
2608 Quaternion worldRot = parentRot * oldRot; 3750 Quaternion worldRot = parentRot * oldRot;
2609 part.RotationOffset = worldRot; 3751 part.RotationOffset = worldRot;
2610 3752
@@ -2615,29 +3757,32 @@ namespace OpenSim.Region.Framework.Scenes
2615 3757
2616 part.LinkNum = linkNum; 3758 part.LinkNum = linkNum;
2617 3759
3760 m_scene.updateScenePartGroup(part, this);
3761
2618 // Compute the new position of this SOP relative to the group position 3762 // Compute the new position of this SOP relative to the group position
2619 part.OffsetPosition = part.GroupPosition - AbsolutePosition; 3763 part.setOffsetPosition(newPos - AbsolutePosition);
2620 3764
2621 // (radams1 20120711: I don't know why part.OffsetPosition is set multiple times. 3765 // (radams1 20120711: I don't know why part.OffsetPosition is set multiple times.
2622 // It would have the affect of setting the physics engine position multiple 3766 // It would have the affect of setting the physics engine position multiple
2623 // times. In theory, that is not necessary but I don't have a good linkset 3767 // times. In theory, that is not necessary but I don't have a good linkset
2624 // test to know that cleaning up this code wouldn't break things.) 3768 // test to know that cleaning up this code wouldn't break things.)
2625 3769
2626 // Rotate the relative position by the rotation of the group
2627 Quaternion rootRotation = m_rootPart.RotationOffset;
2628 Vector3 pos = part.OffsetPosition;
2629 pos *= Quaternion.Inverse(rootRotation);
2630 part.OffsetPosition = pos;
2631
2632 // Compute the SOP's rotation relative to the rotation of the group. 3770 // Compute the SOP's rotation relative to the rotation of the group.
2633 parentRot = m_rootPart.RotationOffset; 3771 parentRot = m_rootPart.RotationOffset;
3772
2634 oldRot = part.RotationOffset; 3773 oldRot = part.RotationOffset;
2635 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 3774 Quaternion newRot = Quaternion.Conjugate(parentRot) * worldRot;
2636 part.RotationOffset = newRot; 3775 part.setRotationOffset(newRot);
3776
3777 Vector3 pos = part.OffsetPosition;
3778 pos *= Quaternion.Conjugate(parentRot);
3779
3780 part.OffsetPosition = pos; // update position and orientation on physics also
2637 3781
2638 // Since this SOP's state has changed, push those changes into the physics engine 3782 // Since this SOP's state has changed, push those changes into the physics engine
2639 // and the simulator. 3783 // and the simulator.
2640 part.UpdatePrimFlags(UsesPhysics, IsTemporary, IsPhantom, IsVolumeDetect); 3784 // done on caller
3785// part.UpdatePrimFlags(UsesPhysics, IsTemporary, IsPhantom, IsVolumeDetect, false);
2641 } 3786 }
2642 3787
2643 /// <summary> 3788 /// <summary>
@@ -2652,30 +3797,26 @@ namespace OpenSim.Region.Framework.Scenes
2652 { 3797 {
2653 if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) 3798 if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
2654 { 3799 {
3800 if (BlockGrabOverride)
3801 return;
3802
2655 SceneObjectPart part = GetPart(partID); 3803 SceneObjectPart part = GetPart(partID);
2656 3804
2657 if (part == null) 3805 if (part == null)
2658 return; 3806 return;
2659 3807
3808 if (part.BlockGrab)
3809 return;
3810
2660 PhysicsActor pa = m_rootPart.PhysActor; 3811 PhysicsActor pa = m_rootPart.PhysActor;
2661 3812
2662 if (pa != null) 3813 if (pa != null && pa.IsPhysical)
2663 { 3814 {
2664 if (pa.IsPhysical) 3815 // empirically convert distance diference to a impulse
2665 { 3816 Vector3 grabforce = pos - AbsolutePosition;
2666 if (!BlockGrabOverride && !part.BlockGrab) 3817 grabforce = grabforce * (pa.Mass * 0.1f);
2667 { 3818 pa.AddForce(grabforce, false);
2668 Vector3 llmoveforce = pos - AbsolutePosition; 3819 m_scene.PhysicsScene.AddPhysicsActorTaint(pa);
2669 Vector3 grabforce = llmoveforce;
2670 grabforce = (grabforce / 10) * pa.Mass;
2671 pa.AddForce(grabforce, true);
2672 m_scene.PhysicsScene.AddPhysicsActorTaint(pa);
2673 }
2674 }
2675 else
2676 {
2677 NonPhysicalGrabMovement(pos);
2678 }
2679 } 3820 }
2680 else 3821 else
2681 { 3822 {
@@ -2704,6 +3845,8 @@ namespace OpenSim.Region.Framework.Scenes
2704 /// <param name="remoteClient"></param> 3845 /// <param name="remoteClient"></param>
2705 public void SpinStart(IClientAPI remoteClient) 3846 public void SpinStart(IClientAPI remoteClient)
2706 { 3847 {
3848 if (BlockGrabOverride || m_rootPart.BlockGrab)
3849 return;
2707 if (m_scene.EventManager.TriggerGroupSpinStart(UUID)) 3850 if (m_scene.EventManager.TriggerGroupSpinStart(UUID))
2708 { 3851 {
2709 PhysicsActor pa = m_rootPart.PhysActor; 3852 PhysicsActor pa = m_rootPart.PhysActor;
@@ -2725,72 +3868,74 @@ namespace OpenSim.Region.Framework.Scenes
2725 /// <param name="remoteClient"></param> 3868 /// <param name="remoteClient"></param>
2726 public void SpinMovement(Quaternion newOrientation, IClientAPI remoteClient) 3869 public void SpinMovement(Quaternion newOrientation, IClientAPI remoteClient)
2727 { 3870 {
2728 // The incoming newOrientation, sent by the client, "seems" to be the 3871 // The incoming newOrientation, sent by the client, "seems" to be the
2729 // desired target orientation. This needs further verification; in particular, 3872 // desired target orientation. This needs further verification; in particular,
2730 // one would expect that the initial incoming newOrientation should be 3873 // one would expect that the initial incoming newOrientation should be
2731 // fairly close to the original prim's physical orientation, 3874 // fairly close to the original prim's physical orientation,
2732 // m_rootPart.PhysActor.Orientation. This however does not seem to be the 3875 // m_rootPart.PhysActor.Orientation. This however does not seem to be the
2733 // case (might just be an issue with different quaternions representing the 3876 // case (might just be an issue with different quaternions representing the
2734 // same rotation, or it might be a coordinate system issue). 3877 // same rotation, or it might be a coordinate system issue).
2735 // 3878 //
2736 // Since it's not clear what the relationship is between the PhysActor.Orientation 3879 // Since it's not clear what the relationship is between the PhysActor.Orientation
2737 // and the incoming orientations sent by the client, we take an alternative approach 3880 // and the incoming orientations sent by the client, we take an alternative approach
2738 // of calculating the delta rotation between the orientations being sent by the 3881 // of calculating the delta rotation between the orientations being sent by the
2739 // client. (Since a spin is invoked by ctrl+shift+drag in the client, we expect 3882 // client. (Since a spin is invoked by ctrl+shift+drag in the client, we expect
2740 // a steady stream of several new orientations coming in from the client.) 3883 // a steady stream of several new orientations coming in from the client.)
2741 // This ensures that the delta rotations are being calculated from self-consistent 3884 // This ensures that the delta rotations are being calculated from self-consistent
2742 // pairs of old/new rotations. Given the delta rotation, we apply a torque around 3885 // pairs of old/new rotations. Given the delta rotation, we apply a torque around
2743 // the delta rotation axis, scaled by the object mass times an arbitrary scaling 3886 // the delta rotation axis, scaled by the object mass times an arbitrary scaling
2744 // factor (to ensure the resulting torque is not "too strong" or "too weak"). 3887 // factor (to ensure the resulting torque is not "too strong" or "too weak").
2745 // 3888 //
2746 // Ideally we need to calculate (probably iteratively) the exact torque or series 3889 // Ideally we need to calculate (probably iteratively) the exact torque or series
2747 // of torques needed to arrive exactly at the destination orientation. However, since 3890 // of torques needed to arrive exactly at the destination orientation. However, since
2748 // it is not yet clear how to map the destination orientation (provided by the viewer) 3891 // it is not yet clear how to map the destination orientation (provided by the viewer)
2749 // into PhysActor orientations (needed by the physics engine), we omit this step. 3892 // into PhysActor orientations (needed by the physics engine), we omit this step.
2750 // This means that the resulting torque will at least be in the correct direction, 3893 // This means that the resulting torque will at least be in the correct direction,
2751 // but it will result in over-shoot or under-shoot of the target orientation. 3894 // but it will result in over-shoot or under-shoot of the target orientation.
2752 // For the end user, this means that ctrl+shift+drag can be used for relative, 3895 // For the end user, this means that ctrl+shift+drag can be used for relative,
2753 // but not absolute, adjustments of orientation for physical prims. 3896 // but not absolute, adjustments of orientation for physical prims.
3897
3898 if (BlockGrabOverride || m_rootPart.BlockGrab)
3899 return;
3900
2754 if (m_scene.EventManager.TriggerGroupSpin(UUID, newOrientation)) 3901 if (m_scene.EventManager.TriggerGroupSpin(UUID, newOrientation))
2755 { 3902 {
2756 PhysicsActor pa = m_rootPart.PhysActor; 3903 PhysicsActor pa = m_rootPart.PhysActor;
2757 3904
2758 if (pa != null) 3905 if (pa != null && pa.IsPhysical)
2759 { 3906 {
2760 if (pa.IsPhysical) 3907 if (m_rootPart.IsWaitingForFirstSpinUpdatePacket)
2761 { 3908 {
2762 if (m_rootPart.IsWaitingForFirstSpinUpdatePacket) 3909 // first time initialization of "old" orientation for calculation of delta rotations
2763 { 3910 m_rootPart.SpinOldOrientation = newOrientation;
2764 // first time initialization of "old" orientation for calculation of delta rotations 3911 m_rootPart.IsWaitingForFirstSpinUpdatePacket = false;
2765 m_rootPart.SpinOldOrientation = newOrientation;
2766 m_rootPart.IsWaitingForFirstSpinUpdatePacket = false;
2767 }
2768 else
2769 {
2770 // save and update old orientation
2771 Quaternion old = m_rootPart.SpinOldOrientation;
2772 m_rootPart.SpinOldOrientation = newOrientation;
2773 //m_log.Error("[SCENE OBJECT GROUP]: Old orientation is " + old);
2774 //m_log.Error("[SCENE OBJECT GROUP]: Incoming new orientation is " + newOrientation);
2775
2776 // compute difference between previous old rotation and new incoming rotation
2777 Quaternion minimalRotationFromQ1ToQ2 = Quaternion.Inverse(old) * newOrientation;
2778
2779 float rotationAngle;
2780 Vector3 rotationAxis;
2781 minimalRotationFromQ1ToQ2.GetAxisAngle(out rotationAxis, out rotationAngle);
2782 rotationAxis.Normalize();
2783
2784 //m_log.Error("SCENE OBJECT GROUP]: rotation axis is " + rotationAxis);
2785 Vector3 spinforce = new Vector3(rotationAxis.X, rotationAxis.Y, rotationAxis.Z);
2786 spinforce = (spinforce/8) * pa.Mass; // 8 is an arbitrary torque scaling factor
2787 pa.AddAngularForce(spinforce,true);
2788 m_scene.PhysicsScene.AddPhysicsActorTaint(pa);
2789 }
2790 } 3912 }
2791 else 3913 else
2792 { 3914 {
2793 NonPhysicalSpinMovement(newOrientation); 3915 // save and update old orientation
3916 Quaternion old = m_rootPart.SpinOldOrientation;
3917 m_rootPart.SpinOldOrientation = newOrientation;
3918 //m_log.Error("[SCENE OBJECT GROUP]: Old orientation is " + old);
3919 //m_log.Error("[SCENE OBJECT GROUP]: Incoming new orientation is " + newOrientation);
3920
3921 // compute difference between previous old rotation and new incoming rotation
3922 Quaternion minimalRotationFromQ1ToQ2 = newOrientation * Quaternion.Inverse(old);
3923
3924 float rotationAngle;
3925 Vector3 spinforce;
3926 minimalRotationFromQ1ToQ2.GetAxisAngle(out spinforce, out rotationAngle);
3927 if(Math.Abs(rotationAngle)< 0.001)
3928 return;
3929
3930 spinforce.Normalize();
3931
3932 //m_log.Error("SCENE OBJECT GROUP]: rotation axis is " + rotationAxis);
3933 if(rotationAngle > 0)
3934 spinforce = spinforce * pa.Mass * 0.1f; // 0.1 is an arbitrary torque scaling factor
3935 else
3936 spinforce = spinforce * pa.Mass * -0.1f; // 0.1 is an arbitrary torque scaling
3937 pa.AddAngularForce(spinforce,true);
3938 m_scene.PhysicsScene.AddPhysicsActorTaint(pa);
2794 } 3939 }
2795 } 3940 }
2796 else 3941 else
@@ -2880,51 +4025,80 @@ namespace OpenSim.Region.Framework.Scenes
2880 /// <param name="SetTemporary"></param> 4025 /// <param name="SetTemporary"></param>
2881 /// <param name="SetPhantom"></param> 4026 /// <param name="SetPhantom"></param>
2882 /// <param name="SetVolumeDetect"></param> 4027 /// <param name="SetVolumeDetect"></param>
2883 public void UpdatePrimFlags(uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVolumeDetect) 4028 public void UpdateFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVolumeDetect)
2884 { 4029 {
2885 SceneObjectPart selectionPart = GetPart(localID); 4030 if (m_scene == null || IsDeleted)
4031 return;
2886 4032
2887 if (Scene != null) 4033 HasGroupChanged = true;
2888 {
2889 if (SetTemporary)
2890 {
2891 DetachFromBackup();
2892 // Remove from database and parcel prim count
2893 //
2894 m_scene.DeleteFromStorage(UUID);
2895 }
2896 else if (!Backup)
2897 {
2898 // Previously been temporary now switching back so make it
2899 // available for persisting again
2900 AttachToBackup();
2901 }
2902 4034
2903 m_scene.EventManager.TriggerParcelPrimCountTainted(); 4035 if (SetTemporary)
4036 {
4037 DetachFromBackup();
4038 // Remove from database and parcel prim count
4039 //
4040 m_scene.DeleteFromStorage(UUID);
4041 }
4042 else if (!Backup)
4043 {
4044 // Previously been temporary now switching back so make it
4045 // available for persisting again
4046 AttachToBackup();
2904 } 4047 }
2905 4048
2906 if (selectionPart != null) 4049
4050 SceneObjectPart[] parts = m_parts.GetArray();
4051
4052 if (UsePhysics)
2907 { 4053 {
2908 SceneObjectPart[] parts = m_parts.GetArray(); 4054 int maxprims = m_scene.m_linksetPhysCapacity;
2909 4055 bool checkShape = (maxprims > 0 &&
2910 if (Scene != null) 4056 parts.Length > maxprims);
4057
4058 for (int i = 0; i < parts.Length; i++)
2911 { 4059 {
2912 for (int i = 0; i < parts.Length; i++) 4060 SceneObjectPart part = parts[i];
4061
4062 if(part.PhysicsShapeType == (byte)PhysicsShapeType.None)
4063 continue; // assuming root type was checked elsewhere
4064
4065 if (checkShape)
2913 { 4066 {
2914 SceneObjectPart part = parts[i]; 4067 if (--maxprims < 0)
2915 if (part.Scale.X > m_scene.m_maxPhys ||
2916 part.Scale.Y > m_scene.m_maxPhys ||
2917 part.Scale.Z > m_scene.m_maxPhys )
2918 { 4068 {
2919 UsePhysics = false; // Reset physics 4069 UsePhysics = false;
2920 break; 4070 break;
2921 } 4071 }
2922 } 4072 }
4073
4074 if (part.Scale.X > m_scene.m_maxPhys ||
4075 part.Scale.Y > m_scene.m_maxPhys ||
4076 part.Scale.Z > m_scene.m_maxPhys )
4077 {
4078 UsePhysics = false; // Reset physics
4079 break;
4080 }
2923 } 4081 }
4082 }
4083
4084 if (parts.Length > 1)
4085 {
4086 m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true);
2924 4087
2925 for (int i = 0; i < parts.Length; i++) 4088 for (int i = 0; i < parts.Length; i++)
2926 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect); 4089 {
4090
4091 if (parts[i].UUID != m_rootPart.UUID)
4092 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true);
4093 }
4094
4095 if (m_rootPart.PhysActor != null)
4096 m_rootPart.PhysActor.Building = false;
2927 } 4097 }
4098 else
4099 m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, false);
4100
4101 m_scene.EventManager.TriggerParcelPrimCountTainted();
2928 } 4102 }
2929 4103
2930 public void UpdateExtraParam(uint localID, ushort type, bool inUse, byte[] data) 4104 public void UpdateExtraParam(uint localID, ushort type, bool inUse, byte[] data)
@@ -2936,24 +4110,21 @@ namespace OpenSim.Region.Framework.Scenes
2936 } 4110 }
2937 } 4111 }
2938 4112
4113
4114
2939 /// <summary> 4115 /// <summary>
2940 /// Update the texture entry for this part 4116 /// Gets the number of parts
2941 /// </summary> 4117 /// </summary>
2942 /// <param name="localID"></param> 4118 /// <returns></returns>
2943 /// <param name="textureEntry"></param> 4119 public int GetPartCount()
2944 public void UpdateTextureEntry(uint localID, byte[] textureEntry)
2945 { 4120 {
2946 SceneObjectPart part = GetPart(localID); 4121 return Parts.Count();
2947 if (part != null)
2948 {
2949 part.UpdateTextureEntry(textureEntry);
2950 }
2951 } 4122 }
2952 4123
2953 public void AdjustChildPrimPermissions(bool forceTaskInventoryPermissive) 4124 public void AdjustChildPrimPermissions(bool forceTaskInventoryPermissive)
2954 { 4125 {
2955 uint newOwnerMask = (uint)(PermissionMask.All | PermissionMask.Export) & 0xfffffff8; // Mask folded bits 4126 uint newOwnerMask = (uint)(PermissionMask.All | PermissionMask.Export) & 0xfffffff0; // Mask folded bits
2956 uint foldedPerms = RootPart.OwnerMask & 3; 4127 uint foldedPerms = RootPart.OwnerMask & (uint)PermissionMask.FoldedMask;
2957 4128
2958 ForEachPart(part => 4129 ForEachPart(part =>
2959 { 4130 {
@@ -2964,14 +4135,14 @@ namespace OpenSim.Region.Framework.Scenes
2964 part.Inventory.ApplyGodPermissions(part.BaseMask); 4135 part.Inventory.ApplyGodPermissions(part.BaseMask);
2965 }); 4136 });
2966 4137
2967 uint lockMask = ~(uint)(PermissionMask.Move | PermissionMask.Modify); 4138 uint lockMask = ~(uint)(PermissionMask.Move);
2968 uint lockBit = RootPart.OwnerMask & (uint)(PermissionMask.Move | PermissionMask.Modify); 4139 uint lockBit = RootPart.OwnerMask & (uint)(PermissionMask.Move);
2969 RootPart.OwnerMask = (RootPart.OwnerMask & lockBit) | ((newOwnerMask | foldedPerms) & lockMask); 4140 RootPart.OwnerMask = (RootPart.OwnerMask & lockBit) | ((newOwnerMask | foldedPerms) & lockMask);
2970 4141
2971// m_log.DebugFormat( 4142// m_log.DebugFormat(
2972// "[SCENE OBJECT GROUP]: RootPart.OwnerMask now {0} for {1} in {2}", 4143// "[SCENE OBJECT GROUP]: RootPart.OwnerMask now {0} for {1} in {2}",
2973// (OpenMetaverse.PermissionMask)RootPart.OwnerMask, Name, Scene.Name); 4144// (OpenMetaverse.PermissionMask)RootPart.OwnerMask, Name, Scene.Name);
2974 4145 InvalidateEffectivePerms();
2975 RootPart.ScheduleFullUpdate(); 4146 RootPart.ScheduleFullUpdate();
2976 } 4147 }
2977 4148
@@ -2980,7 +4151,24 @@ namespace OpenSim.Region.Framework.Scenes
2980 { 4151 {
2981 RootPart.UpdatePermissions(AgentID, field, localID, mask, addRemTF); 4152 RootPart.UpdatePermissions(AgentID, field, localID, mask, addRemTF);
2982 4153
2983 AdjustChildPrimPermissions(Scene.Permissions.IsGod(AgentID)); 4154 bool god = Scene.Permissions.IsGod(AgentID);
4155
4156 if (field == 1 && god)
4157 {
4158 ForEachPart(part =>
4159 {
4160 part.BaseMask = RootPart.BaseMask;
4161 });
4162 }
4163
4164 AdjustChildPrimPermissions(false);
4165
4166 if (field == 1 && god) // Base mask was set. Update all child part inventories
4167 {
4168 foreach (SceneObjectPart part in Parts)
4169 part.Inventory.ApplyGodPermissions(RootPart.BaseMask);
4170 InvalidateEffectivePerms();
4171 }
2984 4172
2985 HasGroupChanged = true; 4173 HasGroupChanged = true;
2986 4174
@@ -3010,6 +4198,7 @@ namespace OpenSim.Region.Framework.Scenes
3010 if (pa != null) 4198 if (pa != null)
3011 m_scene.PhysicsScene.AddPhysicsActorTaint(pa); 4199 m_scene.PhysicsScene.AddPhysicsActorTaint(pa);
3012 } 4200 }
4201 InvalidBoundsRadius();
3013 } 4202 }
3014 4203
3015 #endregion 4204 #endregion
@@ -3025,163 +4214,101 @@ namespace OpenSim.Region.Framework.Scenes
3025// m_log.DebugFormat( 4214// m_log.DebugFormat(
3026// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale); 4215// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale);
3027 4216
4217 if (Scene == null)
4218 return;
4219
3028 PhysicsActor pa = m_rootPart.PhysActor; 4220 PhysicsActor pa = m_rootPart.PhysActor;
3029 4221
3030 RootPart.StoreUndoState(true); 4222 float minsize = Scene.m_minNonphys;
4223 float maxsize = Scene.m_maxNonphys;
3031 4224
3032 if (Scene != null) 4225 if (pa != null && pa.IsPhysical)
3033 { 4226 {
3034 scale.X = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.X)); 4227 minsize = Scene.m_minPhys;
3035 scale.Y = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Y)); 4228 maxsize = Scene.m_maxPhys;
3036 scale.Z = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Z));
3037
3038 if (pa != null && pa.IsPhysical)
3039 {
3040 scale.X = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.X));
3041 scale.Y = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.Y));
3042 scale.Z = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.Z));
3043 }
3044 } 4229 }
3045 4230
4231 scale.X = Util.Clamp(scale.X, minsize, maxsize);
4232 scale.Y = Util.Clamp(scale.Y, minsize, maxsize);
4233 scale.Z = Util.Clamp(scale.Z, minsize, maxsize);
4234
4235 // requested scaling factors
3046 float x = (scale.X / RootPart.Scale.X); 4236 float x = (scale.X / RootPart.Scale.X);
3047 float y = (scale.Y / RootPart.Scale.Y); 4237 float y = (scale.Y / RootPart.Scale.Y);
3048 float z = (scale.Z / RootPart.Scale.Z); 4238 float z = (scale.Z / RootPart.Scale.Z);
3049 4239
3050 SceneObjectPart[] parts = m_parts.GetArray(); 4240 SceneObjectPart[] parts = m_parts.GetArray();
3051 4241
3052 if (Scene != null & (x > 1.0f || y > 1.0f || z > 1.0f)) 4242 // fix scaling factors so parts don't violate dimensions
4243 for(int i = 0;i < parts.Length;i++)
3053 { 4244 {
3054 for (int i = 0; i < parts.Length; i++) 4245 SceneObjectPart obPart = parts[i];
4246 if(obPart.UUID != m_rootPart.UUID)
3055 { 4247 {
3056 SceneObjectPart obPart = parts[i]; 4248 Vector3 oldSize = new Vector3(obPart.Scale);
3057 if (obPart.UUID != m_rootPart.UUID)
3058 {
3059// obPart.IgnoreUndoUpdate = true;
3060 Vector3 oldSize = new Vector3(obPart.Scale);
3061 4249
3062 float f = 1.0f; 4250 float f = 1.0f;
3063 float a = 1.0f; 4251 float a = 1.0f;
3064
3065 if (pa != null && pa.IsPhysical)
3066 {
3067 if (oldSize.X * x > Scene.m_maxPhys)
3068 {
3069 f = m_scene.m_maxPhys / oldSize.X;
3070 a = f / x;
3071 x *= a;
3072 y *= a;
3073 z *= a;
3074 }
3075 else if (oldSize.X * x < Scene.m_minPhys)
3076 {
3077 f = m_scene.m_minPhys / oldSize.X;
3078 a = f / x;
3079 x *= a;
3080 y *= a;
3081 z *= a;
3082 }
3083 4252
3084 if (oldSize.Y * y > Scene.m_maxPhys) 4253 if(oldSize.X * x > maxsize)
3085 { 4254 {
3086 f = m_scene.m_maxPhys / oldSize.Y; 4255 f = maxsize / oldSize.X;
3087 a = f / y; 4256 a = f / x;
3088 x *= a; 4257 x *= a;
3089 y *= a; 4258 y *= a;
3090 z *= a; 4259 z *= a;
3091 } 4260 }
3092 else if (oldSize.Y * y < Scene.m_minPhys) 4261 else if(oldSize.X * x < minsize)
3093 { 4262 {
3094 f = m_scene.m_minPhys / oldSize.Y; 4263 f = minsize / oldSize.X;
3095 a = f / y; 4264 a = f / x;
3096 x *= a; 4265 x *= a;
3097 y *= a; 4266 y *= a;
3098 z *= a; 4267 z *= a;
3099 } 4268 }
3100
3101 if (oldSize.Z * z > Scene.m_maxPhys)
3102 {
3103 f = m_scene.m_maxPhys / oldSize.Z;
3104 a = f / z;
3105 x *= a;
3106 y *= a;
3107 z *= a;
3108 }
3109 else if (oldSize.Z * z < Scene.m_minPhys)
3110 {
3111 f = m_scene.m_minPhys / oldSize.Z;
3112 a = f / z;
3113 x *= a;
3114 y *= a;
3115 z *= a;
3116 }
3117 }
3118 else
3119 {
3120 if (oldSize.X * x > Scene.m_maxNonphys)
3121 {
3122 f = m_scene.m_maxNonphys / oldSize.X;
3123 a = f / x;
3124 x *= a;
3125 y *= a;
3126 z *= a;
3127 }
3128 else if (oldSize.X * x < Scene.m_minNonphys)
3129 {
3130 f = m_scene.m_minNonphys / oldSize.X;
3131 a = f / x;
3132 x *= a;
3133 y *= a;
3134 z *= a;
3135 }
3136
3137 if (oldSize.Y * y > Scene.m_maxNonphys)
3138 {
3139 f = m_scene.m_maxNonphys / oldSize.Y;
3140 a = f / y;
3141 x *= a;
3142 y *= a;
3143 z *= a;
3144 }
3145 else if (oldSize.Y * y < Scene.m_minNonphys)
3146 {
3147 f = m_scene.m_minNonphys / oldSize.Y;
3148 a = f / y;
3149 x *= a;
3150 y *= a;
3151 z *= a;
3152 }
3153 4269
3154 if (oldSize.Z * z > Scene.m_maxNonphys) 4270 if(oldSize.Y * y > maxsize)
3155 { 4271 {
3156 f = m_scene.m_maxNonphys / oldSize.Z; 4272 f = maxsize / oldSize.Y;
3157 a = f / z; 4273 a = f / y;
3158 x *= a; 4274 x *= a;
3159 y *= a; 4275 y *= a;
3160 z *= a; 4276 z *= a;
3161 } 4277 }
3162 else if (oldSize.Z * z < Scene.m_minNonphys) 4278 else if(oldSize.Y * y < minsize)
3163 { 4279 {
3164 f = m_scene.m_minNonphys / oldSize.Z; 4280 f = minsize / oldSize.Y;
3165 a = f / z; 4281 a = f / y;
3166 x *= a; 4282 x *= a;
3167 y *= a; 4283 y *= a;
3168 z *= a; 4284 z *= a;
3169 } 4285 }
3170 }
3171 4286
3172// obPart.IgnoreUndoUpdate = false; 4287 if(oldSize.Z * z > maxsize)
4288 {
4289 f = maxsize / oldSize.Z;
4290 a = f / z;
4291 x *= a;
4292 y *= a;
4293 z *= a;
4294 }
4295 else if(oldSize.Z * z < minsize)
4296 {
4297 f = minsize / oldSize.Z;
4298 a = f / z;
4299 x *= a;
4300 y *= a;
4301 z *= a;
3173 } 4302 }
3174 } 4303 }
3175 } 4304 }
3176 4305
3177 Vector3 prevScale = RootPart.Scale; 4306 Vector3 rootScale = RootPart.Scale;
3178 prevScale.X *= x; 4307 rootScale.X *= x;
3179 prevScale.Y *= y; 4308 rootScale.Y *= y;
3180 prevScale.Z *= z; 4309 rootScale.Z *= z;
3181 4310
3182// RootPart.IgnoreUndoUpdate = true; 4311 RootPart.Scale = rootScale;
3183 RootPart.Resize(prevScale);
3184// RootPart.IgnoreUndoUpdate = false;
3185 4312
3186 for (int i = 0; i < parts.Length; i++) 4313 for (int i = 0; i < parts.Length; i++)
3187 { 4314 {
@@ -3189,8 +4316,6 @@ namespace OpenSim.Region.Framework.Scenes
3189 4316
3190 if (obPart.UUID != m_rootPart.UUID) 4317 if (obPart.UUID != m_rootPart.UUID)
3191 { 4318 {
3192 obPart.IgnoreUndoUpdate = true;
3193
3194 Vector3 currentpos = new Vector3(obPart.OffsetPosition); 4319 Vector3 currentpos = new Vector3(obPart.OffsetPosition);
3195 currentpos.X *= x; 4320 currentpos.X *= x;
3196 currentpos.Y *= y; 4321 currentpos.Y *= y;
@@ -3201,18 +4326,190 @@ namespace OpenSim.Region.Framework.Scenes
3201 newSize.Y *= y; 4326 newSize.Y *= y;
3202 newSize.Z *= z; 4327 newSize.Z *= z;
3203 4328
3204 obPart.Resize(newSize); 4329 obPart.Scale = newSize;
3205 obPart.UpdateOffSet(currentpos); 4330 obPart.UpdateOffSet(currentpos);
4331 }
4332 }
4333
4334 InvalidBoundsRadius();
4335 HasGroupChanged = true;
4336 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE);
4337 ScheduleGroupForFullUpdate();
4338
4339 }
4340
4341 public bool GroupResize(double fscale)
4342 {
4343// m_log.DebugFormat(
4344// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, fscale);
4345
4346 if (Scene == null || IsDeleted || inTransit || fscale < 0)
4347 return false;
4348
4349 // ignore lsl restrictions. let them be done a LSL
4350 PhysicsActor pa = m_rootPart.PhysActor;
4351
4352 if(RootPart.KeyframeMotion != null)
4353 RootPart.KeyframeMotion.Suspend();
4354
4355 float minsize = Scene.m_minNonphys;
4356 float maxsize = Scene.m_maxNonphys;
3206 4357
3207 obPart.IgnoreUndoUpdate = false; 4358 // assuming physics is more restrictive
4359 if (pa != null && pa.IsPhysical)
4360 {
4361 minsize = Scene.m_minPhys;
4362 maxsize = Scene.m_maxPhys;
4363 }
4364
4365 SceneObjectPart[] parts = m_parts.GetArray();
4366 float tmp;
4367 // check scaling factor so parts don't violate dimensions
4368 for(int i = 0; i < parts.Length; i++)
4369 {
4370 SceneObjectPart obPart = parts[i];
4371 Vector3 oldSize = new Vector3(obPart.Scale);
4372 tmp = (float)(oldSize.X * fscale);
4373 if(tmp > maxsize)
4374 return false;
4375 if(tmp < minsize)
4376 return false;
4377
4378 tmp = (float)(oldSize.Y * fscale);
4379 if(tmp > maxsize)
4380 return false;
4381 if(tmp < minsize)
4382 return false;
4383
4384 tmp = (float)(oldSize.Z * fscale);
4385 if(tmp > maxsize)
4386 return false;
4387 if(tmp < minsize)
4388 return false;
4389 }
4390
4391 Vector3 newSize = RootPart.Scale;
4392 newSize.X = (float)(newSize.X * fscale);
4393 newSize.Y = (float)(newSize.Y * fscale);
4394 newSize.Z = (float)(newSize.Z * fscale);
4395
4396 if(pa != null)
4397 pa.Building = true;
4398
4399 RootPart.Scale = newSize;
4400
4401 Vector3 currentpos;
4402 for (int i = 0; i < parts.Length; i++)
4403 {
4404 SceneObjectPart obPart = parts[i];
4405
4406 if (obPart.UUID != m_rootPart.UUID)
4407 {
4408 currentpos = obPart.OffsetPosition;
4409 currentpos.X = (float)(currentpos.X * fscale);
4410 currentpos.Y = (float)(currentpos.Y * fscale);
4411 currentpos.Z = (float)(currentpos.Z * fscale);
4412
4413 newSize = obPart.Scale;
4414 newSize.X = (float)(newSize.X * fscale);
4415 newSize.Y = (float)(newSize.Y * fscale);
4416 newSize.Z = (float)(newSize.Z * fscale);
4417
4418 obPart.Scale = newSize;
4419 obPart.UpdateOffSet(currentpos);
3208 } 4420 }
4421 }
4422
4423 if(pa != null)
4424 pa.Building = false;
4425
4426 InvalidBoundsRadius();
4427
4428 HasGroupChanged = true;
4429 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE);
4430 ScheduleGroupForFullUpdate();
4431
4432 if(RootPart.KeyframeMotion != null)
4433 RootPart.KeyframeMotion.Resume();
4434
4435 return true;
4436 }
4437
4438 public float GetMaxGroupResizeScale()
4439 {
4440 if (Scene == null || IsDeleted || inTransit)
4441 return 1.0f;
4442
4443 float maxsize = Scene.m_maxNonphys;
4444 PhysicsActor pa = m_rootPart.PhysActor;
4445 // assuming physics is more restrictive
4446 if (pa != null && pa.IsPhysical)
4447 maxsize = Scene.m_maxPhys;
3209 4448
3210// obPart.IgnoreUndoUpdate = false; 4449 SceneObjectPart[] parts = m_parts.GetArray();
3211// obPart.StoreUndoState(); 4450 float larger = float.MinValue;
4451
4452 for(int i = 0; i < parts.Length; i++)
4453 {
4454 SceneObjectPart obPart = parts[i];
4455 Vector3 oldSize = new Vector3(obPart.Scale);
4456 if(larger < oldSize.X)
4457 larger = oldSize.X;
4458
4459 if(larger < oldSize.Y)
4460 larger = oldSize.Y;
4461
4462 if(larger < oldSize.Z)
4463 larger = oldSize.Z;
3212 } 4464 }
3213 4465
3214// m_log.DebugFormat( 4466 if(larger >= maxsize)
3215// "[SCENE OBJECT GROUP]: Finished group resizing {0} {1} to {2}", Name, LocalId, RootPart.Scale); 4467 return 1.0f;
4468
4469 larger += 1e-3f;
4470 float fscale = maxsize / larger;
4471
4472 return fscale;
4473 }
4474
4475 public float GetMinGroupResizeScale()
4476 {
4477 if (Scene == null || IsDeleted || inTransit)
4478 return 1.0f;
4479
4480 float minsize = Scene.m_minNonphys;
4481 PhysicsActor pa = m_rootPart.PhysActor;
4482 // assuming physics is more restrictive
4483 if (pa != null && pa.IsPhysical)
4484 minsize = Scene.m_minPhys;
4485
4486 SceneObjectPart[] parts = m_parts.GetArray();
4487 float smaller = float.MaxValue;
4488
4489 for(int i = 0; i < parts.Length; i++)
4490 {
4491 SceneObjectPart obPart = parts[i];
4492 Vector3 oldSize = new Vector3(obPart.Scale);
4493 if(smaller > oldSize.X)
4494 smaller = oldSize.X;
4495
4496 if(smaller > oldSize.Y)
4497 smaller = oldSize.Y;
4498
4499 if(smaller > oldSize.Z)
4500 smaller = oldSize.Z;
4501 }
4502
4503 if(smaller <= minsize)
4504 return 1.0f;
4505
4506 if(smaller > 2e-3f)
4507 smaller -= 1e-3f;
4508 float fscale = minsize / smaller;
4509 if(fscale < 1e-8f)
4510 fscale = 1e-8f;
4511
4512 return fscale;
3216 } 4513 }
3217 4514
3218 #endregion 4515 #endregion
@@ -3225,14 +4522,6 @@ namespace OpenSim.Region.Framework.Scenes
3225 /// <param name="pos"></param> 4522 /// <param name="pos"></param>
3226 public void UpdateGroupPosition(Vector3 pos) 4523 public void UpdateGroupPosition(Vector3 pos)
3227 { 4524 {
3228// m_log.DebugFormat("[SCENE OBJECT GROUP]: Updating group position on {0} {1} to {2}", Name, LocalId, pos);
3229
3230 RootPart.StoreUndoState(true);
3231
3232// SceneObjectPart[] parts = m_parts.GetArray();
3233// for (int i = 0; i < parts.Length; i++)
3234// parts[i].StoreUndoState();
3235
3236 if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) 4525 if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
3237 { 4526 {
3238 if (IsAttachment) 4527 if (IsAttachment)
@@ -3265,21 +4554,17 @@ namespace OpenSim.Region.Framework.Scenes
3265 /// </summary> 4554 /// </summary>
3266 /// <param name="pos"></param> 4555 /// <param name="pos"></param>
3267 /// <param name="localID"></param> 4556 /// <param name="localID"></param>
4557 ///
4558
3268 public void UpdateSinglePosition(Vector3 pos, uint localID) 4559 public void UpdateSinglePosition(Vector3 pos, uint localID)
3269 { 4560 {
3270 SceneObjectPart part = GetPart(localID); 4561 SceneObjectPart part = GetPart(localID);
3271 4562
3272// SceneObjectPart[] parts = m_parts.GetArray();
3273// for (int i = 0; i < parts.Length; i++)
3274// parts[i].StoreUndoState();
3275
3276 if (part != null) 4563 if (part != null)
3277 { 4564 {
3278// m_log.DebugFormat( 4565// unlock parts position change
3279// "[SCENE OBJECT GROUP]: Updating single position of {0} {1} to {2}", part.Name, part.LocalId, pos); 4566 if (m_rootPart.PhysActor != null)
3280 4567 m_rootPart.PhysActor.Building = true;
3281 part.StoreUndoState(false);
3282 part.IgnoreUndoUpdate = true;
3283 4568
3284 if (part.UUID == m_rootPart.UUID) 4569 if (part.UUID == m_rootPart.UUID)
3285 { 4570 {
@@ -3290,8 +4575,10 @@ namespace OpenSim.Region.Framework.Scenes
3290 part.UpdateOffSet(pos); 4575 part.UpdateOffSet(pos);
3291 } 4576 }
3292 4577
4578 if (m_rootPart.PhysActor != null)
4579 m_rootPart.PhysActor.Building = false;
4580
3293 HasGroupChanged = true; 4581 HasGroupChanged = true;
3294 part.IgnoreUndoUpdate = false;
3295 } 4582 }
3296 } 4583 }
3297 4584
@@ -3301,13 +4588,7 @@ namespace OpenSim.Region.Framework.Scenes
3301 /// <param name="newPos"></param> 4588 /// <param name="newPos"></param>
3302 public void UpdateRootPosition(Vector3 newPos) 4589 public void UpdateRootPosition(Vector3 newPos)
3303 { 4590 {
3304// m_log.DebugFormat( 4591 // needs to be called with phys building true
3305// "[SCENE OBJECT GROUP]: Updating root position of {0} {1} to {2}", Name, LocalId, pos);
3306
3307// SceneObjectPart[] parts = m_parts.GetArray();
3308// for (int i = 0; i < parts.Length; i++)
3309// parts[i].StoreUndoState();
3310
3311 Vector3 oldPos; 4592 Vector3 oldPos;
3312 4593
3313 if (IsAttachment) 4594 if (IsAttachment)
@@ -3328,12 +4609,19 @@ namespace OpenSim.Region.Framework.Scenes
3328 } 4609 }
3329 4610
3330 AbsolutePosition = newPos; 4611 AbsolutePosition = newPos;
3331 4612
3332 if (IsAttachment) 4613 if (IsAttachment)
3333 m_rootPart.AttachedPos = newPos; 4614 m_rootPart.AttachedPos = newPos;
3334 4615
3335 HasGroupChanged = true; 4616 HasGroupChanged = true;
3336 ScheduleGroupForTerseUpdate(); 4617 if (m_rootPart.Undoing)
4618 {
4619 ScheduleGroupForFullUpdate();
4620 }
4621 else
4622 {
4623 ScheduleGroupForTerseUpdate();
4624 }
3337 } 4625 }
3338 4626
3339 #endregion 4627 #endregion
@@ -3346,24 +4634,16 @@ namespace OpenSim.Region.Framework.Scenes
3346 /// <param name="rot"></param> 4634 /// <param name="rot"></param>
3347 public void UpdateGroupRotationR(Quaternion rot) 4635 public void UpdateGroupRotationR(Quaternion rot)
3348 { 4636 {
3349// m_log.DebugFormat(
3350// "[SCENE OBJECT GROUP]: Updating group rotation R of {0} {1} to {2}", Name, LocalId, rot);
3351
3352// SceneObjectPart[] parts = m_parts.GetArray();
3353// for (int i = 0; i < parts.Length; i++)
3354// parts[i].StoreUndoState();
3355
3356 m_rootPart.StoreUndoState(true);
3357
3358 m_rootPart.UpdateRotation(rot); 4637 m_rootPart.UpdateRotation(rot);
3359 4638
4639/* this is done by rootpart RotationOffset set called by UpdateRotation
3360 PhysicsActor actor = m_rootPart.PhysActor; 4640 PhysicsActor actor = m_rootPart.PhysActor;
3361 if (actor != null) 4641 if (actor != null)
3362 { 4642 {
3363 actor.Orientation = m_rootPart.RotationOffset; 4643 actor.Orientation = m_rootPart.RotationOffset;
3364 m_scene.PhysicsScene.AddPhysicsActorTaint(actor); 4644 m_scene.PhysicsScene.AddPhysicsActorTaint(actor);
3365 } 4645 }
3366 4646*/
3367 HasGroupChanged = true; 4647 HasGroupChanged = true;
3368 ScheduleGroupForTerseUpdate(); 4648 ScheduleGroupForTerseUpdate();
3369 } 4649 }
@@ -3375,16 +4655,6 @@ namespace OpenSim.Region.Framework.Scenes
3375 /// <param name="rot"></param> 4655 /// <param name="rot"></param>
3376 public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot) 4656 public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot)
3377 { 4657 {
3378// m_log.DebugFormat(
3379// "[SCENE OBJECT GROUP]: Updating group rotation PR of {0} {1} to {2}", Name, LocalId, rot);
3380
3381// SceneObjectPart[] parts = m_parts.GetArray();
3382// for (int i = 0; i < parts.Length; i++)
3383// parts[i].StoreUndoState();
3384
3385 RootPart.StoreUndoState(true);
3386 RootPart.IgnoreUndoUpdate = true;
3387
3388 m_rootPart.UpdateRotation(rot); 4658 m_rootPart.UpdateRotation(rot);
3389 4659
3390 PhysicsActor actor = m_rootPart.PhysActor; 4660 PhysicsActor actor = m_rootPart.PhysActor;
@@ -3403,8 +4673,6 @@ namespace OpenSim.Region.Framework.Scenes
3403 4673
3404 HasGroupChanged = true; 4674 HasGroupChanged = true;
3405 ScheduleGroupForTerseUpdate(); 4675 ScheduleGroupForTerseUpdate();
3406
3407 RootPart.IgnoreUndoUpdate = false;
3408 } 4676 }
3409 4677
3410 /// <summary> 4678 /// <summary>
@@ -3417,13 +4685,11 @@ namespace OpenSim.Region.Framework.Scenes
3417 SceneObjectPart part = GetPart(localID); 4685 SceneObjectPart part = GetPart(localID);
3418 4686
3419 SceneObjectPart[] parts = m_parts.GetArray(); 4687 SceneObjectPart[] parts = m_parts.GetArray();
3420 for (int i = 0; i < parts.Length; i++)
3421 parts[i].StoreUndoState();
3422 4688
3423 if (part != null) 4689 if (part != null)
3424 { 4690 {
3425// m_log.DebugFormat( 4691 if (m_rootPart.PhysActor != null)
3426// "[SCENE OBJECT GROUP]: Updating single rotation of {0} {1} to {2}", part.Name, part.LocalId, rot); 4692 m_rootPart.PhysActor.Building = true;
3427 4693
3428 if (part.UUID == m_rootPart.UUID) 4694 if (part.UUID == m_rootPart.UUID)
3429 { 4695 {
@@ -3433,6 +4699,9 @@ namespace OpenSim.Region.Framework.Scenes
3433 { 4699 {
3434 part.UpdateRotation(rot); 4700 part.UpdateRotation(rot);
3435 } 4701 }
4702
4703 if (m_rootPart.PhysActor != null)
4704 m_rootPart.PhysActor.Building = false;
3436 } 4705 }
3437 } 4706 }
3438 4707
@@ -3446,12 +4715,8 @@ namespace OpenSim.Region.Framework.Scenes
3446 SceneObjectPart part = GetPart(localID); 4715 SceneObjectPart part = GetPart(localID);
3447 if (part != null) 4716 if (part != null)
3448 { 4717 {
3449// m_log.DebugFormat( 4718 if (m_rootPart.PhysActor != null)
3450// "[SCENE OBJECT GROUP]: Updating single position and rotation of {0} {1} to {2}", 4719 m_rootPart.PhysActor.Building = true;
3451// part.Name, part.LocalId, rot);
3452
3453 part.StoreUndoState();
3454 part.IgnoreUndoUpdate = true;
3455 4720
3456 if (part.UUID == m_rootPart.UUID) 4721 if (part.UUID == m_rootPart.UUID)
3457 { 4722 {
@@ -3464,7 +4729,8 @@ namespace OpenSim.Region.Framework.Scenes
3464 part.OffsetPosition = pos; 4729 part.OffsetPosition = pos;
3465 } 4730 }
3466 4731
3467 part.IgnoreUndoUpdate = false; 4732 if (m_rootPart.PhysActor != null)
4733 m_rootPart.PhysActor.Building = false;
3468 } 4734 }
3469 } 4735 }
3470 4736
@@ -3474,15 +4740,12 @@ namespace OpenSim.Region.Framework.Scenes
3474 /// <param name="rot"></param> 4740 /// <param name="rot"></param>
3475 public void UpdateRootRotation(Quaternion rot) 4741 public void UpdateRootRotation(Quaternion rot)
3476 { 4742 {
3477// m_log.DebugFormat( 4743 // needs to be called with phys building true
3478// "[SCENE OBJECT GROUP]: Updating root rotation of {0} {1} to {2}",
3479// Name, LocalId, rot);
3480
3481 Quaternion axRot = rot; 4744 Quaternion axRot = rot;
3482 Quaternion oldParentRot = m_rootPart.RotationOffset; 4745 Quaternion oldParentRot = m_rootPart.RotationOffset;
3483 4746
3484 m_rootPart.StoreUndoState(); 4747 //Don't use UpdateRotation because it schedules an update prematurely
3485 m_rootPart.UpdateRotation(rot); 4748 m_rootPart.RotationOffset = rot;
3486 4749
3487 PhysicsActor pa = m_rootPart.PhysActor; 4750 PhysicsActor pa = m_rootPart.PhysActor;
3488 4751
@@ -3498,64 +4761,203 @@ namespace OpenSim.Region.Framework.Scenes
3498 SceneObjectPart prim = parts[i]; 4761 SceneObjectPart prim = parts[i];
3499 if (prim.UUID != m_rootPart.UUID) 4762 if (prim.UUID != m_rootPart.UUID)
3500 { 4763 {
3501 prim.IgnoreUndoUpdate = true; 4764 Quaternion NewRot = oldParentRot * prim.RotationOffset;
4765 NewRot = Quaternion.Inverse(axRot) * NewRot;
4766 prim.RotationOffset = NewRot;
4767
3502 Vector3 axPos = prim.OffsetPosition; 4768 Vector3 axPos = prim.OffsetPosition;
4769
3503 axPos *= oldParentRot; 4770 axPos *= oldParentRot;
3504 axPos *= Quaternion.Inverse(axRot); 4771 axPos *= Quaternion.Inverse(axRot);
3505 prim.OffsetPosition = axPos; 4772 prim.OffsetPosition = axPos;
3506 Quaternion primsRot = prim.RotationOffset;
3507 Quaternion newRot = oldParentRot * primsRot;
3508 newRot = Quaternion.Inverse(axRot) * newRot;
3509 prim.RotationOffset = newRot;
3510 prim.ScheduleTerseUpdate();
3511 prim.IgnoreUndoUpdate = false;
3512 } 4773 }
3513 } 4774 }
3514 4775
3515// for (int i = 0; i < parts.Length; i++) 4776 HasGroupChanged = true;
3516// { 4777 ScheduleGroupForFullUpdate();
3517// SceneObjectPart childpart = parts[i]; 4778 }
3518// if (childpart != m_rootPart)
3519// {
3520//// childpart.IgnoreUndoUpdate = false;
3521//// childpart.StoreUndoState();
3522// }
3523// }
3524 4779
3525 m_rootPart.ScheduleTerseUpdate(); 4780 private enum updatetype :int
4781 {
4782 none = 0,
4783 partterse = 1,
4784 partfull = 2,
4785 groupterse = 3,
4786 groupfull = 4
4787 }
3526 4788
3527// m_log.DebugFormat( 4789 public void doChangeObject(SceneObjectPart part, ObjectChangeData data)
3528// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}", 4790 {
3529// Name, LocalId, rot); 4791 // TODO this still as excessive *.Schedule*Update()s
4792
4793 if (part != null && part.ParentGroup != null)
4794 {
4795 ObjectChangeType change = data.change;
4796 bool togroup = ((change & ObjectChangeType.Group) != 0);
4797 // bool uniform = ((what & ObjectChangeType.UniformScale) != 0); not in use
4798
4799 SceneObjectGroup group = part.ParentGroup;
4800 PhysicsActor pha = group.RootPart.PhysActor;
4801
4802 updatetype updateType = updatetype.none;
4803
4804 if (togroup)
4805 {
4806 // related to group
4807 if ((change & (ObjectChangeType.Rotation | ObjectChangeType.Position)) != 0)
4808 {
4809 if ((change & ObjectChangeType.Rotation) != 0)
4810 {
4811 group.RootPart.UpdateRotation(data.rotation);
4812 updateType = updatetype.none;
4813 }
4814 if ((change & ObjectChangeType.Position) != 0)
4815 {
4816 if (IsAttachment || m_scene.Permissions.CanObjectEntry(group, false, data.position))
4817 UpdateGroupPosition(data.position);
4818 updateType = updatetype.groupterse;
4819 }
4820 else
4821 // ugly rotation update of all parts
4822 {
4823 group.ResetChildPrimPhysicsPositions();
4824 }
4825
4826 }
4827 if ((change & ObjectChangeType.Scale) != 0)
4828 {
4829 if (pha != null)
4830 pha.Building = true;
4831
4832 group.GroupResize(data.scale);
4833 updateType = updatetype.none;
4834
4835 if (pha != null)
4836 pha.Building = false;
4837 }
4838 }
4839 else
4840 {
4841 // related to single prim in a link-set ( ie group)
4842 if (pha != null)
4843 pha.Building = true;
4844
4845 // root part is special
4846 // parts offset positions or rotations need to change also
4847
4848 if (part == group.RootPart)
4849 {
4850 if ((change & ObjectChangeType.Rotation) != 0)
4851 group.UpdateRootRotation(data.rotation);
4852 if ((change & ObjectChangeType.Position) != 0)
4853 group.UpdateRootPosition(data.position);
4854 if ((change & ObjectChangeType.Scale) != 0)
4855 part.Resize(data.scale);
4856 }
4857 else
4858 {
4859 if ((change & ObjectChangeType.Position) != 0)
4860 {
4861 part.OffsetPosition = data.position;
4862 updateType = updatetype.partterse;
4863 }
4864 if ((change & ObjectChangeType.Rotation) != 0)
4865 {
4866 part.UpdateRotation(data.rotation);
4867 updateType = updatetype.none;
4868 }
4869 if ((change & ObjectChangeType.Scale) != 0)
4870 {
4871 part.Resize(data.scale);
4872 updateType = updatetype.none;
4873 }
4874 }
4875
4876 if (pha != null)
4877 pha.Building = false;
4878 }
4879
4880 if (updateType != updatetype.none)
4881 {
4882 group.HasGroupChanged = true;
4883
4884 switch (updateType)
4885 {
4886 case updatetype.partterse:
4887 part.ScheduleTerseUpdate();
4888 break;
4889 case updatetype.partfull:
4890 part.ScheduleFullUpdate();
4891 break;
4892 case updatetype.groupterse:
4893 group.ScheduleGroupForTerseUpdate();
4894 break;
4895 case updatetype.groupfull:
4896 group.ScheduleGroupForFullUpdate();
4897 break;
4898 default:
4899 break;
4900 }
4901 }
4902 }
3530 } 4903 }
3531 4904
3532 #endregion 4905 #endregion
3533 4906
3534 internal void SetAxisRotation(int axis, int rotate10) 4907 internal void SetAxisRotation(int axis, int rotate10)
3535 { 4908 {
3536 bool setX = false; 4909 bool setX = ((axis & (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_X) != 0);
3537 bool setY = false; 4910 bool setY = ((axis & (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Y) != 0);
3538 bool setZ = false; 4911 bool setZ = ((axis & (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Z) != 0);
3539 4912
3540 int xaxis = 2; 4913 if (setX || setY || setZ)
3541 int yaxis = 4; 4914 {
3542 int zaxis = 8; 4915 bool lockaxis = (rotate10 == 0); // zero means axis locked
3543 4916
3544 setX = ((axis & xaxis) != 0) ? true : false; 4917 byte locks = RootPart.RotationAxisLocks;
3545 setY = ((axis & yaxis) != 0) ? true : false;
3546 setZ = ((axis & zaxis) != 0) ? true : false;
3547 4918
3548 float setval = (rotate10 > 0) ? 1f : 0f; 4919 if (setX)
4920 {
4921 if(lockaxis)
4922 locks |= (byte)SceneObjectGroup.axisSelect.STATUS_ROTATE_X;
4923 else
4924 locks &= (byte)SceneObjectGroup.axisSelect.NOT_STATUS_ROTATE_X;
4925 }
3549 4926
3550 if (setX) 4927 if (setY)
3551 RootPart.RotationAxis.X = setval; 4928 {
3552 if (setY) 4929 if(lockaxis)
3553 RootPart.RotationAxis.Y = setval; 4930 locks |= (byte)SceneObjectGroup.axisSelect.STATUS_ROTATE_Y;
3554 if (setZ) 4931 else
3555 RootPart.RotationAxis.Z = setval; 4932 locks &= (byte)SceneObjectGroup.axisSelect.NOT_STATUS_ROTATE_Y;
4933 }
3556 4934
3557 if (setX || setY || setZ) 4935 if (setZ)
4936 {
4937 if(lockaxis)
4938 locks |= (byte)SceneObjectGroup.axisSelect.STATUS_ROTATE_Z;
4939 else
4940 locks &= (byte)SceneObjectGroup.axisSelect.NOT_STATUS_ROTATE_Z;
4941 }
4942
4943 RootPart.RotationAxisLocks = locks;
3558 RootPart.SetPhysicsAxisRotation(); 4944 RootPart.SetPhysicsAxisRotation();
4945 }
4946 }
4947
4948 public int GetAxisRotation(int axis)
4949 {
4950 byte rotAxislocks = RootPart.RotationAxisLocks;
4951
4952 // if multiple return the one with higher id
4953 if (axis == (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Z)
4954 return (rotAxislocks & (byte)SceneObjectGroup.axisSelect.STATUS_ROTATE_Z) == 0 ? 1:0;
4955 if (axis == (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Y)
4956 return (rotAxislocks & (byte)SceneObjectGroup.axisSelect.STATUS_ROTATE_Y) == 0 ? 1:0;
4957 if (axis == (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_X)
4958 return (rotAxislocks & (byte)SceneObjectGroup.axisSelect.STATUS_ROTATE_X) == 0 ? 1:0;
4959
4960 return 0;
3559 } 4961 }
3560 4962
3561 public int registerRotTargetWaypoint(Quaternion target, float tolerance) 4963 public int registerRotTargetWaypoint(Quaternion target, float tolerance)
@@ -3567,6 +4969,8 @@ namespace OpenSim.Region.Framework.Scenes
3567 waypoint.handle = handle; 4969 waypoint.handle = handle;
3568 lock (m_rotTargets) 4970 lock (m_rotTargets)
3569 { 4971 {
4972 if (m_rotTargets.Count >= 8)
4973 m_rotTargets.Remove(m_rotTargets.ElementAt(0).Key);
3570 m_rotTargets.Add(handle, waypoint); 4974 m_rotTargets.Add(handle, waypoint);
3571 } 4975 }
3572 m_scene.AddGroupTarget(this); 4976 m_scene.AddGroupTarget(this);
@@ -3592,12 +4996,14 @@ namespace OpenSim.Region.Framework.Scenes
3592 waypoint.handle = handle; 4996 waypoint.handle = handle;
3593 lock (m_targets) 4997 lock (m_targets)
3594 { 4998 {
4999 if (m_targets.Count >= 8)
5000 m_targets.Remove(m_targets.ElementAt(0).Key);
3595 m_targets.Add(handle, waypoint); 5001 m_targets.Add(handle, waypoint);
3596 } 5002 }
3597 m_scene.AddGroupTarget(this); 5003 m_scene.AddGroupTarget(this);
3598 return (int)handle; 5004 return (int)handle;
3599 } 5005 }
3600 5006
3601 public void unregisterTargetWaypoint(int handle) 5007 public void unregisterTargetWaypoint(int handle)
3602 { 5008 {
3603 lock (m_targets) 5009 lock (m_targets)
@@ -3625,10 +5031,11 @@ namespace OpenSim.Region.Framework.Scenes
3625 scriptPosTarget target = m_targets[idx]; 5031 scriptPosTarget target = m_targets[idx];
3626 if (Util.GetDistanceTo(target.targetPos, m_rootPart.GroupPosition) <= target.tolerance) 5032 if (Util.GetDistanceTo(target.targetPos, m_rootPart.GroupPosition) <= target.tolerance)
3627 { 5033 {
5034 at_target = true;
5035
3628 // trigger at_target 5036 // trigger at_target
3629 if (m_scriptListens_atTarget) 5037 if (m_scriptListens_atTarget)
3630 { 5038 {
3631 at_target = true;
3632 scriptPosTarget att = new scriptPosTarget(); 5039 scriptPosTarget att = new scriptPosTarget();
3633 att.targetPos = target.targetPos; 5040 att.targetPos = target.targetPos;
3634 att.tolerance = target.tolerance; 5041 att.tolerance = target.tolerance;
@@ -3638,14 +5045,14 @@ namespace OpenSim.Region.Framework.Scenes
3638 } 5045 }
3639 } 5046 }
3640 } 5047 }
3641 5048
3642 if (atTargets.Count > 0) 5049 if (atTargets.Count > 0)
3643 { 5050 {
3644 SceneObjectPart[] parts = m_parts.GetArray(); 5051 SceneObjectPart[] parts = m_parts.GetArray();
3645 uint[] localids = new uint[parts.Length]; 5052 uint[] localids = new uint[parts.Length];
3646 for (int i = 0; i < parts.Length; i++) 5053 for (int i = 0; i < parts.Length; i++)
3647 localids[i] = parts[i].LocalId; 5054 localids[i] = parts[i].LocalId;
3648 5055
3649 for (int ctr = 0; ctr < localids.Length; ctr++) 5056 for (int ctr = 0; ctr < localids.Length; ctr++)
3650 { 5057 {
3651 foreach (uint target in atTargets.Keys) 5058 foreach (uint target in atTargets.Keys)
@@ -3655,10 +5062,10 @@ namespace OpenSim.Region.Framework.Scenes
3655 localids[ctr], att.handle, att.targetPos, m_rootPart.GroupPosition); 5062 localids[ctr], att.handle, att.targetPos, m_rootPart.GroupPosition);
3656 } 5063 }
3657 } 5064 }
3658 5065
3659 return; 5066 return;
3660 } 5067 }
3661 5068
3662 if (m_scriptListens_notAtTarget && !at_target) 5069 if (m_scriptListens_notAtTarget && !at_target)
3663 { 5070 {
3664 //trigger not_at_target 5071 //trigger not_at_target
@@ -3666,7 +5073,7 @@ namespace OpenSim.Region.Framework.Scenes
3666 uint[] localids = new uint[parts.Length]; 5073 uint[] localids = new uint[parts.Length];
3667 for (int i = 0; i < parts.Length; i++) 5074 for (int i = 0; i < parts.Length; i++)
3668 localids[i] = parts[i].LocalId; 5075 localids[i] = parts[i].LocalId;
3669 5076
3670 for (int ctr = 0; ctr < localids.Length; ctr++) 5077 for (int ctr = 0; ctr < localids.Length; ctr++)
3671 { 5078 {
3672 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); 5079 m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]);
@@ -3746,11 +5153,35 @@ namespace OpenSim.Region.Framework.Scenes
3746 } 5153 }
3747 } 5154 }
3748 } 5155 }
3749 5156
5157 public Vector3 GetGeometricCenter()
5158 {
5159 // this is not real geometric center but a average of positions relative to root prim acording to
5160 // http://wiki.secondlife.com/wiki/llGetGeometricCenter
5161 // ignoring tortured prims details since sl also seems to ignore
5162 // so no real use in doing it on physics
5163
5164 Vector3 gc = Vector3.Zero;
5165
5166 SceneObjectPart[] parts = m_parts.GetArray();
5167 int nparts = parts.Length;
5168 if (nparts < 2)
5169 return gc;
5170
5171 // average all parts positions
5172 for (int i = 0; i < nparts; i++)
5173 {
5174 if (parts[i] != RootPart)
5175 gc += parts[i].OffsetPosition;
5176 }
5177 gc /= nparts;
5178
5179 return gc;
5180 }
5181
3750 public float GetMass() 5182 public float GetMass()
3751 { 5183 {
3752 float retmass = 0f; 5184 float retmass = 0f;
3753
3754 SceneObjectPart[] parts = m_parts.GetArray(); 5185 SceneObjectPart[] parts = m_parts.GetArray();
3755 for (int i = 0; i < parts.Length; i++) 5186 for (int i = 0; i < parts.Length; i++)
3756 retmass += parts[i].GetMass(); 5187 retmass += parts[i].GetMass();
@@ -3758,30 +5189,82 @@ namespace OpenSim.Region.Framework.Scenes
3758 return retmass; 5189 return retmass;
3759 } 5190 }
3760 5191
3761 /// <summary> 5192 // center of mass of full object
3762 /// If the object is a sculpt/mesh, retrieve the mesh data for each part and reinsert it into each shape so that 5193 public Vector3 GetCenterOfMass()
3763 /// the physics engine can use it.
3764 /// </summary>
3765 /// <remarks>
3766 /// When the physics engine has finished with it, the sculpt data is discarded to save memory.
3767 /// </remarks>
3768/*
3769 public void CheckSculptAndLoad()
3770 { 5194 {
3771 if (IsDeleted) 5195 PhysicsActor pa = RootPart.PhysActor;
3772 return;
3773 5196
3774 if ((RootPart.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) != 0) 5197 if(((RootPart.Flags & PrimFlags.Physics) !=0) && pa !=null)
3775 return; 5198 {
5199 // physics knows better about center of mass of physical prims
5200 Vector3 tmp = pa.CenterOfMass;
5201 return tmp;
5202 }
3776 5203
3777// m_log.Debug("Processing CheckSculptAndLoad for {0} {1}", Name, LocalId); 5204 Vector3 Ptot = Vector3.Zero;
5205 float totmass = 0f;
5206 float m;
3778 5207
3779 SceneObjectPart[] parts = m_parts.GetArray(); 5208 SceneObjectPart[] parts = m_parts.GetArray();
3780
3781 for (int i = 0; i < parts.Length; i++) 5209 for (int i = 0; i < parts.Length; i++)
3782 parts[i].CheckSculptAndLoad(); 5210 {
5211 m = parts[i].GetMass();
5212 Ptot += parts[i].GetPartCenterOfMass() * m;
5213 totmass += m;
5214 }
5215
5216 if (totmass == 0)
5217 totmass = 0;
5218 else
5219 totmass = 1 / totmass;
5220 Ptot *= totmass;
5221
5222 return Ptot;
3783 } 5223 }
3784*/ 5224
5225 public void GetInertiaData(out float TotalMass, out Vector3 CenterOfMass, out Vector3 Inertia, out Vector4 aux )
5226 {
5227 PhysicsActor pa = RootPart.PhysActor;
5228
5229 if(((RootPart.Flags & PrimFlags.Physics) !=0) && pa !=null)
5230 {
5231 PhysicsInertiaData inertia;
5232
5233 inertia = pa.GetInertiaData();
5234
5235 TotalMass = inertia.TotalMass;
5236 CenterOfMass = inertia.CenterOfMass;
5237 Inertia = inertia.Inertia;
5238 aux = inertia.InertiaRotation;
5239
5240 return;
5241 }
5242
5243 TotalMass = GetMass();
5244 CenterOfMass = GetCenterOfMass() - AbsolutePosition;
5245 CenterOfMass *= Quaternion.Conjugate(RootPart.RotationOffset);
5246 Inertia = Vector3.Zero;
5247 aux = Vector4.Zero;
5248 }
5249
5250 public void SetInertiaData(float TotalMass, Vector3 CenterOfMass, Vector3 Inertia, Vector4 aux )
5251 {
5252 PhysicsInertiaData inertia = new PhysicsInertiaData();
5253 inertia.TotalMass = TotalMass;
5254 inertia.CenterOfMass = CenterOfMass;
5255 inertia.Inertia = Inertia;
5256 inertia.InertiaRotation = aux;
5257
5258 if(TotalMass < 0)
5259 RootPart.PhysicsInertia = null;
5260 else
5261 RootPart.PhysicsInertia = new PhysicsInertiaData(inertia);
5262
5263 PhysicsActor pa = RootPart.PhysActor;
5264 if(pa !=null)
5265 pa.SetInertiaData(inertia);
5266 }
5267
3785 /// <summary> 5268 /// <summary>
3786 /// Set the user group to which this scene object belongs. 5269 /// Set the user group to which this scene object belongs.
3787 /// </summary> 5270 /// </summary>
@@ -3798,7 +5281,7 @@ namespace OpenSim.Region.Framework.Scenes
3798 } 5281 }
3799 5282
3800 HasGroupChanged = true; 5283 HasGroupChanged = true;
3801 5284
3802 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 5285 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
3803 // for the same object with very different properties. The caller must schedule the update. 5286 // for the same object with very different properties. The caller must schedule the update.
3804 //ScheduleGroupForFullUpdate(); 5287 //ScheduleGroupForFullUpdate();
@@ -3937,6 +5420,133 @@ namespace OpenSim.Region.Framework.Scenes
3937 FromItemID = uuid; 5420 FromItemID = uuid;
3938 } 5421 }
3939 5422
5423 public void ResetOwnerChangeFlag()
5424 {
5425 ForEachPart(delegate(SceneObjectPart part)
5426 {
5427 part.ResetOwnerChangeFlag();
5428 });
5429 InvalidateEffectivePerms();
5430 }
5431
5432 // clear some references to easy cg
5433 public void Clear()
5434 {
5435 m_parts.Clear();
5436 m_sittingAvatars.Clear();
5437// m_rootPart = null;
5438
5439 m_PlaySoundMasterPrim = null;
5440 m_PlaySoundSlavePrims.Clear();
5441 m_LoopSoundMasterPrim = null;
5442 m_targets.Clear();
5443 m_partsNameToLinkMap.Clear();
5444 }
5445
5446 private Dictionary<string,int> m_partsNameToLinkMap = new Dictionary<string, int>();
5447 private string GetLinkNumber_lastname;
5448 private int GetLinkNumber_lastnumber;
5449
5450 // this scales bad but so does GetLinkNumPart
5451 public int GetLinkNumber(string name)
5452 {
5453 if(String.IsNullOrEmpty(name) || name == "Object")
5454 return -1;
5455
5456 lock(m_partsNameToLinkMap)
5457 {
5458 if(m_partsNameToLinkMap.Count == 0)
5459 {
5460 GetLinkNumber_lastname = String.Empty;
5461 GetLinkNumber_lastnumber = -1;
5462 SceneObjectPart[] parts = m_parts.GetArray();
5463 for (int i = 0; i < parts.Length; i++)
5464 {
5465 string s = parts[i].Name;
5466 if(String.IsNullOrEmpty(s) || s == "Object" || s == "Primitive")
5467 continue;
5468
5469 if(m_partsNameToLinkMap.ContainsKey(s))
5470 {
5471 int ol = parts[i].LinkNum;
5472 if(ol < m_partsNameToLinkMap[s])
5473 m_partsNameToLinkMap[s] = ol;
5474 }
5475 else
5476 m_partsNameToLinkMap[s] = parts[i].LinkNum;
5477 }
5478 }
5479
5480 if(name == GetLinkNumber_lastname)
5481 return GetLinkNumber_lastnumber;
5482
5483 if(m_partsNameToLinkMap.ContainsKey(name))
5484 {
5485 lock(m_partsNameToLinkMap)
5486 {
5487 GetLinkNumber_lastname = name;
5488 GetLinkNumber_lastnumber = m_partsNameToLinkMap[name];
5489 return GetLinkNumber_lastnumber;
5490 }
5491 }
5492 }
5493
5494 if(m_sittingAvatars.Count > 0)
5495 {
5496 int j = m_parts.Count + 1;
5497
5498 ScenePresence[] avs = m_sittingAvatars.ToArray();
5499 for (int i = 0; i < avs.Length; i++, j++)
5500 {
5501 if (avs[i].Name == name)
5502 {
5503 GetLinkNumber_lastname = name;
5504 GetLinkNumber_lastnumber = j;
5505 return j;
5506 }
5507 }
5508 }
5509
5510 return -1;
5511 }
5512
5513 public void InvalidatePartsLinkMaps()
5514 {
5515 lock(m_partsNameToLinkMap)
5516 {
5517 m_partsNameToLinkMap.Clear();
5518 GetLinkNumber_lastname = String.Empty;
5519 GetLinkNumber_lastnumber = -1;
5520 }
5521 }
5522
5523 public bool CollisionSoundThrottled(int collisionSoundType)
5524 {
5525 double time = m_lastCollisionSoundMS;
5526// m_lastCollisionSoundMS = Util.GetTimeStampMS();
5527// time = m_lastCollisionSoundMS - time;
5528 double now = Util.GetTimeStampMS();
5529 time = now - time;
5530 switch (collisionSoundType)
5531 {
5532 case 0: // default sounds
5533 case 2: // default sounds with volume set by script
5534 if(time < 300.0)
5535 return true;
5536 break;
5537 case 1: // selected sound
5538 if(time < 200.0)
5539 return true;
5540 break;
5541 default:
5542 break;
5543 }
5544 m_lastCollisionSoundMS = now;
5545 return false;
5546 }
5547
3940 #endregion 5548 #endregion
3941 } 5549 }
5550
5551
3942} 5552}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index d1c5f72..2c183ad 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>
@@ -136,8 +148,8 @@ namespace OpenSim.Region.Framework.Scenes
136 /// <summary> 148 /// <summary>
137 /// Dynamic objects that can be created and deleted as required. 149 /// Dynamic objects that can be created and deleted as required.
138 /// </summary> 150 /// </summary>
139 public DOMap DynObjs 151 public DOMap DynObjs
140 { 152 {
141 get 153 get
142 { 154 {
143 if (m_dynObjs == null) 155 if (m_dynObjs == null)
@@ -151,16 +163,16 @@ namespace OpenSim.Region.Framework.Scenes
151 m_dynObjs = value; 163 m_dynObjs = value;
152 } 164 }
153 } 165 }
154 166
155 /// <value> 167 /// <value>
156 /// Is this a root part? 168 /// Is this a root part?
157 /// </value> 169 /// </value>
158 /// <remarks> 170 /// <remarks>
159 /// This will return true even if the whole object is attached to an avatar. 171 /// This will return true even if the whole object is attached to an avatar.
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>
@@ -173,19 +185,18 @@ namespace OpenSim.Region.Framework.Scenes
173 return 185 return
174 !(SitTargetPosition == Vector3.Zero 186 !(SitTargetPosition == Vector3.Zero
175 && (SitTargetOrientation == Quaternion.Identity // Valid Zero Rotation quaternion 187 && (SitTargetOrientation == Quaternion.Identity // Valid Zero Rotation quaternion
176 || SitTargetOrientation.X == 0f && SitTargetOrientation.Y == 0f && SitTargetOrientation.Z == 1f && SitTargetOrientation.W == 0f // W-Z Mapping was invalid at one point 188 || (SitTargetOrientation.W == 0f && SitTargetOrientation.X == 0f && SitTargetOrientation.Y == 0f && SitTargetOrientation.Z == 0f ))); // Invalid Quaternion
177 || SitTargetOrientation.X == 0f && SitTargetOrientation.Y == 0f && SitTargetOrientation.Z == 0f && SitTargetOrientation.W == 0f)); // Invalid Quaternion
178 } 189 }
179 } 190 }
180 191
181 #region Fields 192 #region Fields
182 193
183 public bool AllowedDrop; 194 public bool AllowedDrop;
184 195
185 public bool DIE_AT_EDGE; 196 public bool DIE_AT_EDGE;
186 197
187 public bool RETURN_AT_EDGE; 198 public bool RETURN_AT_EDGE;
188 199
189 public bool BlockGrab { get; set; } 200 public bool BlockGrab { get; set; }
190 201
191 public bool StatusSandbox; 202 public bool StatusSandbox;
@@ -210,7 +221,7 @@ namespace OpenSim.Region.Framework.Scenes
210 // Note: This isn't persisted in the database right now, as the fields for that aren't just there yet. 221 // Note: This isn't persisted in the database right now, as the fields for that aren't just there yet.
211 // Not a big problem as long as the script that sets it remains in the prim on startup. 222 // Not a big problem as long as the script that sets it remains in the prim on startup.
212 // for SL compatibility it should be persisted though (set sound / displaytext / particlesystem, kill script) 223 // for SL compatibility it should be persisted though (set sound / displaytext / particlesystem, kill script)
213 224
214 public UUID Sound; 225 public UUID Sound;
215 226
216 public byte SoundFlags; 227 public byte SoundFlags;
@@ -227,26 +238,26 @@ namespace OpenSim.Region.Framework.Scenes
227 /// </remarks> 238 /// </remarks>
228 public bool SoundQueueing { get; set; } 239 public bool SoundQueueing { get; set; }
229 240
230 public uint TimeStampFull; 241 [XmlIgnore]
231 242 public Quaternion AttachRotation = Quaternion.Identity;
232 public uint TimeStampLastActivity; // Will be used for AutoReturn
233
234 public uint TimeStampTerse;
235 243
236 public int STATUS_ROTATE_X; 244 [XmlIgnore]
245 public int STATUS_ROTATE_X; // this should not be used
237 246
238 public int STATUS_ROTATE_Y; 247 [XmlIgnore]
248 public int STATUS_ROTATE_Y; // this should not be used
239 249
240 public int STATUS_ROTATE_Z; 250 [XmlIgnore]
251 public int STATUS_ROTATE_Z; // this should not be used
241 252
242 private Dictionary<int, string> m_CollisionFilter = new Dictionary<int, string>(); 253 private Dictionary<int, string> m_CollisionFilter = new Dictionary<int, string>();
243 254
244 /// <value> 255 /// <value>
245 /// The UUID of the user inventory item from which this object was rezzed if this is a root part. 256 /// The UUID of the user inventory item from which this object was rezzed if this is a root part.
246 /// If UUID.Zero then either this is not a root part or there is no connection with a user inventory item. 257 /// If UUID.Zero then either this is not a root part or there is no connection with a user inventory item.
247 /// </value> 258 /// </value>
248 private UUID m_fromUserInventoryItemID; 259 private UUID m_fromUserInventoryItemID;
249 260
250 public UUID FromUserInventoryItemID 261 public UUID FromUserInventoryItemID
251 { 262 {
252 get { return m_fromUserInventoryItemID; } 263 get { return m_fromUserInventoryItemID; }
@@ -255,12 +266,34 @@ namespace OpenSim.Region.Framework.Scenes
255 266
256 public scriptEvents AggregateScriptEvents; 267 public scriptEvents AggregateScriptEvents;
257 268
258 public Vector3 AttachedPos; 269 public Vector3 AttachedPos
270 {
271 get;
272 set;
273 }
259 274
260 public Vector3 RotationAxis = Vector3.One; 275 // rotation locks on local X,Y and or Z axis bit flags
276 // bits are as in llSetStatus defined in SceneObjectGroup.axisSelect enum
277 // but reversed logic: bit cleared means free to rotate
278 public byte RotationAxisLocks = 0;
261 279
262 public bool VolumeDetectActive; // XmlIgnore set to avoid problems with persistance until I come to care for this 280 // WRONG flag in libOmvPrimFlags
263 // Certainly this must be a persistant setting finally 281 private const uint primFlagVolumeDetect = (uint)PrimFlags.JointLP2P;
282
283 public bool VolumeDetectActive
284 {
285 get
286 {
287 return (Flags & (PrimFlags)primFlagVolumeDetect) != 0;
288 }
289 set
290 {
291 if(value)
292 Flags |= (PrimFlags)primFlagVolumeDetect;
293 else
294 Flags &= (PrimFlags)(~primFlagVolumeDetect);
295 }
296 }
264 297
265 public bool IsWaitingForFirstSpinUpdatePacket; 298 public bool IsWaitingForFirstSpinUpdatePacket;
266 299
@@ -273,7 +306,7 @@ namespace OpenSim.Region.Framework.Scenes
273 306
274 /// <summary> 307 /// <summary>
275 /// This part's inventory 308 /// This part's inventory
276 /// </summary> 309 /// </summary>
277 public IEntityInventory Inventory 310 public IEntityInventory Inventory
278 { 311 {
279 get { return m_inventory; } 312 get { return m_inventory; }
@@ -281,29 +314,31 @@ namespace OpenSim.Region.Framework.Scenes
281 protected SceneObjectPartInventory m_inventory; 314 protected SceneObjectPartInventory m_inventory;
282 315
283 public bool Undoing; 316 public bool Undoing;
284 317
285 public bool IgnoreUndoUpdate = false; 318 public bool IgnoreUndoUpdate = false;
286 319
287 public PrimFlags LocalFlags; 320 public PrimFlags LocalFlags;
288 321
289 private float m_damage = -1.0f; 322 private float m_damage = -1.0f;
290 private byte[] m_TextureAnimation; 323 private byte[] m_TextureAnimation;
291 private byte m_clickAction; 324 private byte m_clickAction;
292 private Color m_color = Color.Black; 325 private Color m_color = Color.Black;
293 private readonly List<uint> m_lastColliders = new List<uint>(); 326 private List<uint> m_lastColliders = new List<uint>();
327 private bool m_lastLandCollide;
294 private int m_linkNum; 328 private int m_linkNum;
295 329
296 private int m_scriptAccessPin; 330 private int m_scriptAccessPin;
297 331
298 private readonly Dictionary<UUID, scriptEvents> m_scriptEvents = new Dictionary<UUID, scriptEvents>(); 332 private readonly Dictionary<UUID, scriptEvents> m_scriptEvents = new Dictionary<UUID, scriptEvents>();
299 private string m_sitName = String.Empty; 333 private string m_sitName = String.Empty;
300 private Quaternion m_sitTargetOrientation = Quaternion.Identity; 334 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
301 private Vector3 m_sitTargetPosition; 335 private Vector3 m_sitTargetPosition;
302 private string m_sitAnimation = "SIT"; 336 private string m_sitAnimation = "SIT";
337 private bool m_occupied; // KF if any av is sitting on this prim
303 private string m_text = String.Empty; 338 private string m_text = String.Empty;
304 private string m_touchName = String.Empty; 339 private string m_touchName = String.Empty;
305 private readonly List<UndoState> m_undo = new List<UndoState>(5); 340 private UndoRedoState m_UndoRedo = null;
306 private readonly List<UndoState> m_redo = new List<UndoState>(5); 341 private object m_UndoLock = new object();
307 342
308 private bool m_passTouches = false; 343 private bool m_passTouches = false;
309 private bool m_passCollisions = false; 344 private bool m_passCollisions = false;
@@ -329,16 +364,22 @@ namespace OpenSim.Region.Framework.Scenes
329 protected Vector3 m_lastPosition; 364 protected Vector3 m_lastPosition;
330 protected Quaternion m_lastRotation; 365 protected Quaternion m_lastRotation;
331 protected Vector3 m_lastVelocity; 366 protected Vector3 m_lastVelocity;
332 protected Vector3 m_lastAcceleration; 367 protected Vector3 m_lastAcceleration; // acceleration is a derived var with high noise
333 protected Vector3 m_lastAngularVelocity; 368 protected Vector3 m_lastAngularVelocity;
334 protected int m_lastTerseSent; 369 protected double m_lastUpdateSentTime;
370 protected float m_buoyancy = 0.0f;
371 protected Vector3 m_force;
372 protected Vector3 m_torque;
335 373
336 protected byte m_physicsShapeType = (byte)PhysShapeType.prim; 374 protected byte m_physicsShapeType = (byte)PhysShapeType.prim;
337 protected float m_density = 1000.0f; // in kg/m^3 375 protected float m_density = 1000.0f; // in kg/m^3
338 protected float m_gravitymod = 1.0f; 376 protected float m_gravitymod = 1.0f;
339 protected float m_friction = 0.6f; // wood 377 protected float m_friction = 0.6f; // wood
340 protected float m_bounce = 0.5f; // wood 378 protected float m_bounce = 0.5f; // wood
341 379
380
381 protected bool m_isSelected = false;
382
342 /// <summary> 383 /// <summary>
343 /// Stores media texture data 384 /// Stores media texture data
344 /// </summary> 385 /// </summary>
@@ -350,15 +391,24 @@ namespace OpenSim.Region.Framework.Scenes
350 private Vector3 m_cameraAtOffset; 391 private Vector3 m_cameraAtOffset;
351 private bool m_forceMouselook; 392 private bool m_forceMouselook;
352 393
353 // TODO: Collision sound should have default. 394
395 // 0 for default collision sounds, -1 for script disabled sound 1 for script defined sound
396 private sbyte m_collisionSoundType = 0;
354 private UUID m_collisionSound; 397 private UUID m_collisionSound;
355 private float m_collisionSoundVolume; 398 private float m_collisionSoundVolume;
356 399
400 private int LastColSoundSentTime;
401
402 private SOPVehicle m_vehicleParams = null;
403
404 private PhysicsInertiaData m_physicsInertia;
405
357 public KeyframeMotion KeyframeMotion 406 public KeyframeMotion KeyframeMotion
358 { 407 {
359 get; set; 408 get; set;
360 } 409 }
361 410
411
362 #endregion Fields 412 #endregion Fields
363 413
364// ~SceneObjectPart() 414// ~SceneObjectPart()
@@ -388,6 +438,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 438 // 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 439 // 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); 440 m_inventory = new SceneObjectPartInventory(this);
441 LastColSoundSentTime = Util.EnvironmentTickCount();
391 } 442 }
392 443
393 /// <summary> 444 /// <summary>
@@ -399,13 +450,13 @@ namespace OpenSim.Region.Framework.Scenes
399 /// <param name="rotationOffset"></param> 450 /// <param name="rotationOffset"></param>
400 /// <param name="offsetPosition"></param> 451 /// <param name="offsetPosition"></param>
401 public SceneObjectPart( 452 public SceneObjectPart(
402 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition, 453 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition,
403 Quaternion rotationOffset, Vector3 offsetPosition) : this() 454 Quaternion rotationOffset, Vector3 offsetPosition) : this()
404 { 455 {
405 m_name = "Primitive"; 456 m_name = "Object";
406 457
407 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed); 458 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed);
408 LastOwnerID = CreatorID = OwnerID = ownerID; 459 RezzerID = LastOwnerID = CreatorID = OwnerID = ownerID;
409 UUID = UUID.Random(); 460 UUID = UUID.Random();
410 Shape = shape; 461 Shape = shape;
411 OwnershipCost = 0; 462 OwnershipCost = 0;
@@ -418,16 +469,18 @@ namespace OpenSim.Region.Framework.Scenes
418 Velocity = Vector3.Zero; 469 Velocity = Vector3.Zero;
419 AngularVelocity = Vector3.Zero; 470 AngularVelocity = Vector3.Zero;
420 Acceleration = Vector3.Zero; 471 Acceleration = Vector3.Zero;
472 APIDActive = false;
421 Flags = 0; 473 Flags = 0;
422 CreateSelected = true; 474 CreateSelected = true;
423
424 TrimPermissions(); 475 TrimPermissions();
476 AggregateInnerPerms();
425 } 477 }
426 478
427 #endregion Constructors 479 #endregion Constructors
428 480
429 #region XML Schema 481 #region XML Schema
430 482
483 private UUID _rezzerID;
431 private UUID _lastOwnerID; 484 private UUID _lastOwnerID;
432 private UUID _ownerID; 485 private UUID _ownerID;
433 private UUID _groupID; 486 private UUID _groupID;
@@ -441,14 +494,14 @@ namespace OpenSim.Region.Framework.Scenes
441 private uint _ownerMask = (uint)(PermissionMask.All | PermissionMask.Export); 494 private uint _ownerMask = (uint)(PermissionMask.All | PermissionMask.Export);
442 private uint _groupMask = (uint)PermissionMask.None; 495 private uint _groupMask = (uint)PermissionMask.None;
443 private uint _everyoneMask = (uint)PermissionMask.None; 496 private uint _everyoneMask = (uint)PermissionMask.None;
444 private uint _nextOwnerMask = (uint)PermissionMask.All; 497 private uint _nextOwnerMask = (uint)(PermissionMask.Move | PermissionMask.Transfer);
445 private PrimFlags _flags = PrimFlags.None; 498 private PrimFlags _flags = PrimFlags.None;
446 private DateTime m_expires; 499 private DateTime m_expires;
447 private DateTime m_rezzed; 500 private DateTime m_rezzed;
448 private bool m_createSelected = false; 501 private bool m_createSelected = false;
449 502
450 private UUID _creatorID; 503 private UUID _creatorID;
451 public UUID CreatorID 504 public UUID CreatorID
452 { 505 {
453 get { return _creatorID; } 506 get { return _creatorID; }
454 set { _creatorID = value; } 507 set { _creatorID = value; }
@@ -458,7 +511,7 @@ namespace OpenSim.Region.Framework.Scenes
458 /// <summary> 511 /// <summary>
459 /// Data about the creator in the form home_url;name 512 /// Data about the creator in the form home_url;name
460 /// </summary> 513 /// </summary>
461 public string CreatorData 514 public string CreatorData
462 { 515 {
463 get { return m_creatorData; } 516 get { return m_creatorData; }
464 set { m_creatorData = value; } 517 set { m_creatorData = value; }
@@ -480,45 +533,35 @@ namespace OpenSim.Region.Framework.Scenes
480 } 533 }
481 set 534 set
482 { 535 {
536 CreatorData = string.Empty;
483 if ((value == null) || (value != null && value == string.Empty)) 537 if ((value == null) || (value != null && value == string.Empty))
484 {
485 CreatorData = string.Empty;
486 return; 538 return;
487 }
488 539
489 if (!value.Contains(";")) // plain UUID 540 // value is uuid or uuid;homeuri;firstname lastname
541 string[] parts = value.Split(';');
542 if (parts.Length > 0)
490 { 543 {
544
491 UUID uuid = UUID.Zero; 545 UUID uuid = UUID.Zero;
492 UUID.TryParse(value, out uuid); 546 UUID.TryParse(parts[0], out uuid);
493 CreatorID = uuid; 547 CreatorID = uuid;
494 } 548
495 else // <uuid>[;<endpoint>[;name]] 549 if (parts.Length > 1)
496 {
497 string name = "Unknown User";
498 string[] parts = value.Split(';');
499 if (parts.Length >= 1)
500 {
501 UUID uuid = UUID.Zero;
502 UUID.TryParse(parts[0], out uuid);
503 CreatorID = uuid;
504 }
505 if (parts.Length >= 2)
506 { 550 {
507 CreatorData = parts[1]; 551 CreatorData = parts[1];
508 if (!CreatorData.EndsWith("/")) 552 if (!CreatorData.EndsWith("/"))
509 CreatorData += "/"; 553 CreatorData += "/";
554 if (parts.Length > 2)
555 CreatorData += ';' + parts[2];
556 else
557 CreatorData += ";Unknown User";
510 } 558 }
511 if (parts.Length >= 3)
512 name = parts[2];
513
514 CreatorData += ';' + name;
515
516 } 559 }
517 } 560 }
518 } 561 }
519 562
520 /// <summary> 563 /// <summary>
521 /// A relic from when we we thought that prims contained folder objects. In 564 /// A relic from when we we thought that prims contained folder objects. In
522 /// reality, prim == folder 565 /// reality, prim == folder
523 /// Exposing this is not particularly good, but it's one of the least evils at the moment to see 566 /// Exposing this is not particularly good, but it's one of the least evils at the moment to see
524 /// folder id from prim inventory item data, since it's not (yet) actually stored with the prim. 567 /// folder id from prim inventory item data, since it's not (yet) actually stored with the prim.
@@ -539,12 +582,16 @@ namespace OpenSim.Region.Framework.Scenes
539 } 582 }
540 583
541 /// <value> 584 /// <value>
542 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 585 /// Get the inventory list
543 /// </value> 586 /// </value>
544 public TaskInventoryDictionary TaskInventory 587 public TaskInventoryDictionary TaskInventory
545 { 588 {
546 get { return m_inventory.Items; } 589 get {
547 set { m_inventory.Items = value; } 590 return m_inventory.Items;
591 }
592 set {
593 m_inventory.Items = value;
594 }
548 } 595 }
549 596
550 /// <summary> 597 /// <summary>
@@ -560,10 +607,10 @@ namespace OpenSim.Region.Framework.Scenes
560 public UUID UUID 607 public UUID UUID
561 { 608 {
562 get { return m_uuid; } 609 get { return m_uuid; }
563 set 610 set
564 { 611 {
565 m_uuid = value; 612 m_uuid = value;
566 613
567 // This is necessary so that TaskInventoryItem parent ids correctly reference the new uuid of this part 614 // This is necessary so that TaskInventoryItem parent ids correctly reference the new uuid of this part
568 if (Inventory != null) 615 if (Inventory != null)
569 Inventory.ResetObjectID(); 616 Inventory.ResetObjectID();
@@ -583,28 +630,16 @@ namespace OpenSim.Region.Framework.Scenes
583 public virtual string Name 630 public virtual string Name
584 { 631 {
585 get { return m_name; } 632 get { return m_name; }
586 set
587 {
588 m_name = value;
589
590 PhysicsActor pa = PhysActor;
591
592 if (pa != null)
593 pa.SOPName = value;
594 }
595 }
596
597 public byte Material
598 {
599 get { return (byte) m_material; }
600 set 633 set
601 { 634 {
602 m_material = (Material)value; 635 m_name = value;
636 if(ParentGroup != null)
637 ParentGroup.InvalidatePartsLinkMaps();
603 638
604 PhysicsActor pa = PhysActor; 639 PhysicsActor pa = PhysActor;
605 640
606 if (pa != null) 641 if (pa != null)
607 pa.SetMaterial((int)value); 642 pa.SOPName = value;
608 } 643 }
609 } 644 }
610 645
@@ -633,6 +668,19 @@ namespace OpenSim.Region.Framework.Scenes
633 } 668 }
634 } 669 }
635 670
671 public bool IsSelected
672 {
673 get { return m_isSelected; }
674 set
675 {
676 m_isSelected = value;
677 if (ParentGroup != null)
678 ParentGroup.PartSelectChanged(value);
679
680 }
681 }
682
683
636 public Dictionary<int, string> CollisionFilter 684 public Dictionary<int, string> CollisionFilter
637 { 685 {
638 get { return m_CollisionFilter; } 686 get { return m_CollisionFilter; }
@@ -654,14 +702,14 @@ namespace OpenSim.Region.Framework.Scenes
654 set { m_APIDTarget = value; } 702 set { m_APIDTarget = value; }
655 } 703 }
656 704
657 705
658 protected float APIDDamp 706 protected float APIDDamp
659 { 707 {
660 get { return m_APIDDamp; } 708 get { return m_APIDDamp; }
661 set { m_APIDDamp = value; } 709 set { m_APIDDamp = value; }
662 } 710 }
663 711
664 712
665 protected float APIDStrength 713 protected float APIDStrength
666 { 714 {
667 get { return m_APIDStrength; } 715 get { return m_APIDStrength; }
@@ -707,53 +755,61 @@ namespace OpenSim.Region.Framework.Scenes
707 set { m_LoopSoundSlavePrims = value; } 755 set { m_LoopSoundSlavePrims = value; }
708 } 756 }
709 757
710
711 public Byte[] TextureAnimation 758 public Byte[] TextureAnimation
712 { 759 {
713 get { return m_TextureAnimation; } 760 get { return m_TextureAnimation; }
714 set { m_TextureAnimation = value; } 761 set { m_TextureAnimation = value; }
715 } 762 }
716 763
717
718 public Byte[] ParticleSystem 764 public Byte[] ParticleSystem
719 { 765 {
720 get { return m_particleSystem; } 766 get { return m_particleSystem; }
721 set { m_particleSystem = value; } 767 set { m_particleSystem = value; }
722 } 768 }
723 769
724 770
725 public DateTime Expires 771 public DateTime Expires
726 { 772 {
727 get { return m_expires; } 773 get { return m_expires; }
728 set { m_expires = value; } 774 set { m_expires = value; }
729 } 775 }
730 776
731 777
732 public DateTime Rezzed 778 public DateTime Rezzed
733 { 779 {
734 get { return m_rezzed; } 780 get { return m_rezzed; }
735 set { m_rezzed = value; } 781 set { m_rezzed = value; }
736 } 782 }
737 783
738 784
739 public float Damage 785 public float Damage
740 { 786 {
741 get { return m_damage; } 787 get { return m_damage; }
742 set { m_damage = value; } 788 set { m_damage = value; }
743 } 789 }
744 790
791 public void setGroupPosition(Vector3 pos)
792 {
793 m_groupPosition = pos;
794 }
795
745 /// <summary> 796 /// <summary>
746 /// The position of the entire group that this prim belongs to. 797 /// The position of the entire group that this prim belongs to.
747 /// </summary> 798 /// </summary>
799 ///
800
748 public Vector3 GroupPosition 801 public Vector3 GroupPosition
749 { 802 {
750 get 803 get
751 { 804 {
752 // If this is a linkset, we don't want the physics engine mucking up our group position here. 805 // If this is a linkset, we don't want the physics engine mucking up our group position here.
753 PhysicsActor actor = PhysActor; 806 PhysicsActor actor = PhysActor;
754 // If physical and the root prim of a linkset, the position of the group is what physics thinks. 807 if (_parentID == 0)
755 if (actor != null && ParentID == 0) 808 {
756 m_groupPosition = actor.Position; 809 if (actor != null)
810 m_groupPosition = actor.Position;
811 return m_groupPosition;
812 }
757 813
758 // If I'm an attachment, my position is reported as the position of who I'm attached to 814 // If I'm an attachment, my position is reported as the position of who I'm attached to
759 if (ParentGroup.IsAttachment) 815 if (ParentGroup.IsAttachment)
@@ -763,19 +819,21 @@ namespace OpenSim.Region.Framework.Scenes
763 return sp.AbsolutePosition; 819 return sp.AbsolutePosition;
764 } 820 }
765 821
822 // use root prim's group position. Physics may have updated it
823 if (ParentGroup.RootPart != this)
824 m_groupPosition = ParentGroup.RootPart.GroupPosition;
766 return m_groupPosition; 825 return m_groupPosition;
767 } 826 }
768 set 827 set
769 { 828 {
770 m_groupPosition = value; 829 m_groupPosition = value;
771
772 PhysicsActor actor = PhysActor; 830 PhysicsActor actor = PhysActor;
773 if (actor != null) 831 if (actor != null && ParentGroup.Scene.PhysicsScene != null)
774 { 832 {
775 try 833 try
776 { 834 {
777 // Root prim actually goes at Position 835 // Root prim actually goes at Position
778 if (ParentID == 0) 836 if (_parentID == 0)
779 { 837 {
780 actor.Position = value; 838 actor.Position = value;
781 } 839 }
@@ -798,27 +856,51 @@ namespace OpenSim.Region.Framework.Scenes
798 } 856 }
799 } 857 }
800 858
859 public void setOffsetPosition(Vector3 pos)
860 {
861 m_offsetPosition = pos;
862 }
863
801 public Vector3 OffsetPosition 864 public Vector3 OffsetPosition
802 { 865 {
803 get { return m_offsetPosition; } 866 get { return m_offsetPosition; }
804 set 867 set
805 { 868 {
806// StoreUndoState(); 869 Vector3 oldpos = m_offsetPosition;
807 m_offsetPosition = value; 870 m_offsetPosition = value;
808 871
809 if (ParentGroup != null && !ParentGroup.IsDeleted) 872 if (ParentGroup != null && !ParentGroup.IsDeleted)
810 { 873 {
874 if((oldpos - m_offsetPosition).LengthSquared() > 1.0f)
875 ParentGroup.InvalidBoundsRadius();
876
811 PhysicsActor actor = PhysActor; 877 PhysicsActor actor = PhysActor;
812 if (ParentID != 0 && actor != null) 878 if (_parentID != 0 && actor != null)
813 { 879 {
814 actor.Position = GetWorldPosition(); 880 actor.Position = GetWorldPosition();
815 actor.Orientation = GetWorldRotation(); 881 actor.Orientation = GetWorldRotation();
816 882
817 // Tell the physics engines that this prim changed. 883 // Tell the physics engines that this prim changed.
818 if (ParentGroup.Scene != null) 884 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null)
819 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 885 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
820 } 886 }
887
888 if (!m_parentGroup.m_dupeInProgress)
889 {
890 List<ScenePresence> avs = ParentGroup.GetSittingAvatars();
891 foreach (ScenePresence av in avs)
892 {
893 if (av.ParentID == m_localId)
894 {
895 Vector3 offset = (m_offsetPosition - oldpos);
896 av.AbsolutePosition += offset;
897// av.SendAvatarDataToAllAgents();
898 av.SendTerseUpdateToAllClients();
899 }
900 }
901 }
821 } 902 }
903 TriggerScriptChangedEvent(Changed.POSITION);
822 } 904 }
823 } 905 }
824 906
@@ -840,6 +922,11 @@ namespace OpenSim.Region.Framework.Scenes
840 } 922 }
841 } 923 }
842 924
925 public void setRotationOffset(Quaternion q)
926 {
927 m_rotationOffset = q;
928 }
929
843 public Quaternion RotationOffset 930 public Quaternion RotationOffset
844 { 931 {
845 get 932 get
@@ -848,28 +935,15 @@ namespace OpenSim.Region.Framework.Scenes
848 PhysicsActor actor = PhysActor; 935 PhysicsActor actor = PhysActor;
849 // If this is a root of a linkset, the real rotation is what the physics engine thinks. 936 // If this is a root of a linkset, the real rotation is what the physics engine thinks.
850 // If not a root prim, the offset rotation is computed by SOG and is relative to the root. 937 // If not a root prim, the offset rotation is computed by SOG and is relative to the root.
851 if (ParentID == 0 && (Shape.PCode != 9 || Shape.State == 0) && actor != null) 938 if (_parentID == 0 && (Shape.PCode != 9 || Shape.State == 0) && actor != null)
852 { 939 m_rotationOffset = actor.Orientation;
853 if (actor.Orientation.X != 0f || actor.Orientation.Y != 0f
854 || actor.Orientation.Z != 0f || actor.Orientation.W != 0f)
855 {
856 m_rotationOffset = actor.Orientation;
857 }
858 }
859
860// float roll, pitch, yaw = 0;
861// m_rotationOffset.GetEulerAngles(out roll, out pitch, out yaw);
862//
863// m_log.DebugFormat(
864// "[SCENE OBJECT PART]: Got euler {0} for RotationOffset on {1} {2}",
865// new Vector3(roll, pitch, yaw), Name, LocalId);
866 940
867 return m_rotationOffset; 941 return m_rotationOffset;
868 } 942 }
869 943
870 set 944 set
871 { 945 {
872 StoreUndoState(); 946// StoreUndoState();
873 m_rotationOffset = value; 947 m_rotationOffset = value;
874 948
875 PhysicsActor actor = PhysActor; 949 PhysicsActor actor = PhysActor;
@@ -878,7 +952,7 @@ namespace OpenSim.Region.Framework.Scenes
878 try 952 try
879 { 953 {
880 // Root prim gets value directly 954 // Root prim gets value directly
881 if (ParentID == 0) 955 if (_parentID == 0)
882 { 956 {
883 actor.Orientation = value; 957 actor.Orientation = value;
884 //m_log.Info("[PART]: RO1:" + actor.Orientation.ToString()); 958 //m_log.Info("[PART]: RO1:" + actor.Orientation.ToString());
@@ -960,7 +1034,7 @@ namespace OpenSim.Region.Framework.Scenes
960 get 1034 get
961 { 1035 {
962 PhysicsActor actor = PhysActor; 1036 PhysicsActor actor = PhysActor;
963 if ((actor != null) && actor.IsPhysical) 1037 if ((actor != null) && actor.IsPhysical && ParentGroup.RootPart == this)
964 { 1038 {
965 m_angularVelocity = actor.RotationalVelocity; 1039 m_angularVelocity = actor.RotationalVelocity;
966 } 1040 }
@@ -974,21 +1048,38 @@ namespace OpenSim.Region.Framework.Scenes
974 m_angularVelocity = value; 1048 m_angularVelocity = value;
975 1049
976 PhysicsActor actor = PhysActor; 1050 PhysicsActor actor = PhysActor;
977 if ((actor != null) && actor.IsPhysical) 1051 if ((actor != null) && actor.IsPhysical && ParentGroup.RootPart == this)
1052 {
978 actor.RotationalVelocity = m_angularVelocity; 1053 actor.RotationalVelocity = m_angularVelocity;
1054 }
979 } 1055 }
980 } 1056 }
981 1057
982 /// <summary></summary> 1058 /// <summary></summary>
983 public Vector3 Acceleration 1059 public Vector3 Acceleration
984 { 1060 {
985 get { return m_acceleration; } 1061 get
986 set 1062 {
1063 PhysicsActor actor = PhysActor;
1064 if (actor != null)
1065 {
1066 m_acceleration = actor.Acceleration;
1067 }
1068 return m_acceleration;
1069 }
1070
1071 set
987 { 1072 {
988 if (Util.IsNanOrInfinity(value)) 1073 if (Util.IsNanOrInfinity(value))
989 m_acceleration = Vector3.Zero; 1074 m_acceleration = Vector3.Zero;
990 else 1075 else
991 m_acceleration = value; 1076 m_acceleration = value;
1077
1078 PhysicsActor actor = PhysActor;
1079 if ((actor != null) && actor.IsPhysical && ParentGroup.RootPart == this)
1080 {
1081 actor.Acceleration = m_acceleration;
1082 }
992 } 1083 }
993 } 1084 }
994 1085
@@ -1007,8 +1098,8 @@ namespace OpenSim.Region.Framework.Scenes
1007 { 1098 {
1008 get 1099 get
1009 { 1100 {
1010 if (m_text.Length > 255) 1101 if (m_text.Length > 256) // yes > 254
1011 return m_text.Substring(0, 254); 1102 return m_text.Substring(0, 256);
1012 return m_text; 1103 return m_text;
1013 } 1104 }
1014 set { m_text = value; } 1105 set { m_text = value; }
@@ -1056,7 +1147,10 @@ namespace OpenSim.Region.Framework.Scenes
1056 public PrimitiveBaseShape Shape 1147 public PrimitiveBaseShape Shape
1057 { 1148 {
1058 get { return m_shape; } 1149 get { return m_shape; }
1059 set { m_shape = value;} 1150 set
1151 {
1152 m_shape = value;
1153 }
1060 } 1154 }
1061 1155
1062 /// <summary> 1156 /// <summary>
@@ -1069,10 +1163,10 @@ namespace OpenSim.Region.Framework.Scenes
1069 { 1163 {
1070 if (m_shape != null) 1164 if (m_shape != null)
1071 { 1165 {
1072 StoreUndoState(); 1166 Vector3 oldscale = m_shape.Scale;
1073
1074 m_shape.Scale = value; 1167 m_shape.Scale = value;
1075 1168 if (ParentGroup != null && ((value - oldscale).LengthSquared() >1.0f))
1169 ParentGroup.InvalidBoundsRadius();
1076 PhysicsActor actor = PhysActor; 1170 PhysicsActor actor = PhysActor;
1077 if (actor != null) 1171 if (actor != null)
1078 { 1172 {
@@ -1081,11 +1175,7 @@ namespace OpenSim.Region.Framework.Scenes
1081 if (ParentGroup.Scene.PhysicsScene != null) 1175 if (ParentGroup.Scene.PhysicsScene != null)
1082 { 1176 {
1083 actor.Size = m_shape.Scale; 1177 actor.Size = m_shape.Scale;
1084 1178 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
1085// if (Shape.SculptEntry)
1086// CheckSculptAndLoad();
1087// else
1088 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
1089 } 1179 }
1090 } 1180 }
1091 } 1181 }
@@ -1095,20 +1185,47 @@ namespace OpenSim.Region.Framework.Scenes
1095 } 1185 }
1096 } 1186 }
1097 1187
1188 public float maxSimpleArea()
1189 {
1190 float a,b;
1191 float sx = m_shape.Scale.X;
1192 float sy = m_shape.Scale.Y;
1193 float sz = m_shape.Scale.Z;
1194
1195 if( sx > sy)
1196 {
1197 a = sx;
1198 if(sy > sz)
1199 b = sy;
1200 else
1201 b = sz;
1202 }
1203 else
1204 {
1205 a = sy;
1206 if(sx > sz)
1207 b = sx;
1208 else
1209 b = sz;
1210 }
1211
1212 return a * b;
1213 }
1214
1098 public UpdateRequired UpdateFlag { get; set; } 1215 public UpdateRequired UpdateFlag { get; set; }
1099 public bool UpdatePhysRequired { get; set; } 1216 private object UpdateFlagLock = new object();
1100 1217
1101 /// <summary> 1218 /// <summary>
1102 /// Used for media on a prim. 1219 /// Used for media on a prim.
1103 /// </summary> 1220 /// </summary>
1104 /// Do not change this value directly - always do it through an IMoapModule. 1221 /// Do not change this value directly - always do it through an IMoapModule.
1105 public string MediaUrl 1222 public string MediaUrl
1106 { 1223 {
1107 get 1224 get
1108 { 1225 {
1109 return m_mediaUrl; 1226 return m_mediaUrl;
1110 } 1227 }
1111 1228
1112 set 1229 set
1113 { 1230 {
1114 m_mediaUrl = value; 1231 m_mediaUrl = value;
@@ -1121,10 +1238,10 @@ namespace OpenSim.Region.Framework.Scenes
1121 public bool CreateSelected 1238 public bool CreateSelected
1122 { 1239 {
1123 get { return m_createSelected; } 1240 get { return m_createSelected; }
1124 set 1241 set
1125 { 1242 {
1126// m_log.DebugFormat("[SOP]: Setting CreateSelected to {0} for {1} {2}", value, Name, UUID); 1243// m_log.DebugFormat("[SOP]: Setting CreateSelected to {0} for {1} {2}", value, Name, UUID);
1127 m_createSelected = value; 1244 m_createSelected = value;
1128 } 1245 }
1129 } 1246 }
1130 1247
@@ -1137,10 +1254,10 @@ namespace OpenSim.Region.Framework.Scenes
1137 { 1254 {
1138 get 1255 get
1139 { 1256 {
1140 if (ParentGroup.IsAttachment) 1257 if (_parentID == 0)
1141 return GroupPosition; 1258 return GroupPosition;
1142 1259
1143 return m_offsetPosition + m_groupPosition; 1260 return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset);
1144 } 1261 }
1145 } 1262 }
1146 1263
@@ -1261,7 +1378,14 @@ namespace OpenSim.Region.Framework.Scenes
1261 public UUID LastOwnerID 1378 public UUID LastOwnerID
1262 { 1379 {
1263 get { return _lastOwnerID; } 1380 get { return _lastOwnerID; }
1264 set { _lastOwnerID = value; } 1381 set {
1382 _lastOwnerID = value; }
1383 }
1384
1385 public UUID RezzerID
1386 {
1387 get { return _rezzerID; }
1388 set { _rezzerID = value; }
1265 } 1389 }
1266 1390
1267 public uint BaseMask 1391 public uint BaseMask
@@ -1295,7 +1419,7 @@ namespace OpenSim.Region.Framework.Scenes
1295 } 1419 }
1296 1420
1297 /// <summary> 1421 /// <summary>
1298 /// Property flags. See OpenMetaverse.PrimFlags 1422 /// Property flags. See OpenMetaverse.PrimFlags
1299 /// </summary> 1423 /// </summary>
1300 /// <remarks> 1424 /// <remarks>
1301 /// Example properties are PrimFlags.Phantom and PrimFlags.DieAtEdge 1425 /// Example properties are PrimFlags.Phantom and PrimFlags.DieAtEdge
@@ -1303,13 +1427,20 @@ namespace OpenSim.Region.Framework.Scenes
1303 public PrimFlags Flags 1427 public PrimFlags Flags
1304 { 1428 {
1305 get { return _flags; } 1429 get { return _flags; }
1306 set 1430 set
1307 { 1431 {
1308// m_log.DebugFormat("[SOP]: Setting flags for {0} {1} to {2}", UUID, Name, value); 1432// m_log.DebugFormat("[SOP]: Setting flags for {0} {1} to {2}", UUID, Name, value);
1309 _flags = value; 1433 _flags = value;
1310 } 1434 }
1311 } 1435 }
1312 1436
1437 [XmlIgnore]
1438 public bool IsOccupied // KF If an av is sittingon this prim
1439 {
1440 get { return m_occupied; }
1441 set { m_occupied = value; }
1442 }
1443
1313 /// <summary> 1444 /// <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 1445 /// 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
1315 /// </summary> 1446 /// </summary>
@@ -1339,7 +1470,7 @@ namespace OpenSim.Region.Framework.Scenes
1339 } 1470 }
1340 1471
1341 private UUID _parentUUID = UUID.Zero; 1472 private UUID _parentUUID = UUID.Zero;
1342 1473
1343 public UUID ParentUUID 1474 public UUID ParentUUID
1344 { 1475 {
1345 get 1476 get
@@ -1352,20 +1483,48 @@ namespace OpenSim.Region.Framework.Scenes
1352 1483
1353 set { _parentUUID = value; } 1484 set { _parentUUID = value; }
1354 } 1485 }
1355 1486
1356 public string SitAnimation 1487 public string SitAnimation
1357 { 1488 {
1358 get { return m_sitAnimation; } 1489 get { return m_sitAnimation; }
1359 set { m_sitAnimation = value; } 1490 set { m_sitAnimation = value; }
1360 } 1491 }
1361 1492
1493 public UUID invalidCollisionSoundUUID = new UUID("ffffffff-ffff-ffff-ffff-ffffffffffff");
1494
1495 // 0 for default collision sounds, -1 for script disabled sound 1 for script defined sound
1496 // runtime thing.. do not persist
1497 [XmlIgnore]
1498 public sbyte CollisionSoundType
1499 {
1500 get
1501 {
1502 return m_collisionSoundType;
1503 }
1504 set
1505 {
1506 m_collisionSoundType = value;
1507 if (value == -1)
1508 m_collisionSound = invalidCollisionSoundUUID;
1509 else if (value == 0)
1510 m_collisionSound = UUID.Zero;
1511 }
1512 }
1513
1362 public UUID CollisionSound 1514 public UUID CollisionSound
1363 { 1515 {
1364 get { return m_collisionSound; } 1516 get { return m_collisionSound; }
1365 set 1517 set
1366 { 1518 {
1367 m_collisionSound = value; 1519 m_collisionSound = value;
1368 aggregateScriptEvents(); 1520
1521 if (value == invalidCollisionSoundUUID)
1522 m_collisionSoundType = -1;
1523 else if (value == UUID.Zero)
1524 m_collisionSoundType = 0;
1525 else
1526 m_collisionSoundType = 1;
1527
1369 } 1528 }
1370 } 1529 }
1371 1530
@@ -1375,6 +1534,126 @@ namespace OpenSim.Region.Framework.Scenes
1375 set { m_collisionSoundVolume = value; } 1534 set { m_collisionSoundVolume = value; }
1376 } 1535 }
1377 1536
1537 public float Buoyancy
1538 {
1539 get
1540 {
1541 if (ParentGroup.RootPart == this)
1542 return m_buoyancy;
1543
1544 return ParentGroup.RootPart.Buoyancy;
1545 }
1546 set
1547 {
1548 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1549 {
1550 ParentGroup.RootPart.Buoyancy = value;
1551 return;
1552 }
1553 m_buoyancy = value;
1554 if (PhysActor != null)
1555 PhysActor.Buoyancy = value;
1556 }
1557 }
1558
1559 public Vector3 Force
1560 {
1561 get
1562 {
1563 if (ParentGroup.RootPart == this)
1564 return m_force;
1565
1566 return ParentGroup.RootPart.Force;
1567 }
1568
1569 set
1570 {
1571 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1572 {
1573 ParentGroup.RootPart.Force = value;
1574 return;
1575 }
1576 m_force = value;
1577 if (PhysActor != null)
1578 PhysActor.Force = value;
1579 }
1580 }
1581
1582 public Vector3 Torque
1583 {
1584 get
1585 {
1586 if (ParentGroup.RootPart == this)
1587 return m_torque;
1588
1589 return ParentGroup.RootPart.Torque;
1590 }
1591
1592 set
1593 {
1594 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1595 {
1596 ParentGroup.RootPart.Torque = value;
1597 return;
1598 }
1599 m_torque = value;
1600 if (PhysActor != null)
1601 PhysActor.Torque = value;
1602 }
1603 }
1604
1605 public byte Material
1606 {
1607 get { return (byte)m_material; }
1608 set
1609 {
1610 if (value >= 0 && value <= (byte)SOPMaterialData.MaxMaterial)
1611 {
1612 bool update = false;
1613
1614 if (m_material != (Material)value)
1615 {
1616 update = true;
1617 m_material = (Material)value;
1618 }
1619
1620 if (m_friction != SOPMaterialData.friction(m_material))
1621 {
1622 update = true;
1623 m_friction = SOPMaterialData.friction(m_material);
1624 }
1625
1626 if (m_bounce != SOPMaterialData.bounce(m_material))
1627 {
1628 update = true;
1629 m_bounce = SOPMaterialData.bounce(m_material);
1630 }
1631
1632 if (update)
1633 {
1634 if (PhysActor != null)
1635 {
1636 PhysActor.SetMaterial((int)value);
1637 }
1638 if(ParentGroup != null)
1639 {
1640 ParentGroup.HasGroupChanged = true;
1641 ScheduleFullUpdate();
1642 }
1643 }
1644 }
1645 }
1646 }
1647
1648 // not a propriety to move to methods place later
1649 private bool HasMesh()
1650 {
1651 if (Shape != null && (Shape.SculptType == (byte)SculptType.Mesh))
1652 return true;
1653 return false;
1654 }
1655
1656 // not a propriety to move to methods place later
1378 public byte DefaultPhysicsShapeType() 1657 public byte DefaultPhysicsShapeType()
1379 { 1658 {
1380 byte type; 1659 byte type;
@@ -1387,9 +1666,73 @@ namespace OpenSim.Region.Framework.Scenes
1387 return type; 1666 return type;
1388 } 1667 }
1389 1668
1669 [XmlIgnore]
1670 public bool UsesComplexCost
1671 {
1672 get
1673 {
1674 byte pst = PhysicsShapeType;
1675 if(pst == (byte) PhysShapeType.none || HasMesh())
1676 return true;
1677 return false;
1678 }
1679 }
1680
1681 [XmlIgnore]
1682 public float PhysicsCost
1683 {
1684 get
1685 {
1686 if(PhysicsShapeType == (byte)PhysShapeType.none)
1687 return 0;
1688
1689 float cost = 0.1f;
1690 if (PhysActor != null)
1691 cost = PhysActor.PhysicsCost;
1692 else
1693 cost = 0.1f;
1694
1695 if ((Flags & PrimFlags.Physics) != 0)
1696 cost *= (1.0f + 0.01333f * Scale.LengthSquared()); // 0.01333 == 0.04/3
1697 return cost;
1698 }
1699 }
1700
1701 [XmlIgnore]
1702 public float StreamingCost
1703 {
1704 get
1705 {
1706 float cost;
1707 if (PhysActor != null)
1708 cost = PhysActor.StreamCost;
1709 else
1710 cost = 1.0f;
1711 return 1.0f;
1712 }
1713 }
1714
1715 [XmlIgnore]
1716 public float SimulationCost
1717 {
1718 get
1719 {
1720 // ignoring scripts. Don't like considering them for this
1721 if((Flags & PrimFlags.Physics) != 0)
1722 return 1.0f;
1723
1724 return 0.5f;
1725 }
1726 }
1727
1390 public byte PhysicsShapeType 1728 public byte PhysicsShapeType
1391 { 1729 {
1392 get { return m_physicsShapeType; } 1730 get
1731 {
1732// if (PhysActor != null)
1733// m_physicsShapeType = PhysActor.PhysicsShapeType;
1734 return m_physicsShapeType;
1735 }
1393 set 1736 set
1394 { 1737 {
1395 byte oldv = m_physicsShapeType; 1738 byte oldv = m_physicsShapeType;
@@ -1410,30 +1753,23 @@ namespace OpenSim.Region.Framework.Scenes
1410 { 1753 {
1411 if (PhysActor != null) 1754 if (PhysActor != null)
1412 { 1755 {
1413 Velocity = new Vector3(0, 0, 0);
1414 Acceleration = new Vector3(0, 0, 0);
1415 if (ParentGroup.RootPart == this)
1416 AngularVelocity = new Vector3(0, 0, 0);
1417 ParentGroup.Scene.RemovePhysicalPrim(1); 1756 ParentGroup.Scene.RemovePhysicalPrim(1);
1418 RemoveFromPhysics(); 1757 RemoveFromPhysics();
1758// Stop();
1419 } 1759 }
1420 } 1760 }
1421 else if (PhysActor == null) 1761 else if (PhysActor == null)
1422 { 1762 {
1423 ApplyPhysics((uint)Flags, VolumeDetectActive); 1763 if(oldv == (byte)PhysShapeType.none)
1764 {
1765 ApplyPhysics((uint)Flags, VolumeDetectActive, false);
1766 UpdatePhysicsSubscribedEvents();
1767 }
1424 } 1768 }
1425 else 1769 else
1426 {
1427 PhysActor.PhysicsShapeType = m_physicsShapeType; 1770 PhysActor.PhysicsShapeType = m_physicsShapeType;
1428 }
1429 1771
1430 if (ParentGroup != null) 1772 ParentGroup.HasGroupChanged = true;
1431 ParentGroup.HasGroupChanged = true;
1432 }
1433
1434 if (m_physicsShapeType != value)
1435 {
1436 UpdatePhysRequired = true;
1437 } 1773 }
1438 } 1774 }
1439 } 1775 }
@@ -1446,17 +1782,18 @@ namespace OpenSim.Region.Framework.Scenes
1446 if (value >=1 && value <= 22587.0) 1782 if (value >=1 && value <= 22587.0)
1447 { 1783 {
1448 m_density = value; 1784 m_density = value;
1449 UpdatePhysRequired = true;
1450 }
1451 1785
1452 ScheduleFullUpdateIfNone();
1453 1786
1454 if (ParentGroup != null) 1787 if (ParentGroup != null)
1455 ParentGroup.HasGroupChanged = true; 1788 {
1789 ParentGroup.HasGroupChanged = true;
1790 ScheduleFullUpdate();
1791 }
1456 1792
1457 PhysicsActor pa = PhysActor; 1793 PhysicsActor pa = PhysActor;
1458 if (pa != null) 1794 if (pa != null)
1459 pa.Density = Density; 1795 pa.Density = m_density;
1796 }
1460 } 1797 }
1461 } 1798 }
1462 1799
@@ -1468,17 +1805,17 @@ namespace OpenSim.Region.Framework.Scenes
1468 if( value >= -1 && value <=28.0f) 1805 if( value >= -1 && value <=28.0f)
1469 { 1806 {
1470 m_gravitymod = value; 1807 m_gravitymod = value;
1471 UpdatePhysRequired = true;
1472 }
1473
1474 ScheduleFullUpdateIfNone();
1475 1808
1476 if (ParentGroup != null) 1809 if (ParentGroup != null)
1477 ParentGroup.HasGroupChanged = true; 1810 {
1811 ParentGroup.HasGroupChanged = true;
1812 ScheduleFullUpdate();
1813 }
1478 1814
1479 PhysicsActor pa = PhysActor; 1815 PhysicsActor pa = PhysActor;
1480 if (pa != null) 1816 if (pa != null)
1481 pa.GravModifier = GravityModifier; 1817 pa.GravModifier = m_gravitymod;
1818 }
1482 } 1819 }
1483 } 1820 }
1484 1821
@@ -1490,17 +1827,17 @@ namespace OpenSim.Region.Framework.Scenes
1490 if (value >= 0 && value <= 255.0f) 1827 if (value >= 0 && value <= 255.0f)
1491 { 1828 {
1492 m_friction = value; 1829 m_friction = value;
1493 UpdatePhysRequired = true;
1494 }
1495
1496 ScheduleFullUpdateIfNone();
1497 1830
1498 if (ParentGroup != null) 1831 if (ParentGroup != null)
1499 ParentGroup.HasGroupChanged = true; 1832 {
1833 ParentGroup.HasGroupChanged = true;
1834 ScheduleFullUpdate();
1835 }
1500 1836
1501 PhysicsActor pa = PhysActor; 1837 PhysicsActor pa = PhysActor;
1502 if (pa != null) 1838 if (pa != null)
1503 pa.Friction = Friction; 1839 pa.Friction = m_friction;
1840 }
1504 } 1841 }
1505 } 1842 }
1506 1843
@@ -1512,20 +1849,21 @@ namespace OpenSim.Region.Framework.Scenes
1512 if (value >= 0 && value <= 1.0f) 1849 if (value >= 0 && value <= 1.0f)
1513 { 1850 {
1514 m_bounce = value; 1851 m_bounce = value;
1515 UpdatePhysRequired = true;
1516 }
1517 1852
1518 ScheduleFullUpdateIfNone(); 1853 if (ParentGroup != null)
1519 1854 {
1520 if (ParentGroup != null) 1855 ParentGroup.HasGroupChanged = true;
1521 ParentGroup.HasGroupChanged = true; 1856 ScheduleFullUpdate();
1857 }
1522 1858
1523 PhysicsActor pa = PhysActor; 1859 PhysicsActor pa = PhysActor;
1524 if (pa != null) 1860 if (pa != null)
1525 pa.Restitution = Restitution; 1861 pa.Restitution = m_bounce;
1862 }
1526 } 1863 }
1527 } 1864 }
1528 1865
1866
1529 #endregion Public Properties with only Get 1867 #endregion Public Properties with only Get
1530 1868
1531 private uint ApplyMask(uint val, bool set, uint mask) 1869 private uint ApplyMask(uint val, bool set, uint mask)
@@ -1545,7 +1883,8 @@ namespace OpenSim.Region.Framework.Scenes
1545 /// </summary> 1883 /// </summary>
1546 public void ClearUpdateSchedule() 1884 public void ClearUpdateSchedule()
1547 { 1885 {
1548 UpdateFlag = UpdateRequired.NONE; 1886 lock(UpdateFlagLock)
1887 UpdateFlag = UpdateRequired.NONE;
1549 } 1888 }
1550 1889
1551 /// <summary> 1890 /// <summary>
@@ -1585,7 +1924,7 @@ namespace OpenSim.Region.Framework.Scenes
1585 1924
1586 public void ResetExpire() 1925 public void ResetExpire()
1587 { 1926 {
1588 Expires = DateTime.Now + new TimeSpan(600000000); 1927 Expires = DateTime.UtcNow + new TimeSpan(600000000);
1589 } 1928 }
1590 1929
1591 public void AddFlag(PrimFlags flag) 1930 public void AddFlag(PrimFlags flag)
@@ -1636,8 +1975,8 @@ namespace OpenSim.Region.Framework.Scenes
1636 Utils.FloatToBytes(pTexAnim.Start).CopyTo(data, pos); 1975 Utils.FloatToBytes(pTexAnim.Start).CopyTo(data, pos);
1637 Utils.FloatToBytes(pTexAnim.Length).CopyTo(data, pos + 4); 1976 Utils.FloatToBytes(pTexAnim.Length).CopyTo(data, pos + 4);
1638 Utils.FloatToBytes(pTexAnim.Rate).CopyTo(data, pos + 8); 1977 Utils.FloatToBytes(pTexAnim.Rate).CopyTo(data, pos + 8);
1639 }
1640 1978
1979 }
1641 m_TextureAnimation = data; 1980 m_TextureAnimation = data;
1642 } 1981 }
1643 1982
@@ -1680,6 +2019,61 @@ namespace OpenSim.Region.Framework.Scenes
1680 } 2019 }
1681 } 2020 }
1682 2021
2022 // SetVelocity for LSL llSetVelocity.. may need revision if having other uses in future
2023 public void SetVelocity(Vector3 pVel, bool localGlobalTF)
2024 {
2025 if (ParentGroup == null || ParentGroup.IsDeleted || ParentGroup.inTransit)
2026 return;
2027
2028 if (ParentGroup.IsAttachment)
2029 return; // don't work on attachments (for now ??)
2030
2031 SceneObjectPart root = ParentGroup.RootPart;
2032
2033 if (root.VehicleType != (int)Vehicle.TYPE_NONE) // don't mess with vehicles
2034 return;
2035
2036 PhysicsActor pa = root.PhysActor;
2037
2038 if (pa == null || !pa.IsPhysical)
2039 return;
2040
2041 if (localGlobalTF)
2042 {
2043 pVel = pVel * GetWorldRotation();
2044 }
2045
2046 ParentGroup.Velocity = pVel;
2047 }
2048
2049 // SetAngularVelocity for LSL llSetAngularVelocity.. may need revision if having other uses in future
2050 public void SetAngularVelocity(Vector3 pAngVel, bool localGlobalTF)
2051 {
2052 if (ParentGroup == null || ParentGroup.IsDeleted || ParentGroup.inTransit)
2053 return;
2054
2055 if (ParentGroup.IsAttachment)
2056 return; // don't work on attachments (for now ??)
2057
2058 SceneObjectPart root = ParentGroup.RootPart;
2059
2060 if (root.VehicleType != (int)Vehicle.TYPE_NONE) // don't mess with vehicles
2061 return;
2062
2063 PhysicsActor pa = root.PhysActor;
2064
2065 if (pa == null || !pa.IsPhysical)
2066 return;
2067
2068 if (localGlobalTF)
2069 {
2070 pAngVel = pAngVel * GetWorldRotation();
2071 }
2072
2073 root.AngularVelocity = pAngVel;
2074 }
2075
2076
1683 /// <summary> 2077 /// <summary>
1684 /// hook to the physics scene to apply angular impulse 2078 /// hook to the physics scene to apply angular impulse
1685 /// This is sent up to the group, which then finds the root prim 2079 /// This is sent up to the group, which then finds the root prim
@@ -1689,6 +2083,9 @@ namespace OpenSim.Region.Framework.Scenes
1689 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param> 2083 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param>
1690 public void ApplyAngularImpulse(Vector3 impulsei, bool localGlobalTF) 2084 public void ApplyAngularImpulse(Vector3 impulsei, bool localGlobalTF)
1691 { 2085 {
2086 if (ParentGroup == null || ParentGroup.IsDeleted || ParentGroup.inTransit)
2087 return;
2088
1692 Vector3 impulse = impulsei; 2089 Vector3 impulse = impulsei;
1693 2090
1694 if (localGlobalTF) 2091 if (localGlobalTF)
@@ -1700,7 +2097,7 @@ namespace OpenSim.Region.Framework.Scenes
1700 impulse = newimpulse; 2097 impulse = newimpulse;
1701 } 2098 }
1702 2099
1703 ParentGroup.applyAngularImpulse(impulse); 2100 ParentGroup.ApplyAngularImpulse(impulse);
1704 } 2101 }
1705 2102
1706 /// <summary> 2103 /// <summary>
@@ -1710,20 +2107,18 @@ namespace OpenSim.Region.Framework.Scenes
1710 /// </summary> 2107 /// </summary>
1711 /// <param name="impulsei">Vector force</param> 2108 /// <param name="impulsei">Vector force</param>
1712 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param> 2109 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param>
1713 public void SetAngularImpulse(Vector3 impulsei, bool localGlobalTF) 2110
2111 // this is actualy Set Torque.. keeping naming so not to edit lslapi also
2112 public void SetAngularImpulse(Vector3 torquei, bool localGlobalTF)
1714 { 2113 {
1715 Vector3 impulse = impulsei; 2114 Vector3 torque = torquei;
1716 2115
1717 if (localGlobalTF) 2116 if (localGlobalTF)
1718 { 2117 {
1719 Quaternion grot = GetWorldRotation(); 2118 torque *= GetWorldRotation();
1720 Quaternion AXgrot = grot;
1721 Vector3 AXimpulsei = impulsei;
1722 Vector3 newimpulse = AXimpulsei * AXgrot;
1723 impulse = newimpulse;
1724 } 2119 }
1725 2120
1726 ParentGroup.setAngularImpulse(impulse); 2121 Torque = torque;
1727 } 2122 }
1728 2123
1729 /// <summary> 2124 /// <summary>
@@ -1731,7 +2126,9 @@ namespace OpenSim.Region.Framework.Scenes
1731 /// </summary> 2126 /// </summary>
1732 /// <param name="rootObjectFlags"></param> 2127 /// <param name="rootObjectFlags"></param>
1733 /// <param name="VolumeDetectActive"></param> 2128 /// <param name="VolumeDetectActive"></param>
1734 public void ApplyPhysics(uint rootObjectFlags, bool _VolumeDetectActive) 2129 /// <param name="building"></param>
2130
2131 public void ApplyPhysics(uint _ObjectFlags, bool _VolumeDetectActive, bool building)
1735 { 2132 {
1736 VolumeDetectActive = _VolumeDetectActive; 2133 VolumeDetectActive = _VolumeDetectActive;
1737 2134
@@ -1741,8 +2138,8 @@ namespace OpenSim.Region.Framework.Scenes
1741 if (PhysicsShapeType == (byte)PhysShapeType.none) 2138 if (PhysicsShapeType == (byte)PhysShapeType.none)
1742 return; 2139 return;
1743 2140
1744 bool isPhysical = (rootObjectFlags & (uint) PrimFlags.Physics) != 0; 2141 bool isPhysical = (_ObjectFlags & (uint) PrimFlags.Physics) != 0;
1745 bool isPhantom = (rootObjectFlags & (uint) PrimFlags.Phantom) != 0; 2142 bool isPhantom = (_ObjectFlags & (uint)PrimFlags.Phantom) != 0;
1746 2143
1747 if (_VolumeDetectActive) 2144 if (_VolumeDetectActive)
1748 isPhantom = true; 2145 isPhantom = true;
@@ -1757,10 +2154,14 @@ namespace OpenSim.Region.Framework.Scenes
1757 && !ParentGroup.IsAttachmentCheckFull() 2154 && !ParentGroup.IsAttachmentCheckFull()
1758 && !(Shape.PathCurve == (byte)Extrusion.Flexible)) 2155 && !(Shape.PathCurve == (byte)Extrusion.Flexible))
1759 { 2156 {
1760 AddToPhysics(isPhysical, isPhantom, isPhysical); 2157 AddToPhysics(isPhysical, isPhantom, building, isPhysical);
2158 UpdatePhysicsSubscribedEvents(); // not sure if appliable here
1761 } 2159 }
1762 else 2160 else
2161 {
1763 PhysActor = null; // just to be sure 2162 PhysActor = null; // just to be sure
2163 RemFlag(PrimFlags.CameraDecoupled);
2164 }
1764 } 2165 }
1765 } 2166 }
1766 2167
@@ -1786,9 +2187,9 @@ namespace OpenSim.Region.Framework.Scenes
1786 /// <param name="linkNum"></param> 2187 /// <param name="linkNum"></param>
1787 /// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param> 2188 /// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param>
1788 /// <returns></returns> 2189 /// <returns></returns>
1789 public SceneObjectPart Copy(uint localID, UUID AgentID, UUID GroupID, int linkNum, bool userExposed) 2190 public SceneObjectPart Copy(uint plocalID, UUID AgentID, UUID GroupID, int linkNum, bool userExposed)
1790 { 2191 {
1791 // FIXME: This is dangerous since it's easy to forget to reset some references when necessary and end up 2192 // FIXME: This is dangerous since it's easy to forget to reset some references when necessary and end up
1792 // with bugs that only occur in some circumstances (e.g. crossing between regions on the same simulator 2193 // with bugs that only occur in some circumstances (e.g. crossing between regions on the same simulator
1793 // but not between regions on different simulators). Really, all copying should be done explicitly. 2194 // but not between regions on different simulators). Really, all copying should be done explicitly.
1794 SceneObjectPart dupe = (SceneObjectPart)MemberwiseClone(); 2195 SceneObjectPart dupe = (SceneObjectPart)MemberwiseClone();
@@ -1816,6 +2217,12 @@ namespace OpenSim.Region.Framework.Scenes
1816 dupe.Category = Category; 2217 dupe.Category = Category;
1817 dupe.m_rezzed = m_rezzed; 2218 dupe.m_rezzed = m_rezzed;
1818 2219
2220 dupe.m_UndoRedo = null;
2221 dupe.m_isSelected = false;
2222
2223 dupe.IgnoreUndoUpdate = false;
2224 dupe.Undoing = false;
2225
1819 dupe.m_inventory = new SceneObjectPartInventory(dupe); 2226 dupe.m_inventory = new SceneObjectPartInventory(dupe);
1820 dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone(); 2227 dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone();
1821 2228
@@ -1830,60 +2237,45 @@ namespace OpenSim.Region.Framework.Scenes
1830 } 2237 }
1831 2238
1832 // Move afterwards ResetIDs as it clears the localID 2239 // Move afterwards ResetIDs as it clears the localID
1833 dupe.LocalId = localID; 2240 dupe.LocalId = plocalID;
2241
1834 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. 2242 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1835 dupe.LastOwnerID = OwnerID; 2243 if(OwnerID != GroupID)
2244 dupe.LastOwnerID = OwnerID;
2245 else
2246 dupe.LastOwnerID = LastOwnerID; // redundant ?
2247
2248 dupe.RezzerID = RezzerID;
1836 2249
1837 byte[] extraP = new byte[Shape.ExtraParams.Length]; 2250 byte[] extraP = new byte[Shape.ExtraParams.Length];
1838 Array.Copy(Shape.ExtraParams, extraP, extraP.Length); 2251 Array.Copy(Shape.ExtraParams, extraP, extraP.Length);
1839 dupe.Shape.ExtraParams = extraP; 2252 dupe.Shape.ExtraParams = extraP;
1840 2253
1841 dupe.m_sittingAvatars = new HashSet<ScenePresence>(); 2254 dupe.m_sittingAvatars = new HashSet<ScenePresence>();
1842 2255 dupe.SitTargetAvatar = UUID.Zero;
1843 // safeguard actual copy is done in sog.copy 2256 // safeguard actual copy is done in sog.copy
1844 dupe.KeyframeMotion = null; 2257 dupe.KeyframeMotion = null;
1845 dupe.PayPrice = (int[])PayPrice.Clone(); 2258 dupe.PayPrice = (int[])PayPrice.Clone();
1846 2259
1847 dupe.DynAttrs.CopyFrom(DynAttrs); 2260 dupe.DynAttrs.CopyFrom(DynAttrs);
1848 2261
1849 if (userExposed) 2262 if (userExposed)
1850 { 2263 {
1851/*
1852 if (dupe.m_shape.SculptEntry && dupe.m_shape.SculptTexture != UUID.Zero)
1853 {
1854 ParentGroup.Scene.AssetService.Get(
1855 dupe.m_shape.SculptTexture.ToString(), dupe, dupe.AssetReceived);
1856 }
1857*/
1858 bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0); 2264 bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0);
1859 dupe.DoPhysicsPropertyUpdate(UsePhysics, true); 2265 dupe.DoPhysicsPropertyUpdate(UsePhysics, true);
1860 } 2266 }
1861 2267
2268 if (dupe.PhysActor != null)
2269 dupe.PhysActor.LocalID = plocalID;
2270
1862 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed); 2271 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed);
1863 2272
1864// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID); 2273// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID);
1865 2274
1866 return dupe; 2275 return dupe;
1867 } 2276 }
1868 2277
1869 /// <summary> 2278 /// <summary>
1870 /// Called back by asynchronous asset fetch.
1871 /// </summary>
1872 /// <param name="id">ID of asset received</param>
1873 /// <param name="sender">Register</param>
1874 /// <param name="asset"></param>
1875/*
1876 protected void AssetReceived(string id, Object sender, AssetBase asset)
1877 {
1878 if (asset != null)
1879 SculptTextureCallback(asset);
1880 else
1881 m_log.WarnFormat(
1882 "[SCENE OBJECT PART]: Part {0} {1} requested mesh/sculpt data for asset id {2} from asset service but received no data",
1883 Name, UUID, id);
1884 }
1885*/
1886 /// <summary>
1887 /// Do a physics property update for a NINJA joint. 2279 /// Do a physics property update for a NINJA joint.
1888 /// </summary> 2280 /// </summary>
1889 /// <param name="UsePhysics"></param> 2281 /// <param name="UsePhysics"></param>
@@ -1970,15 +2362,14 @@ namespace OpenSim.Region.Framework.Scenes
1970 ParentGroup.Scene.PhysicsScene.RequestJointDeletion(Name); // FIXME: what if the name changed? 2362 ParentGroup.Scene.PhysicsScene.RequestJointDeletion(Name); // FIXME: what if the name changed?
1971 2363
1972 // make sure client isn't interpolating the joint proxy object 2364 // make sure client isn't interpolating the joint proxy object
1973 Velocity = Vector3.Zero; 2365 Stop();
1974 AngularVelocity = Vector3.Zero;
1975 Acceleration = Vector3.Zero;
1976 } 2366 }
1977 } 2367 }
1978 } 2368 }
1979 2369
1980 /// <summary> 2370 /// <summary>
1981 /// Do a physics propery update for this part. 2371 /// Do a physics propery update for this part.
2372 /// now also updates phantom and volume detector
1982 /// </summary> 2373 /// </summary>
1983 /// <param name="UsePhysics"></param> 2374 /// <param name="UsePhysics"></param>
1984 /// <param name="isNew"></param> 2375 /// <param name="isNew"></param>
@@ -2004,66 +2395,71 @@ namespace OpenSim.Region.Framework.Scenes
2004 { 2395 {
2005 if (pa.IsPhysical) // implies UsePhysics==false for this block 2396 if (pa.IsPhysical) // implies UsePhysics==false for this block
2006 { 2397 {
2007 if (!isNew) 2398 if (!isNew) // implies UsePhysics==false for this block
2399 {
2008 ParentGroup.Scene.RemovePhysicalPrim(1); 2400 ParentGroup.Scene.RemovePhysicalPrim(1);
2009 2401
2010 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate; 2402 Velocity = new Vector3(0, 0, 0);
2011 pa.OnOutOfBounds -= PhysicsOutOfBounds; 2403 Acceleration = new Vector3(0, 0, 0);
2012 pa.delink(); 2404 AngularVelocity = new Vector3(0, 0, 0);
2405 APIDActive = false;
2013 2406
2014 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints && (!isNew)) 2407 if (pa.Phantom && !VolumeDetectActive)
2015 { 2408 {
2016 // destroy all joints connected to this now deactivated body 2409 RemoveFromPhysics();
2017 ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(pa); 2410 return;
2018 } 2411 }
2019 2412
2020 // stop client-side interpolation of all joint proxy objects that have just been deleted 2413 pa.IsPhysical = UsePhysics;
2021 // this is done because RemoveAllJointsConnectedToActor invokes the OnJointDeactivated callback, 2414 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
2022 // which stops client-side interpolation of deactivated joint proxy objects. 2415 pa.OnOutOfBounds -= PhysicsOutOfBounds;
2416 pa.delink();
2417 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
2418 {
2419 // destroy all joints connected to this now deactivated body
2420 ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(pa);
2421 }
2422 }
2023 } 2423 }
2024 2424
2025 if (!UsePhysics && !isNew) 2425 if (pa.IsPhysical != UsePhysics)
2026 { 2426 pa.IsPhysical = UsePhysics;
2027 // reset velocity to 0 on physics switch-off. Without that, the client thinks the
2028 // prim still has velocity and continues to interpolate its position along the old
2029 // velocity-vector.
2030 Velocity = new Vector3(0, 0, 0);
2031 Acceleration = new Vector3(0, 0, 0);
2032 AngularVelocity = new Vector3(0, 0, 0);
2033 //RotationalVelocity = new Vector3(0, 0, 0);
2034 }
2035 2427
2036 pa.IsPhysical = UsePhysics; 2428 if (UsePhysics)
2429 {
2430 if (ParentGroup.RootPart.KeyframeMotion != null)
2431 ParentGroup.RootPart.KeyframeMotion.Stop();
2432 ParentGroup.RootPart.KeyframeMotion = null;
2433 ParentGroup.Scene.AddPhysicalPrim(1);
2037 2434
2038 // If we're not what we're supposed to be in the physics scene, recreate ourselves. 2435 PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
2039 //m_parentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); 2436 PhysActor.OnOutOfBounds += PhysicsOutOfBounds;
2040 /// that's not wholesome. Had to make Scene public
2041 //PhysActor = null;
2042 2437
2043 if ((Flags & PrimFlags.Phantom) == 0) 2438 if (_parentID != 0 && _parentID != LocalId)
2044 {
2045 if (UsePhysics)
2046 { 2439 {
2047 if (ParentGroup.RootPart.KeyframeMotion != null) 2440 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
2048 ParentGroup.RootPart.KeyframeMotion.Stop();
2049 ParentGroup.RootPart.KeyframeMotion = null;
2050 ParentGroup.Scene.AddPhysicalPrim(1);
2051
2052 pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
2053 pa.OnOutOfBounds += PhysicsOutOfBounds;
2054 if (ParentID != 0 && ParentID != LocalId)
2055 {
2056 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
2057 2441
2058 if (parentPa != null) 2442 if (parentPa != null)
2059 { 2443 {
2060 pa.link(parentPa); 2444 pa.link(parentPa);
2061 }
2062 } 2445 }
2063 } 2446 }
2064 } 2447 }
2065 } 2448 }
2066 2449
2450 bool phan = ((Flags & PrimFlags.Phantom) != 0);
2451 if (pa.Phantom != phan)
2452 pa.Phantom = phan;
2453
2454// some engines dont' have this check still
2455// if (VolumeDetectActive != pa.IsVolumeDtc)
2456 {
2457 if (VolumeDetectActive)
2458 pa.SetVolumeDetect(1);
2459 else
2460 pa.SetVolumeDetect(0);
2461 }
2462
2067 // If this part is a sculpt then delay the physics update until we've asynchronously loaded the 2463 // If this part is a sculpt then delay the physics update until we've asynchronously loaded the
2068 // mesh data. 2464 // mesh data.
2069// if (Shape.SculptEntry) 2465// if (Shape.SculptEntry)
@@ -2132,13 +2528,8 @@ namespace OpenSim.Region.Framework.Scenes
2132 2528
2133 public int GetAxisRotation(int axis) 2529 public int GetAxisRotation(int axis)
2134 { 2530 {
2135 //Cannot use ScriptBaseClass constants as no referance to it currently. 2531 if (!ParentGroup.IsDeleted)
2136 if (axis == (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_X) 2532 return ParentGroup.GetAxisRotation(axis);
2137 return STATUS_ROTATE_X;
2138 if (axis == (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Y)
2139 return STATUS_ROTATE_Y;
2140 if (axis == (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Z)
2141 return STATUS_ROTATE_Z;
2142 2533
2143 return 0; 2534 return 0;
2144 } 2535 }
@@ -2153,7 +2544,7 @@ namespace OpenSim.Region.Framework.Scenes
2153 2544
2154 public uint GetEffectiveObjectFlags() 2545 public uint GetEffectiveObjectFlags()
2155 { 2546 {
2156 // Commenting this section of code out since it doesn't actually do anything, as enums are handled by 2547 // Commenting this section of code out since it doesn't actually do anything, as enums are handled by
2157 // value rather than reference 2548 // value rather than reference
2158// PrimFlags f = _flags; 2549// PrimFlags f = _flags;
2159// if (m_parentGroup == null || m_parentGroup.RootPart == this) 2550// if (m_parentGroup == null || m_parentGroup.RootPart == this)
@@ -2162,44 +2553,118 @@ namespace OpenSim.Region.Framework.Scenes
2162 return (uint)Flags | (uint)LocalFlags; 2553 return (uint)Flags | (uint)LocalFlags;
2163 } 2554 }
2164 2555
2556 // some of this lines need be moved to other place later
2557
2558 // effective permitions considering only this part inventory contents perms
2559 public uint AggregatedInnerOwnerPerms {get; private set; }
2560 public uint AggregatedInnerGroupPerms {get; private set; }
2561 public uint AggregatedInnerEveryonePerms {get; private set; }
2562 private object InnerPermsLock = new object();
2563
2564 public void AggregateInnerPerms()
2565 {
2566 // assuming child prims permissions masks are irrelevant on a linkset
2567 // root part is handle at SOG since its masks are the sog masks
2568 const uint mask = (uint)PermissionMask.AllEffective;
2569
2570 uint owner = mask;
2571 uint group = mask;
2572 uint everyone = mask;
2573
2574 lock(InnerPermsLock) // do we really need this?
2575 {
2576 if(Inventory != null)
2577 Inventory.AggregateInnerPerms(ref owner, ref group, ref everyone);
2578
2579 AggregatedInnerOwnerPerms = owner & mask;
2580 AggregatedInnerGroupPerms = group & mask;
2581 AggregatedInnerEveryonePerms = everyone & mask;
2582 }
2583 if(ParentGroup != null)
2584 ParentGroup.InvalidateEffectivePerms();
2585 }
2586
2587 // same as above but called during group Effective Permission validation
2588 public void AggregatedInnerPermsForGroup()
2589 {
2590 // assuming child prims permissions masks are irrelevant on a linkset
2591 // root part is handle at SOG since its masks are the sog masks
2592 const uint mask = (uint)PermissionMask.AllEffective;
2593
2594 uint owner = mask;
2595 uint group = mask;
2596 uint everyone = mask;
2597
2598 lock(InnerPermsLock) // do we really need this?
2599 {
2600 if(Inventory != null)
2601 Inventory.AggregateInnerPerms(ref owner, ref group, ref everyone);
2602
2603 AggregatedInnerOwnerPerms = owner & mask;
2604 AggregatedInnerGroupPerms = group & mask;
2605 AggregatedInnerEveryonePerms = everyone & mask;
2606 }
2607 }
2608
2165 public Vector3 GetGeometricCenter() 2609 public Vector3 GetGeometricCenter()
2166 { 2610 {
2611 // this is not real geometric center but a average of positions relative to root prim acording to
2612 // http://wiki.secondlife.com/wiki/llGetGeometricCenter
2613 // ignoring tortured prims details since sl also seems to ignore
2614 // so no real use in doing it on physics
2615 if (ParentGroup.IsDeleted)
2616 return new Vector3(0, 0, 0);
2617
2618 return ParentGroup.GetGeometricCenter();
2619 }
2620
2621 public float GetMass()
2622 {
2167 PhysicsActor pa = PhysActor; 2623 PhysicsActor pa = PhysActor;
2168 2624
2169 if (pa != null) 2625 if (pa != null)
2170 return pa.GeometricCenter; 2626 return pa.Mass;
2171 else 2627 else
2172 return Vector3.Zero; 2628 return 0;
2173 } 2629 }
2174 2630
2175 public Vector3 GetCenterOfMass() 2631 public Vector3 GetCenterOfMass()
2176 { 2632 {
2633 if (ParentGroup.RootPart == this)
2634 {
2635 if (ParentGroup.IsDeleted)
2636 return AbsolutePosition;
2637 return ParentGroup.GetCenterOfMass();
2638 }
2639
2177 PhysicsActor pa = PhysActor; 2640 PhysicsActor pa = PhysActor;
2178 2641
2179 if (pa != null) 2642 if (pa != null)
2180 return pa.CenterOfMass; 2643 {
2644 Vector3 tmp = pa.CenterOfMass;
2645 return tmp;
2646 }
2181 else 2647 else
2182 return Vector3.Zero; 2648 return AbsolutePosition;
2183 } 2649 }
2184 2650
2185 public float GetMass() 2651 public Vector3 GetPartCenterOfMass()
2186 { 2652 {
2187 PhysicsActor pa = PhysActor; 2653 PhysicsActor pa = PhysActor;
2188 2654
2189 if (pa != null) 2655 if (pa != null)
2190 return pa.Mass; 2656 {
2657 Vector3 tmp = pa.CenterOfMass;
2658 return tmp;
2659 }
2191 else 2660 else
2192 return 0; 2661 return AbsolutePosition;
2193 } 2662 }
2194 2663
2664
2195 public Vector3 GetForce() 2665 public Vector3 GetForce()
2196 { 2666 {
2197 PhysicsActor pa = PhysActor; 2667 return Force;
2198
2199 if (pa != null)
2200 return pa.Force;
2201 else
2202 return Vector3.Zero;
2203 } 2668 }
2204 2669
2205 /// <summary> 2670 /// <summary>
@@ -2314,7 +2779,7 @@ namespace OpenSim.Region.Framework.Scenes
2314 detobj.velVector = obj.Velocity; 2779 detobj.velVector = obj.Velocity;
2315 detobj.colliderType = 0; 2780 detobj.colliderType = 0;
2316 detobj.groupUUID = obj.GroupID; 2781 detobj.groupUUID = obj.GroupID;
2317 2782 detobj.linkNumber = LinkNum;
2318 return detobj; 2783 return detobj;
2319 } 2784 }
2320 2785
@@ -2327,8 +2792,13 @@ namespace OpenSim.Region.Framework.Scenes
2327 detobj.posVector = av.AbsolutePosition; 2792 detobj.posVector = av.AbsolutePosition;
2328 detobj.rotQuat = av.Rotation; 2793 detobj.rotQuat = av.Rotation;
2329 detobj.velVector = av.Velocity; 2794 detobj.velVector = av.Velocity;
2330 detobj.colliderType = 0; 2795 detobj.colliderType = av.IsNPC ? 0x20 : 0x1; // OpenSim\Region\ScriptEngine\Shared\Helpers.cs
2796 if(av.IsSatOnObject)
2797 detobj.colliderType |= 0x4; //passive
2798 else if(detobj.velVector != Vector3.Zero)
2799 detobj.colliderType |= 0x2; //active
2331 detobj.groupUUID = av.ControllingClient.ActiveGroupId; 2800 detobj.groupUUID = av.ControllingClient.ActiveGroupId;
2801 detobj.linkNumber = LinkNum;
2332 2802
2333 return detobj; 2803 return detobj;
2334 } 2804 }
@@ -2344,6 +2814,7 @@ namespace OpenSim.Region.Framework.Scenes
2344 detobj.velVector = Vector3.Zero; 2814 detobj.velVector = Vector3.Zero;
2345 detobj.colliderType = 0; 2815 detobj.colliderType = 0;
2346 detobj.groupUUID = UUID.Zero; 2816 detobj.groupUUID = UUID.Zero;
2817 detobj.linkNumber = LinkNum; // pass my link number not sure needed.. but no harm
2347 2818
2348 return detobj; 2819 return detobj;
2349 } 2820 }
@@ -2352,12 +2823,13 @@ namespace OpenSim.Region.Framework.Scenes
2352 { 2823 {
2353 ColliderArgs colliderArgs = new ColliderArgs(); 2824 ColliderArgs colliderArgs = new ColliderArgs();
2354 List<DetectedObject> colliding = new List<DetectedObject>(); 2825 List<DetectedObject> colliding = new List<DetectedObject>();
2826 Scene parentScene = ParentGroup.Scene;
2355 foreach (uint localId in colliders) 2827 foreach (uint localId in colliders)
2356 { 2828 {
2357 if (localId == 0) 2829 if (localId == 0)
2358 continue; 2830 continue;
2359 2831
2360 SceneObjectPart obj = ParentGroup.Scene.GetSceneObjectPart(localId); 2832 SceneObjectPart obj = parentScene.GetSceneObjectPart(localId);
2361 if (obj != null) 2833 if (obj != null)
2362 { 2834 {
2363 if (!dest.CollisionFilteredOut(obj.UUID, obj.Name)) 2835 if (!dest.CollisionFilteredOut(obj.UUID, obj.Name))
@@ -2365,7 +2837,7 @@ namespace OpenSim.Region.Framework.Scenes
2365 } 2837 }
2366 else 2838 else
2367 { 2839 {
2368 ScenePresence av = ParentGroup.Scene.GetScenePresence(localId); 2840 ScenePresence av = parentScene.GetScenePresence(localId);
2369 if (av != null && (!av.IsChildAgent)) 2841 if (av != null && (!av.IsChildAgent))
2370 { 2842 {
2371 if (!dest.CollisionFilteredOut(av.UUID, av.Name)) 2843 if (!dest.CollisionFilteredOut(av.UUID, av.Name))
@@ -2393,7 +2865,7 @@ namespace OpenSim.Region.Framework.Scenes
2393 CollidingMessage = CreateColliderArgs(this, colliders); 2865 CollidingMessage = CreateColliderArgs(this, colliders);
2394 2866
2395 if (CollidingMessage.Colliders.Count > 0) 2867 if (CollidingMessage.Colliders.Count > 0)
2396 DoNotify(notify, LocalId, CollidingMessage); 2868 notify(LocalId, CollidingMessage);
2397 2869
2398 if (PassCollisions) 2870 if (PassCollisions)
2399 sendToRoot = true; 2871 sendToRoot = true;
@@ -2407,109 +2879,205 @@ namespace OpenSim.Region.Framework.Scenes
2407 { 2879 {
2408 CollidingMessage = CreateColliderArgs(ParentGroup.RootPart, colliders); 2880 CollidingMessage = CreateColliderArgs(ParentGroup.RootPart, colliders);
2409 if (CollidingMessage.Colliders.Count > 0) 2881 if (CollidingMessage.Colliders.Count > 0)
2410 DoNotify(notify, ParentGroup.RootPart.LocalId, CollidingMessage); 2882 notify(ParentGroup.RootPart.LocalId, CollidingMessage);
2411 } 2883 }
2412 } 2884 }
2413 } 2885 }
2414 2886
2415 private void SendLandCollisionEvent(scriptEvents ev, ScriptCollidingNotification notify) 2887 private void SendLandCollisionEvent(scriptEvents ev, ScriptCollidingNotification notify)
2416 { 2888 {
2417 if ((ParentGroup.RootPart.ScriptEvents & ev) != 0) 2889 bool sendToRoot = true;
2418 {
2419 ColliderArgs LandCollidingMessage = new ColliderArgs();
2420 List<DetectedObject> colliding = new List<DetectedObject>();
2421
2422 colliding.Add(CreateDetObjectForGround());
2423 LandCollidingMessage.Colliders = colliding;
2424 2890
2425 DoNotify(notify, LocalId, LandCollidingMessage); 2891 ColliderArgs LandCollidingMessage = new ColliderArgs();
2426 } 2892 List<DetectedObject> colliding = new List<DetectedObject>();
2427 }
2428 2893
2429 private void DoNotify(ScriptCollidingNotification notify, uint id, ColliderArgs collargs) 2894 colliding.Add(CreateDetObjectForGround());
2430 { 2895 LandCollidingMessage.Colliders = colliding;
2431 if (m_parentGroup != null && ParentGroup.Scene != null && ParentGroup.Scene.ShouldUseFireAndForgetForCollisions)
2432 {
2433 // For those learning C#, FireAndForget takes a function, an object to pass
2434 // to that function and an ID string. The "oo => {}" construct is a lambda expression
2435 // for a function with one arguement ('oo'). The 'new Object[] {}" construct creates an Object
2436 // that is an object array and initializes it with three items (the parameters
2437 // being passed). The parameters passed are the function to call ('notify') and
2438 // its two arguements. Finally, once in the function (called later by the FireAndForget
2439 // thread scheduler), the passed object is cast to an object array and then each
2440 // of its items (aoo[0] to aoo[2]) are individually cast to what they are and
2441 // then used in a call of the passed ScriptCollidingNotification function.
2442 Util.FireAndForget(oo =>
2443 {
2444 Object[] aoo = (Object[])oo;
2445 ((ScriptCollidingNotification)aoo[0])((uint)aoo[1], (ColliderArgs)aoo[2]);
2446 2896
2447 }, new Object[] { notify, id, collargs }, "SOP.Collision"); 2897 if (Inventory.ContainsScripts())
2898 {
2899 if (!PassCollisions)
2900 sendToRoot = false;
2448 } 2901 }
2449 else 2902 if ((ScriptEvents & ev) != 0)
2903 notify(LocalId, LandCollidingMessage);
2904
2905 if ((ParentGroup.RootPart.ScriptEvents & ev) != 0 && sendToRoot)
2450 { 2906 {
2451 notify(id, collargs); 2907 notify(ParentGroup.RootPart.LocalId, LandCollidingMessage);
2452 } 2908 }
2453 } 2909 }
2454 2910
2455 public void PhysicsCollision(EventArgs e) 2911 public void PhysicsCollision(EventArgs e)
2456 { 2912 {
2457 if (ParentGroup.Scene == null || ParentGroup.IsDeleted) 2913 if (ParentGroup.Scene == null || ParentGroup.IsDeleted || ParentGroup.inTransit)
2458 return; 2914 return;
2459 2915
2460 // single threaded here 2916 // this a thread from physics ( heartbeat )
2917 bool thisHitLand = false;
2918 bool startLand = false;
2919 bool endedLand = false;
2920
2461 CollisionEventUpdate a = (CollisionEventUpdate)e; 2921 CollisionEventUpdate a = (CollisionEventUpdate)e;
2462 Dictionary<uint, ContactPoint> collissionswith = a.m_objCollisionList; 2922 Dictionary<uint, ContactPoint> collissionswith = a.m_objCollisionList;
2463 List<uint> thisHitColliders = new List<uint>(); 2923 List<uint> thisHitColliders = new List<uint>();
2464 List<uint> endedColliders = new List<uint>(); 2924 List<uint> endedColliders = new List<uint>();
2465 List<uint> startedColliders = new List<uint>(); 2925 List<uint> startedColliders = new List<uint>();
2466 2926
2467 // calculate things that started colliding this time 2927 if (collissionswith.Count == 0)
2468 // and build up list of colliders this time
2469 foreach (uint localid in collissionswith.Keys)
2470 { 2928 {
2471 thisHitColliders.Add(localid); 2929 if (m_lastColliders.Count == 0 && !m_lastLandCollide)
2472 if (!m_lastColliders.Contains(localid)) 2930 return; // nothing to do
2473 startedColliders.Add(localid);
2474 }
2475 2931
2476 // calculate things that ended colliding 2932 endedLand = m_lastLandCollide;
2477 foreach (uint localID in m_lastColliders) 2933 m_lastLandCollide = false;
2478 { 2934
2479 if (!thisHitColliders.Contains(localID)) 2935 foreach (uint localID in m_lastColliders)
2936 {
2480 endedColliders.Add(localID); 2937 endedColliders.Add(localID);
2938 }
2939
2940 m_lastColliders.Clear();
2481 } 2941 }
2942 else
2943 {
2944 List<CollisionForSoundInfo> soundinfolist = new List<CollisionForSoundInfo>();
2482 2945
2483 //add the items that started colliding this time to the last colliders list. 2946 // calculate things that started colliding this time
2484 foreach (uint localID in startedColliders) 2947 // and build up list of colliders this time
2485 m_lastColliders.Add(localID); 2948 if (!VolumeDetectActive && CollisionSoundType >= 0)
2949 {
2950 CollisionForSoundInfo soundinfo;
2951 ContactPoint curcontact;
2486 2952
2487 // remove things that ended colliding from the last colliders list 2953 foreach (uint id in collissionswith.Keys)
2488 foreach (uint localID in endedColliders) 2954 {
2489 m_lastColliders.Remove(localID); 2955 if(id == 0)
2956 {
2957 thisHitLand = true;
2958 if (!m_lastLandCollide)
2959 {
2960 startLand = true;
2961 curcontact = collissionswith[id];
2962 if (Math.Abs(curcontact.RelativeSpeed) > 0.2)
2963 {
2964 soundinfo = new CollisionForSoundInfo();
2965 soundinfo.colliderID = id;
2966 soundinfo.position = curcontact.Position;
2967 soundinfo.relativeVel = curcontact.RelativeSpeed;
2968 soundinfolist.Add(soundinfo);
2969 }
2970 }
2971 }
2972 else
2973 {
2974 thisHitColliders.Add(id);
2975 if (!m_lastColliders.Contains(id))
2976 {
2977 startedColliders.Add(id);
2490 2978
2491 // play the sound. 2979 curcontact = collissionswith[id];
2492 if (startedColliders.Count > 0 && CollisionSound != UUID.Zero && CollisionSoundVolume > 0.0f) 2980 if (Math.Abs(curcontact.RelativeSpeed) > 0.2)
2493 { 2981 {
2494 ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>(); 2982 soundinfo = new CollisionForSoundInfo();
2495 if (soundModule != null) 2983 soundinfo.colliderID = id;
2984 soundinfo.position = curcontact.Position;
2985 soundinfo.relativeVel = curcontact.RelativeSpeed;
2986 soundinfolist.Add(soundinfo);
2987 }
2988 }
2989 }
2990 }
2991 }
2992 else
2993 {
2994 foreach (uint id in collissionswith.Keys)
2995 {
2996 if(id == 0)
2997 {
2998 thisHitLand = true;
2999 if (!m_lastLandCollide)
3000 startLand = true;
3001 }
3002 else
3003 {
3004 thisHitColliders.Add(id);
3005 if (!m_lastColliders.Contains(id))
3006 startedColliders.Add(id);
3007 }
3008 }
3009 }
3010
3011 // calculate things that ended colliding
3012 foreach (uint localID in m_lastColliders)
2496 { 3013 {
2497 soundModule.SendSound(UUID, CollisionSound, 3014 if (!thisHitColliders.Contains(localID))
2498 CollisionSoundVolume, true, 0, 0, false, 3015 endedColliders.Add(localID);
2499 false);
2500 } 3016 }
3017
3018 //add the items that started colliding this time to the last colliders list.
3019 foreach (uint localID in startedColliders)
3020 m_lastColliders.Add(localID);
3021
3022 // remove things that ended colliding from the last colliders list
3023 foreach (uint localID in endedColliders)
3024 m_lastColliders.Remove(localID);
3025
3026 if(m_lastLandCollide && !thisHitLand)
3027 endedLand = true;
3028
3029 m_lastLandCollide = thisHitLand;
3030
3031 // play sounds.
3032 if (soundinfolist.Count > 0)
3033 CollisionSounds.PartCollisionSound(this, soundinfolist);
2501 } 3034 }
3035
3036 EventManager eventmanager = ParentGroup.Scene.EventManager;
3037
3038 SendCollisionEvent(scriptEvents.collision_start, startedColliders, eventmanager.TriggerScriptCollidingStart);
3039 if (!VolumeDetectActive)
3040 SendCollisionEvent(scriptEvents.collision , m_lastColliders , eventmanager.TriggerScriptColliding);
3041 SendCollisionEvent(scriptEvents.collision_end , endedColliders , eventmanager.TriggerScriptCollidingEnd);
3042
3043 if (!VolumeDetectActive)
3044 {
3045 if (startLand)
3046 SendLandCollisionEvent(scriptEvents.land_collision_start, eventmanager.TriggerScriptLandCollidingStart);
3047 if (m_lastLandCollide)
3048 SendLandCollisionEvent(scriptEvents.land_collision, eventmanager.TriggerScriptLandColliding);
3049 if (endedLand)
3050 SendLandCollisionEvent(scriptEvents.land_collision_end, eventmanager.TriggerScriptLandCollidingEnd);
3051 }
3052 }
3053
3054 // The Collision sounds code calls this
3055 public void SendCollisionSound(UUID soundID, double volume, Vector3 position)
3056 {
3057 if (soundID == UUID.Zero)
3058 return;
2502 3059
2503 SendCollisionEvent(scriptEvents.collision_start, startedColliders, ParentGroup.Scene.EventManager.TriggerScriptCollidingStart); 3060 ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>();
2504 SendCollisionEvent(scriptEvents.collision , m_lastColliders , ParentGroup.Scene.EventManager.TriggerScriptColliding); 3061 if (soundModule == null)
2505 SendCollisionEvent(scriptEvents.collision_end , endedColliders , ParentGroup.Scene.EventManager.TriggerScriptCollidingEnd); 3062 return;
3063
3064 if (volume > 1)
3065 volume = 1;
3066 if (volume < 0)
3067 volume = 0;
3068
3069 int now = Util.EnvironmentTickCount();
3070 if(Util.EnvironmentTickCountSubtract(now, LastColSoundSentTime) < 200)
3071 return;
3072
3073 LastColSoundSentTime = now;
3074
3075 UUID ownerID = OwnerID;
3076 UUID objectID = ParentGroup.RootPart.UUID;
3077 UUID parentID = ParentGroup.UUID;
3078 ulong regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle;
2506 3079
2507 if (startedColliders.Contains(0)) 3080 soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, 0 );
2508 SendLandCollisionEvent(scriptEvents.land_collision_start, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingStart);
2509 if (m_lastColliders.Contains(0))
2510 SendLandCollisionEvent(scriptEvents.land_collision, ParentGroup.Scene.EventManager.TriggerScriptLandColliding);
2511 if (endedColliders.Contains(0))
2512 SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd);
2513 } 3081 }
2514 3082
2515 public void PhysicsOutOfBounds(Vector3 pos) 3083 public void PhysicsOutOfBounds(Vector3 pos)
@@ -2517,9 +3085,9 @@ namespace OpenSim.Region.Framework.Scenes
2517 // Note: This is only being called on the root prim at this time. 3085 // Note: This is only being called on the root prim at this time.
2518 3086
2519 m_log.ErrorFormat( 3087 m_log.ErrorFormat(
2520 "[SCENE OBJECT PART]: Physical object {0}, localID {1} went out of bounds at {2} in {3}. Stopping at {4} and making non-physical.", 3088 "[SCENE OBJECT PART]: Physical object {0}, localID {1} went out of bounds at {2} in {3}. Stopping at {4} and making non-physical.",
2521 Name, LocalId, pos, ParentGroup.Scene.Name, AbsolutePosition); 3089 Name, LocalId, pos, ParentGroup.Scene.Name, AbsolutePosition);
2522 3090
2523 RemFlag(PrimFlags.Physics); 3091 RemFlag(PrimFlags.Physics);
2524 DoPhysicsPropertyUpdate(false, true); 3092 DoPhysicsPropertyUpdate(false, true);
2525 } 3093 }
@@ -2539,8 +3107,8 @@ namespace OpenSim.Region.Framework.Scenes
2539 } 3107 }
2540 //ParentGroup.RootPart.m_groupPosition = newpos; 3108 //ParentGroup.RootPart.m_groupPosition = newpos;
2541 } 3109 }
2542 3110/*
2543 if (pa != null && ParentID != 0 && ParentGroup != null) 3111 if (pa != null && _parentID != 0 && ParentGroup != null)
2544 { 3112 {
2545 // Special case where a child object is requesting property updates. 3113 // Special case where a child object is requesting property updates.
2546 // This happens when linksets are modified to use flexible links rather than 3114 // This happens when linksets are modified to use flexible links rather than
@@ -2559,7 +3127,7 @@ namespace OpenSim.Region.Framework.Scenes
2559 // m_log.DebugFormat("{0} PhysicsRequestingTerseUpdate child: pos={1}, rot={2}, offPos={3}, offRot={4}", 3127 // m_log.DebugFormat("{0} PhysicsRequestingTerseUpdate child: pos={1}, rot={2}, offPos={3}, offRot={4}",
2560 // "[SCENE OBJECT PART]", pa.Position, pa.Orientation, m_offsetPosition, RotationOffset); 3128 // "[SCENE OBJECT PART]", pa.Position, pa.Orientation, m_offsetPosition, RotationOffset);
2561 } 3129 }
2562 3130*/
2563 ScheduleTerseUpdate(); 3131 ScheduleTerseUpdate();
2564 } 3132 }
2565 3133
@@ -2574,7 +3142,7 @@ namespace OpenSim.Region.Framework.Scenes
2574 //m_log.Debug("prev: " + prevflag.ToString() + " curr: " + Flags.ToString()); 3142 //m_log.Debug("prev: " + prevflag.ToString() + " curr: " + Flags.ToString());
2575 //ScheduleFullUpdate(); 3143 //ScheduleFullUpdate();
2576 } 3144 }
2577 3145
2578 public void RemoveScriptEvents(UUID scriptid) 3146 public void RemoveScriptEvents(UUID scriptid)
2579 { 3147 {
2580 lock (m_scriptEvents) 3148 lock (m_scriptEvents)
@@ -2619,18 +3187,17 @@ namespace OpenSim.Region.Framework.Scenes
2619 3187
2620 if (ParentGroup.Scene != null) 3188 if (ParentGroup.Scene != null)
2621 { 3189 {
2622 scale.X = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.X)); 3190 float minsize = ParentGroup.Scene.m_minNonphys;
2623 scale.Y = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Y)); 3191 float maxsize = ParentGroup.Scene.m_maxNonphys;
2624 scale.Z = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Z));
2625
2626 if (pa != null && pa.IsPhysical) 3192 if (pa != null && pa.IsPhysical)
2627 { 3193 {
2628 scale.X = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.X)); 3194 minsize = ParentGroup.Scene.m_minPhys;
2629 scale.Y = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Y)); 3195 maxsize = ParentGroup.Scene.m_maxPhys;
2630 scale.Z = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Z)); 3196 }
2631 } 3197 scale.X = Util.Clamp(scale.X, minsize, maxsize);
3198 scale.Y = Util.Clamp(scale.Y, minsize, maxsize);
3199 scale.Z = Util.Clamp(scale.Z, minsize, maxsize);
2632 } 3200 }
2633
2634// m_log.DebugFormat("[SCENE OBJECT PART]: Resizing {0} {1} to {2}", Name, LocalId, scale); 3201// m_log.DebugFormat("[SCENE OBJECT PART]: Resizing {0} {1} to {2}", Name, LocalId, scale);
2635 3202
2636 Scale = scale; 3203 Scale = scale;
@@ -2638,58 +3205,68 @@ namespace OpenSim.Region.Framework.Scenes
2638 ParentGroup.HasGroupChanged = true; 3205 ParentGroup.HasGroupChanged = true;
2639 ScheduleFullUpdate(); 3206 ScheduleFullUpdate();
2640 } 3207 }
2641 3208
2642 public void RotLookAt(Quaternion target, float strength, float damping) 3209 public void RotLookAt(Quaternion target, float strength, float damping)
2643 { 3210 {
2644 if (ParentGroup.IsAttachment) 3211 if(ParentGroup.IsDeleted)
3212 return;
3213
3214 // for now we only handle physics case
3215 if(!ParentGroup.UsesPhysics || ParentGroup.IsAttachment)
3216 return;
3217
3218 // physical is SOG
3219 if(ParentGroup.RootPart != this)
2645 { 3220 {
2646 /* 3221 ParentGroup.RotLookAt(target, strength, damping);
2647 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar); 3222 return;
2648 if (avatar != null)
2649 {
2650 Rotate the Av?
2651 } */
2652 } 3223 }
2653 else
2654 {
2655 APIDDamp = damping;
2656 APIDStrength = strength;
2657 APIDTarget = target;
2658 3224
2659 if (APIDStrength <= 0) 3225 APIDDamp = damping;
2660 { 3226 APIDStrength = strength;
2661 m_log.WarnFormat("[SceneObjectPart] Invalid rotation strength {0}",APIDStrength); 3227 APIDTarget = target;
2662 return; 3228
2663 } 3229 if (APIDStrength <= 0)
2664 3230 {
2665 APIDActive = true; 3231 m_log.WarnFormat("[SceneObjectPart] Invalid rotation strength {0}",APIDStrength);
3232 return;
2666 } 3233 }
2667 3234
3235 APIDActive = true;
3236
2668 // Necessary to get the lookat deltas applied 3237 // Necessary to get the lookat deltas applied
2669 ParentGroup.QueueForUpdateCheck(); 3238 ParentGroup.QueueForUpdateCheck();
2670 } 3239 }
2671 3240
2672 public void StartLookAt(Quaternion target, float strength, float damping) 3241 public void StartLookAt(Quaternion target, float strength, float damping)
2673 { 3242 {
2674 RotLookAt(target,strength,damping); 3243 if(ParentGroup.IsDeleted)
2675 } 3244 return;
2676
2677 public void StopLookAt()
2678 {
2679 APIDActive = false;
2680 }
2681 3245
3246 // non physical is done on LSL
3247 if(ParentGroup.IsAttachment || !ParentGroup.UsesPhysics)
3248 return;
2682 3249
3250 // physical is SOG
3251 if(ParentGroup.RootPart != this)
3252 ParentGroup.RotLookAt(target, strength, damping);
3253 else
3254 RotLookAt(target,strength,damping);
3255 }
2683 3256
2684 public void ScheduleFullUpdateIfNone() 3257 public void StopLookAt()
2685 { 3258 {
2686 if (ParentGroup == null) 3259 if(ParentGroup.IsDeleted)
2687 return; 3260 return;
2688 3261
2689// ??? ParentGroup.HasGroupChanged = true; 3262 if(ParentGroup.RootPart != this && ParentGroup.UsesPhysics)
3263 ParentGroup.StopLookAt();
2690 3264
2691 if (UpdateFlag != UpdateRequired.FULL) 3265 // just in case do this always
2692 ScheduleFullUpdate(); 3266 if(APIDActive)
3267 AngularVelocity = Vector3.Zero;
3268
3269 APIDActive = false;
2693 } 3270 }
2694 3271
2695 /// <summary> 3272 /// <summary>
@@ -2701,41 +3278,44 @@ namespace OpenSim.Region.Framework.Scenes
2701 3278
2702 if (ParentGroup == null) 3279 if (ParentGroup == null)
2703 return; 3280 return;
3281 if (ParentGroup.Scene == null)
3282 return;
2704 3283
2705 ParentGroup.QueueForUpdateCheck(); 3284 if(ParentGroup.Scene.GetNumberOfClients() == 0)
3285 return;
2706 3286
2707 int timeNow = Util.UnixTimeSinceEpoch(); 3287 ParentGroup.QueueForUpdateCheck(); // just in case
2708 3288
2709 // If multiple updates are scheduled on the same second, we still need to perform all of them 3289 lock(UpdateFlagLock)
2710 // So we'll force the issue by bumping up the timestamp so that later processing sees these need
2711 // to be performed.
2712 if (timeNow <= TimeStampFull)
2713 {
2714 TimeStampFull += 1;
2715 }
2716 else
2717 { 3290 {
2718 TimeStampFull = (uint)timeNow; 3291 if(UpdateFlag != UpdateRequired.FULL)
2719 } 3292 {
2720 3293 UpdateFlag = UpdateRequired.FULL;
2721 UpdateFlag = UpdateRequired.FULL;
2722 3294
2723 // m_log.DebugFormat( 3295 // m_log.DebugFormat(
2724 // "[SCENE OBJECT PART]: Scheduling full update for {0}, {1} at {2}", 3296 // "[SCENE OBJECT PART]: Scheduling full update for {0}, {1} at {2}",
2725 // UUID, Name, TimeStampFull); 3297 // UUID, Name, TimeStampFull);
2726 3298
2727 if (ParentGroup.Scene != null) 3299 }
2728 ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, true); 3300 }
3301 ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, true);
2729 } 3302 }
2730 3303
2731 /// <summary> 3304 /// <summary>
2732 /// Schedule a terse update for this prim. Terse updates only send position, 3305 /// Schedule a terse update for this prim. Terse updates only send position,
2733 /// rotation, velocity and rotational velocity information. 3306 /// rotation, velocity and rotational velocity information. WRONG!!!!
2734 /// </summary> 3307 /// </summary>
2735 public void ScheduleTerseUpdate() 3308 public void ScheduleTerseUpdate()
2736 { 3309 {
2737 if (ParentGroup == null) 3310 if (ParentGroup == null)
2738 return; 3311 return;
3312 if (ParentGroup.Scene == null)
3313 return;
3314
3315 ParentGroup.HasGroupChanged = true;
3316
3317 if(ParentGroup.Scene.GetNumberOfClients() == 0)
3318 return;
2739 3319
2740 // This was pulled from SceneViewer. Attachments always receive full updates. 3320 // This was pulled from SceneViewer. Attachments always receive full updates.
2741 // This is needed because otherwise if only the root prim changes position, then 3321 // This is needed because otherwise if only the root prim changes position, then
@@ -2746,21 +3326,19 @@ namespace OpenSim.Region.Framework.Scenes
2746 return; 3326 return;
2747 } 3327 }
2748 3328
2749 if (UpdateFlag == UpdateRequired.NONE) 3329 ParentGroup.QueueForUpdateCheck();
3330 lock(UpdateFlagLock)
2750 { 3331 {
2751 ParentGroup.HasGroupChanged = true; 3332 if (UpdateFlag == UpdateRequired.NONE)
2752 ParentGroup.QueueForUpdateCheck(); 3333 {
2753 3334 UpdateFlag = UpdateRequired.TERSE;
2754 TimeStampTerse = (uint) Util.UnixTimeSinceEpoch();
2755 UpdateFlag = UpdateRequired.TERSE;
2756 3335
2757 // m_log.DebugFormat( 3336 // m_log.DebugFormat(
2758 // "[SCENE OBJECT PART]: Scheduling terse update for {0}, {1} at {2}", 3337 // "[SCENE OBJECT PART]: Scheduling terse update for {0}, {1}",
2759 // UUID, Name, TimeStampTerse); 3338 // UUID, Name);
3339 }
2760 } 3340 }
2761 3341 ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, false);
2762 if (ParentGroup.Scene != null)
2763 ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, false);
2764 } 3342 }
2765 3343
2766 public void ScriptSetPhysicsStatus(bool UsePhysics) 3344 public void ScriptSetPhysicsStatus(bool UsePhysics)
@@ -2769,39 +3347,6 @@ namespace OpenSim.Region.Framework.Scenes
2769 } 3347 }
2770 3348
2771 /// <summary> 3349 /// <summary>
2772 /// Set sculpt and mesh data, and tell the physics engine to process the change.
2773 /// </summary>
2774 /// <param name="texture">The mesh itself.</param>
2775/*
2776 public void SculptTextureCallback(AssetBase texture)
2777 {
2778 if (m_shape.SculptEntry)
2779 {
2780 // commented out for sculpt map caching test - null could mean a cached sculpt map has been found
2781 //if (texture != null)
2782 {
2783 if (texture != null)
2784 {
2785// m_log.DebugFormat(
2786// "[SCENE OBJECT PART]: Setting sculpt data for {0} on SculptTextureCallback()", Name);
2787
2788 m_shape.SculptData = texture.Data;
2789 }
2790
2791 PhysicsActor pa = PhysActor;
2792
2793 if (pa != null)
2794 {
2795 // Update the physics actor with the new loaded sculpt data and set the taint signal.
2796 pa.Shape = m_shape;
2797
2798 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
2799 }
2800 }
2801 }
2802 }
2803*/
2804 /// <summary>
2805 /// Send a full update to the client for the given part 3350 /// Send a full update to the client for the given part
2806 /// </summary> 3351 /// </summary>
2807 /// <param name="remoteClient"></param> 3352 /// <param name="remoteClient"></param>
@@ -2812,16 +3357,14 @@ namespace OpenSim.Region.Framework.Scenes
2812 3357
2813// m_log.DebugFormat( 3358// m_log.DebugFormat(
2814// "[SOG]: Sendinging part full update to {0} for {1} {2}", remoteClient.Name, part.Name, part.LocalId); 3359// "[SOG]: Sendinging part full update to {0} for {1} {2}", remoteClient.Name, part.Name, part.LocalId);
2815 3360
2816 if (IsRoot) 3361
3362 if (ParentGroup.IsAttachment)
2817 { 3363 {
2818 if (ParentGroup.IsAttachment) 3364 ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar);
3365 if (sp != null)
2819 { 3366 {
2820 SendFullUpdateToClient(remoteClient, AttachedPos); 3367 sp.SendAttachmentUpdate(this, UpdateRequired.FULL);
2821 }
2822 else
2823 {
2824 SendFullUpdateToClient(remoteClient, AbsolutePosition);
2825 } 3368 }
2826 } 3369 }
2827 else 3370 else
@@ -2833,42 +3376,68 @@ namespace OpenSim.Region.Framework.Scenes
2833 /// <summary> 3376 /// <summary>
2834 /// Send a full update for this part to all clients. 3377 /// Send a full update for this part to all clients.
2835 /// </summary> 3378 /// </summary>
2836 public void SendFullUpdateToAllClients() 3379 public void SendFullUpdateToAllClientsInternal()
2837 { 3380 {
2838 if (ParentGroup == null) 3381 if (ParentGroup == null)
2839 return; 3382 return;
2840 3383
3384 // Update the "last" values
3385 lock(UpdateFlagLock)
3386 {
3387 m_lastPosition = AbsolutePosition;
3388 m_lastRotation = RotationOffset;
3389 m_lastVelocity = Velocity;
3390 m_lastAcceleration = Acceleration;
3391 m_lastAngularVelocity = AngularVelocity;
3392 m_lastUpdateSentTime = Util.GetTimeStampMS();
3393 }
3394
2841 ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) 3395 ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
2842 { 3396 {
2843 SendFullUpdate(avatar.ControllingClient); 3397 SendFullUpdate(avatar.ControllingClient);
2844 }); 3398 });
2845 } 3399 }
2846 3400
2847 /// <summary> 3401 public void SendFullUpdateToAllClients()
2848 /// Sends a full update to the client
2849 /// </summary>
2850 /// <param name="remoteClient"></param>
2851 public void SendFullUpdateToClient(IClientAPI remoteClient)
2852 { 3402 {
2853 SendFullUpdateToClient(remoteClient, OffsetPosition); 3403 if (ParentGroup == null)
3404 return;
3405
3406 // Update the "last" values
3407 lock(UpdateFlagLock)
3408 {
3409 m_lastPosition = AbsolutePosition;
3410 m_lastRotation = RotationOffset;
3411 m_lastVelocity = Velocity;
3412 m_lastAcceleration = Acceleration;
3413 m_lastAngularVelocity = AngularVelocity;
3414 m_lastUpdateSentTime = Util.GetTimeStampMS();
3415 }
3416
3417 if (ParentGroup.IsAttachment)
3418 {
3419 ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar);
3420 if (sp != null)
3421 {
3422 sp.SendAttachmentUpdate(this, UpdateRequired.FULL);
3423 }
3424 }
3425 else
3426 {
3427 ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
3428 {
3429 SendFullUpdate(avatar.ControllingClient);
3430 });
3431 }
2854 } 3432 }
2855 3433
2856 /// <summary> 3434 /// <summary>
2857 /// Sends a full update to the client 3435 /// Sends a full update to the client
2858 /// </summary> 3436 /// </summary>
2859 /// <param name="remoteClient"></param> 3437 /// <param name="remoteClient"></param>
2860 /// <param name="lPos"></param> 3438 public void SendFullUpdateToClient(IClientAPI remoteClient)
2861 public void SendFullUpdateToClient(IClientAPI remoteClient, Vector3 lPos)
2862 { 3439 {
2863 if (ParentGroup == null) 3440 if (ParentGroup == null || ParentGroup.IsDeleted)
2864 return;
2865
2866 // Suppress full updates during attachment editing
2867 //
2868 if (ParentGroup.IsSelected && ParentGroup.IsAttachment)
2869 return;
2870
2871 if (ParentGroup.IsDeleted)
2872 return; 3441 return;
2873 3442
2874 if (ParentGroup.IsAttachment 3443 if (ParentGroup.IsAttachment
@@ -2889,62 +3458,212 @@ namespace OpenSim.Region.Framework.Scenes
2889 ParentGroup.Scene.StatsReporter.AddObjectUpdates(1); 3458 ParentGroup.Scene.StatsReporter.AddObjectUpdates(1);
2890 } 3459 }
2891 3460
3461 private const float ROTATION_TOLERANCE = 0.01f;
3462 private const float VELOCITY_TOLERANCE = 0.1f;
3463 private const float ANGVELOCITY_TOLERANCE = 0.005f;
3464 private const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
3465 private const double TIME_MS_TOLERANCE = 200.0; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
3466
2892 /// <summary> 3467 /// <summary>
2893 /// Tell all the prims which have had updates scheduled 3468 /// Tell all the prims which have had updates scheduled
2894 /// </summary> 3469 /// </summary>
2895 public void SendScheduledUpdates() 3470 public void SendScheduledUpdates(double now)
2896 { 3471 {
2897 const float ROTATION_TOLERANCE = 0.01f; 3472 bool sendterse = false;
2898 const float VELOCITY_TOLERANCE = 0.001f; 3473 bool sendfull = false;
2899 const float POSITION_TOLERANCE = 0.05f;
2900 const int TIME_MS_TOLERANCE = 3000;
2901 3474
2902 switch (UpdateFlag) 3475 lock(UpdateFlagLock)
2903 { 3476 {
2904 case UpdateRequired.TERSE: 3477 switch (UpdateFlag)
2905 { 3478 {
2906 ClearUpdateSchedule(); 3479 case UpdateRequired.NONE:
2907 // Throw away duplicate or insignificant updates 3480 break;
2908 if (!RotationOffset.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE) || 3481
2909 !Acceleration.Equals(m_lastAcceleration) || 3482 case UpdateRequired.TERSE:
2910 !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) || 3483 sendterse = true;
2911 Velocity.ApproxEquals(Vector3.Zero, VELOCITY_TOLERANCE) || 3484
2912 !AngularVelocity.ApproxEquals(m_lastAngularVelocity, VELOCITY_TOLERANCE) || 3485 Vector3 curvel = Velocity;
2913 !OffsetPosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) || 3486 Vector3 curacc = Acceleration;
2914 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE) 3487 Vector3 angvel = AngularVelocity;
2915 { 3488
2916 SendTerseUpdateToAllClients(); 3489 while(true) // just to avoid ugly goto
3490 {
3491 double elapsed = now - m_lastUpdateSentTime;
3492 if (elapsed > TIME_MS_TOLERANCE)
3493 break;
3494
3495 if( Math.Abs(curacc.X - m_lastAcceleration.X) > VELOCITY_TOLERANCE ||
3496 Math.Abs(curacc.Y - m_lastAcceleration.Y) > VELOCITY_TOLERANCE ||
3497 Math.Abs(curacc.Z - m_lastAcceleration.Z) > VELOCITY_TOLERANCE)
3498 break;
3499
3500 if( Math.Abs(curvel.X - m_lastVelocity.X) > VELOCITY_TOLERANCE ||
3501 Math.Abs(curvel.Y - m_lastVelocity.Y) > VELOCITY_TOLERANCE ||
3502 Math.Abs(curvel.Z - m_lastVelocity.Z) > VELOCITY_TOLERANCE)
3503 break;
3504
3505 float vx = Math.Abs(curvel.X);
3506 if(vx > 128.0)
3507 break;
3508 float vy = Math.Abs(curvel.Y);
3509 if(vy > 128.0)
3510 break;
3511 float vz = Math.Abs(curvel.Z);
3512 if(vz > 128.0)
3513 break;
3514
3515 if (
3516 vx < VELOCITY_TOLERANCE &&
3517 vy < VELOCITY_TOLERANCE &&
3518 vz < VELOCITY_TOLERANCE
3519 )
3520 {
3521 if(!AbsolutePosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE))
3522 break;
3523
3524 if (vx < 1e-4 &&
3525 vy < 1e-4 &&
3526 vz < 1e-4 &&
3527 (
3528 Math.Abs(m_lastVelocity.X) > 1e-4 ||
3529 Math.Abs(m_lastVelocity.Y) > 1e-4 ||
3530 Math.Abs(m_lastVelocity.Z) > 1e-4
3531 ))
3532 break;
3533 }
3534
3535 if( Math.Abs(angvel.X - m_lastAngularVelocity.X) > ANGVELOCITY_TOLERANCE ||
3536 Math.Abs(angvel.Y - m_lastAngularVelocity.Y) > ANGVELOCITY_TOLERANCE ||
3537 Math.Abs(angvel.Z - m_lastAngularVelocity.Z) > ANGVELOCITY_TOLERANCE)
3538 break;
3539
3540 // viewer interpolators have a limit of 64rad/s
3541 float ax = Math.Abs(angvel.X);
3542 if(ax > 64.0)
3543 break;
3544 float ay = Math.Abs(angvel.Y);
3545 if(ay > 64.0)
3546 break;
3547 float az = Math.Abs(angvel.Z);
3548 if(az > 64.0)
3549 break;
3550
3551 if (
3552 ax < ANGVELOCITY_TOLERANCE &&
3553 ay < ANGVELOCITY_TOLERANCE &&
3554 az < ANGVELOCITY_TOLERANCE &&
3555 !RotationOffset.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE)
3556 )
3557 break;
3558
3559 sendterse = false;
3560 break;
3561 }
3562
3563 if(sendterse)
3564 {
3565 // Update the "last" values
3566 m_lastPosition = AbsolutePosition;
3567 m_lastRotation = RotationOffset;
3568 m_lastVelocity = curvel;
3569 m_lastAcceleration = curacc;
3570 m_lastAngularVelocity = angvel;
3571 m_lastUpdateSentTime = now;
3572 ClearUpdateSchedule();
3573 }
3574 break;
2917 3575
2918 // Update the "last" values 3576 case UpdateRequired.FULL:
2919 m_lastPosition = OffsetPosition; 3577 m_lastPosition = AbsolutePosition;
2920 m_lastRotation = RotationOffset; 3578 m_lastRotation = RotationOffset;
2921 m_lastVelocity = Velocity; 3579 m_lastVelocity = Velocity;
2922 m_lastAcceleration = Acceleration; 3580 m_lastAcceleration = Acceleration;
2923 m_lastAngularVelocity = AngularVelocity; 3581 m_lastAngularVelocity = AngularVelocity;
2924 m_lastTerseSent = Environment.TickCount; 3582 m_lastUpdateSentTime = now;
2925 } 3583 ClearUpdateSchedule();
2926 break; 3584 sendfull = true;
3585 break;
2927 } 3586 }
2928 case UpdateRequired.FULL: 3587 }
3588 if(sendterse)
3589 {
3590 ParentGroup.Scene.ForEachClient(delegate(IClientAPI client)
2929 { 3591 {
2930 ClearUpdateSchedule(); 3592 SendTerseUpdateToClient(client);
2931 SendFullUpdateToAllClients(); 3593 });
2932 break; 3594 }
2933 } 3595 else if(sendfull)
3596 {
3597 ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
3598 {
3599 SendFullUpdate(avatar.ControllingClient);
3600 });
2934 } 3601 }
2935 } 3602 }
2936 3603
2937 /// <summary> 3604 /// <summary>
2938 /// Send a terse update to all clients 3605 /// Send a terse update to all clients
2939 /// </summary> 3606 /// </summary>
2940 public void SendTerseUpdateToAllClients() 3607 public void SendTerseUpdateToAllClientsInternal()
2941 { 3608 {
3609 if (ParentGroup == null || ParentGroup.Scene == null)
3610 return;
3611 lock(UpdateFlagLock)
3612 {
3613 if(UpdateFlag != UpdateRequired.NONE)
3614 return;
3615
3616 // Update the "last" values
3617 m_lastPosition = AbsolutePosition;
3618 m_lastRotation = RotationOffset;
3619 m_lastVelocity = Velocity;
3620 m_lastAcceleration = Acceleration;
3621 m_lastAngularVelocity = AngularVelocity;
3622 m_lastUpdateSentTime = Util.GetTimeStampMS();
3623 }
3624
2942 ParentGroup.Scene.ForEachClient(delegate(IClientAPI client) 3625 ParentGroup.Scene.ForEachClient(delegate(IClientAPI client)
2943 { 3626 {
2944 SendTerseUpdateToClient(client); 3627 SendTerseUpdateToClient(client);
2945 }); 3628 });
2946 } 3629 }
2947 3630
3631 public void SendTerseUpdateToAllClients()
3632 {
3633 if (ParentGroup == null || ParentGroup.Scene == null)
3634 return;
3635
3636 lock(UpdateFlagLock)
3637 {
3638 if(UpdateFlag != UpdateRequired.NONE)
3639 return;
3640
3641 // Update the "last" values
3642 m_lastPosition = AbsolutePosition;
3643 m_lastRotation = RotationOffset;
3644 m_lastVelocity = Velocity;
3645 m_lastAcceleration = Acceleration;
3646 m_lastAngularVelocity = AngularVelocity;
3647 m_lastUpdateSentTime = Util.GetTimeStampMS();
3648 }
3649
3650 if (ParentGroup.IsAttachment)
3651 {
3652 ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar);
3653 if (sp != null)
3654 {
3655 sp.SendAttachmentUpdate(this, UpdateRequired.TERSE);
3656 }
3657 }
3658 else
3659 {
3660 ParentGroup.Scene.ForEachClient(delegate(IClientAPI client)
3661 {
3662 SendTerseUpdateToClient(client);
3663 });
3664 }
3665 }
3666
2948 public void SetAxisRotation(int axis, int rotate) 3667 public void SetAxisRotation(int axis, int rotate)
2949 { 3668 {
2950 ParentGroup.SetAxisRotation(axis, rotate); 3669 ParentGroup.SetAxisRotation(axis, rotate);
@@ -2962,10 +3681,13 @@ namespace OpenSim.Region.Framework.Scenes
2962 3681
2963 public void SetBuoyancy(float fvalue) 3682 public void SetBuoyancy(float fvalue)
2964 { 3683 {
2965 PhysicsActor pa = PhysActor; 3684 Buoyancy = fvalue;
2966 3685/*
2967 if (pa != null) 3686 if (PhysActor != null)
2968 pa.Buoyancy = fvalue; 3687 {
3688 PhysActor.Buoyancy = fvalue;
3689 }
3690 */
2969 } 3691 }
2970 3692
2971 public void SetDieAtEdge(bool p) 3693 public void SetDieAtEdge(bool p)
@@ -2981,47 +3703,123 @@ namespace OpenSim.Region.Framework.Scenes
2981 PhysicsActor pa = PhysActor; 3703 PhysicsActor pa = PhysActor;
2982 3704
2983 if (pa != null) 3705 if (pa != null)
2984 pa.FloatOnWater = floatYN == 1; 3706 pa.FloatOnWater = (floatYN == 1);
2985 } 3707 }
2986 3708
2987 public void SetForce(Vector3 force) 3709 public void SetForce(Vector3 force)
2988 { 3710 {
2989 PhysicsActor pa = PhysActor; 3711 Force = force;
3712 }
2990 3713
2991 if (pa != null) 3714 public PhysicsInertiaData PhysicsInertia
2992 pa.Force = force; 3715 {
3716 get
3717 {
3718 return m_physicsInertia;
3719 }
3720 set
3721 {
3722 m_physicsInertia = value;
3723 }
3724 }
3725
3726 public SOPVehicle VehicleParams
3727 {
3728 get
3729 {
3730 return m_vehicleParams;
3731 }
3732 set
3733 {
3734 m_vehicleParams = value;
3735
3736 }
3737 }
3738
3739 public int VehicleType
3740 {
3741 get
3742 {
3743 if (m_vehicleParams == null)
3744 return (int)Vehicle.TYPE_NONE;
3745 else
3746 return (int)m_vehicleParams.Type;
3747 }
3748 set
3749 {
3750 SetVehicleType(value);
3751 }
2993 } 3752 }
2994 3753
2995 public void SetVehicleType(int type) 3754 public void SetVehicleType(int type)
2996 { 3755 {
2997 PhysicsActor pa = PhysActor; 3756 m_vehicleParams = null;
2998 3757
2999 if (pa != null) 3758 if (type == (int)Vehicle.TYPE_NONE)
3000 pa.VehicleType = type; 3759 {
3760 if (_parentID ==0 && PhysActor != null)
3761 PhysActor.VehicleType = (int)Vehicle.TYPE_NONE;
3762 return;
3763 }
3764 m_vehicleParams = new SOPVehicle();
3765 m_vehicleParams.ProcessTypeChange((Vehicle)type);
3766 {
3767 if (_parentID ==0 && PhysActor != null)
3768 PhysActor.VehicleType = type;
3769 return;
3770 }
3771 }
3772
3773 public void SetVehicleFlags(int param, bool remove)
3774 {
3775 if (m_vehicleParams == null)
3776 return;
3777
3778 m_vehicleParams.ProcessVehicleFlags(param, remove);
3779
3780 if (_parentID == 0 && PhysActor != null)
3781 {
3782 PhysActor.VehicleFlags(param, remove);
3783 }
3001 } 3784 }
3002 3785
3003 public void SetVehicleFloatParam(int param, float value) 3786 public void SetVehicleFloatParam(int param, float value)
3004 { 3787 {
3005 PhysicsActor pa = PhysActor; 3788 if (m_vehicleParams == null)
3789 return;
3006 3790
3007 if (pa != null) 3791 m_vehicleParams.ProcessFloatVehicleParam((Vehicle)param, value);
3008 pa.VehicleFloatParam(param, value); 3792
3793 if (_parentID == 0 && PhysActor != null)
3794 {
3795 PhysActor.VehicleFloatParam(param, value);
3796 }
3009 } 3797 }
3010 3798
3011 public void SetVehicleVectorParam(int param, Vector3 value) 3799 public void SetVehicleVectorParam(int param, Vector3 value)
3012 { 3800 {
3013 PhysicsActor pa = PhysActor; 3801 if (m_vehicleParams == null)
3802 return;
3014 3803
3015 if (pa != null) 3804 m_vehicleParams.ProcessVectorVehicleParam((Vehicle)param, value);
3016 pa.VehicleVectorParam(param, value); 3805
3806 if (_parentID == 0 && PhysActor != null)
3807 {
3808 PhysActor.VehicleVectorParam(param, value);
3809 }
3017 } 3810 }
3018 3811
3019 public void SetVehicleRotationParam(int param, Quaternion rotation) 3812 public void SetVehicleRotationParam(int param, Quaternion rotation)
3020 { 3813 {
3021 PhysicsActor pa = PhysActor; 3814 if (m_vehicleParams == null)
3815 return;
3022 3816
3023 if (pa != null) 3817 m_vehicleParams.ProcessRotationVehicleParam((Vehicle)param, rotation);
3024 pa.VehicleRotationParam(param, rotation); 3818
3819 if (_parentID == 0 && PhysActor != null)
3820 {
3821 PhysActor.VehicleRotationParam(param, rotation);
3822 }
3025 } 3823 }
3026 3824
3027 /// <summary> 3825 /// <summary>
@@ -3041,7 +3839,8 @@ namespace OpenSim.Region.Framework.Scenes
3041 Byte[] buf = Shape.Textures.GetBytes(); 3839 Byte[] buf = Shape.Textures.GetBytes();
3042 Primitive.TextureEntry tex = new Primitive.TextureEntry(buf, 0, buf.Length); 3840 Primitive.TextureEntry tex = new Primitive.TextureEntry(buf, 0, buf.Length);
3043 Color4 texcolor; 3841 Color4 texcolor;
3044 if (face >= 0 && face < GetNumberOfSides()) 3842 int nsides = GetNumberOfSides();
3843 if (face >= 0 && face < nsides)
3045 { 3844 {
3046 texcolor = tex.CreateFace((uint)face).RGBA; 3845 texcolor = tex.CreateFace((uint)face).RGBA;
3047 texcolor.R = clippedColor.X; 3846 texcolor.R = clippedColor.X;
@@ -3057,7 +3856,7 @@ namespace OpenSim.Region.Framework.Scenes
3057 } 3856 }
3058 else if (face == ALL_SIDES) 3857 else if (face == ALL_SIDES)
3059 { 3858 {
3060 for (uint i = 0; i < GetNumberOfSides(); i++) 3859 for (uint i = 0; i < nsides; i++)
3061 { 3860 {
3062 if (tex.FaceTextures[i] != null) 3861 if (tex.FaceTextures[i] != null)
3063 { 3862 {
@@ -3093,64 +3892,110 @@ namespace OpenSim.Region.Framework.Scenes
3093 public int GetNumberOfSides() 3892 public int GetNumberOfSides()
3094 { 3893 {
3095 int ret = 0; 3894 int ret = 0;
3096 bool hasCut;
3097 bool hasHollow;
3098 bool hasDimple;
3099 bool hasProfileCut;
3100 3895
3101 PrimType primType = GetPrimType(); 3896 if(Shape.SculptEntry)
3102 HasCutHollowDimpleProfileCut(primType, Shape, out hasCut, out hasHollow, out hasDimple, out hasProfileCut); 3897 {
3898 if (Shape.SculptType != (byte)SculptType.Mesh)
3899 return 1; // sculp
3900
3901 //hack to detect new upload with faces data enconded on pbs
3902 if ((Shape.ProfileCurve & 0xf0) != (byte)HollowShape.Triangle)
3903 // old broken upload TODO
3904 return 8;
3905 }
3906
3907 PrimType primType = GetPrimType(true);
3103 3908
3104 switch (primType) 3909 switch (primType)
3105 { 3910 {
3106 case PrimType.BOX: 3911 case PrimType.BOX:
3107 ret = 6; 3912 ret = 6;
3108 if (hasCut) ret += 2; 3913 if (Shape.ProfileBegin > 0 || Shape.ProfileEnd > 0) // cut case
3109 if (hasHollow) ret += 1; 3914 {
3110 break; 3915 // removed sides
3111 case PrimType.CYLINDER: 3916 int cut = (Shape.ProfileEnd + Shape.ProfileBegin);
3112 ret = 3; 3917 if(cut > 50000) // range is 0 to 50000
3113 if (hasCut) ret += 2; 3918 cut = 50000;
3114 if (hasHollow) ret += 1; 3919 cut /= 12500; // ie 1/4
3920 ret -= cut;
3921 ret += 2; // both cut faces
3922 }
3115 break; 3923 break;
3116 case PrimType.PRISM: 3924 case PrimType.PRISM:
3117 ret = 5; 3925 ret = 5;
3118 if (hasCut) ret += 2; 3926 if (Shape.ProfileBegin > 0 || Shape.ProfileEnd > 0) // cut case
3119 if (hasHollow) ret += 1; 3927 {
3928 // removed faces
3929 int cut = (Shape.ProfileEnd + Shape.ProfileBegin);
3930 if(cut >= 16667 ) // ie 1/3
3931 ret--;
3932 if(cut >= 33333 ) // ie 2/3
3933 ret--;
3934 ret += 2; // both cut faces
3935 }
3936 break;
3937 case PrimType.CYLINDER:
3938 ret = 3;
3939 if (Shape.ProfileBegin > 0 || Shape.ProfileEnd > 0) // cut
3940 ret += 2;
3120 break; 3941 break;
3121 case PrimType.SPHERE: 3942 case PrimType.SPHERE:
3122 ret = 1; 3943 ret = 1;
3123 if (hasCut) ret += 2; 3944 // cut faces exist if cut or skew or unequal twist limits
3124 if (hasDimple) ret += 2; 3945 if (Shape.PathBegin > 0 || Shape.PathEnd > 0 || Shape.PathSkew != 0 || (Shape.PathTwistBegin != Shape.PathTwist))
3125 if (hasHollow) ret += 1; 3946 ret += 2;
3947 if (Shape.ProfileBegin > 0 || Shape.ProfileEnd > 0 || Shape.ProfileHollow > 0) // dimple faces also if hollow
3948 ret += 2;
3126 break; 3949 break;
3127 case PrimType.TORUS: 3950 case PrimType.TORUS:
3128 ret = 1; 3951 ret = 1;
3129 if (hasCut) ret += 2; 3952 if (Shape.PathBegin > 0 || Shape.PathEnd > 0 || Shape.PathSkew != 0
3130 if (hasProfileCut) ret += 2; 3953 || Shape.PathTaperX != 0 || Shape.PathTaperY != 0 || Shape.PathRevolutions > 0
3131 if (hasHollow) ret += 1; 3954 || Shape.PathRadiusOffset != 0 || (Shape.PathTwistBegin != Shape.PathTwist))
3955 ret += 2;
3956 if (Shape.ProfileBegin > 0 || Shape.ProfileEnd > 0) // profile cut
3957 ret += 2;
3132 break; 3958 break;
3133 case PrimType.TUBE: 3959 case PrimType.TUBE:
3134 ret = 4; 3960 ret = 4;
3135 if (hasCut) ret += 2; 3961 if (Shape.PathBegin > 0 || Shape.PathEnd > 0 || Shape.PathSkew != 0
3136 if (hasProfileCut) ret += 2; 3962 || Shape.PathTaperX != 0 || Shape.PathTaperY != 0 || Shape.PathRevolutions > 0
3137 if (hasHollow) ret += 1; 3963 || Shape.PathRadiusOffset != 0 || (Shape.PathTwistBegin != Shape.PathTwist))
3964 ret += 2;
3965 if (Shape.ProfileBegin > 0 || Shape.ProfileEnd > 0) // profile cut
3966 {
3967 // removed sides
3968 int cut = (Shape.ProfileEnd + Shape.ProfileBegin);
3969 if(cut > 50000)
3970 cut = 50000;
3971 cut /= 12500;
3972 ret -= cut;
3973 ret += 2; // both cut faces
3974 }
3138 break; 3975 break;
3139 case PrimType.RING: 3976 case PrimType.RING:
3140 ret = 3; 3977 ret = 3;
3141 if (hasCut) ret += 2; 3978 if (Shape.PathBegin > 0 || Shape.PathEnd > 0 || Shape.PathSkew != 0
3142 if (hasProfileCut) ret += 2; 3979 || Shape.PathTaperX != 0 || Shape.PathTaperY != 0 || Shape.PathRevolutions > 0
3143 if (hasHollow) ret += 1; 3980 || Shape.PathRadiusOffset != 0 || (Shape.PathTwistBegin != Shape.PathTwist))
3144 break; 3981 ret += 2;
3145 case PrimType.SCULPT: 3982 if (Shape.ProfileBegin > 0 || Shape.ProfileEnd > 0) // profile cut
3146 // Special mesh handling 3983 {
3147 if (Shape.SculptType == (byte)SculptType.Mesh) 3984 // removed faces
3148 ret = 8; // if it's a mesh then max 8 faces 3985 int cut = (Shape.ProfileEnd + Shape.ProfileBegin);
3149 else 3986 if(cut >= 16667 )
3150 ret = 1; // if it's a sculpt then max 1 face 3987 ret--;
3988 if(cut >= 33333 )
3989 ret--;
3990 ret += 2; // both cut faces
3991 }
3151 break; 3992 break;
3152 } 3993 }
3153 3994
3995 // hollow face commum to all
3996 if (Shape.ProfileHollow > 0)
3997 ret += 1;
3998
3154 return ret; 3999 return ret;
3155 } 4000 }
3156 4001
@@ -3159,11 +4004,11 @@ namespace OpenSim.Region.Framework.Scenes
3159 /// </summary> 4004 /// </summary>
3160 /// <param name="primShape"></param> 4005 /// <param name="primShape"></param>
3161 /// <returns></returns> 4006 /// <returns></returns>
3162 public PrimType GetPrimType() 4007 public PrimType GetPrimType(bool ignoreSculpt = false)
3163 { 4008 {
3164 if (Shape.SculptEntry) 4009 if (Shape.SculptEntry && !ignoreSculpt)
3165 return PrimType.SCULPT; 4010 return PrimType.SCULPT;
3166 4011
3167 if ((Shape.ProfileCurve & 0x07) == (byte)ProfileShape.Square) 4012 if ((Shape.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
3168 { 4013 {
3169 if (Shape.PathCurve == (byte)Extrusion.Straight) 4014 if (Shape.PathCurve == (byte)Extrusion.Straight)
@@ -3173,7 +4018,7 @@ namespace OpenSim.Region.Framework.Scenes
3173 } 4018 }
3174 else if ((Shape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle) 4019 else if ((Shape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
3175 { 4020 {
3176 if (Shape.PathCurve == (byte)Extrusion.Straight) 4021 if (Shape.PathCurve == (byte)Extrusion.Straight || Shape.PathCurve == (byte)Extrusion.Flexible)
3177 return PrimType.CYLINDER; 4022 return PrimType.CYLINDER;
3178 // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits 4023 // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
3179 else if (Shape.PathCurve == (byte)Extrusion.Curve1) 4024 else if (Shape.PathCurve == (byte)Extrusion.Curve1)
@@ -3186,48 +4031,13 @@ namespace OpenSim.Region.Framework.Scenes
3186 } 4031 }
3187 else if ((Shape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle) 4032 else if ((Shape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
3188 { 4033 {
3189 if (Shape.PathCurve == (byte)Extrusion.Straight) 4034 if (Shape.PathCurve == (byte)Extrusion.Straight || Shape.PathCurve == (byte)Extrusion.Flexible)
3190 return PrimType.PRISM; 4035 return PrimType.PRISM;
3191 else if (Shape.PathCurve == (byte)Extrusion.Curve1) 4036 else if (Shape.PathCurve == (byte)Extrusion.Curve1)
3192 return PrimType.RING; 4037 return PrimType.RING;
3193 } 4038 }
3194
3195 return PrimType.BOX;
3196 }
3197
3198 /// <summary>
3199 /// Tell us if this object has cut, hollow, dimple, and other factors affecting the number of faces
3200 /// </summary>
3201 /// <param name="primType"></param>
3202 /// <param name="shape"></param>
3203 /// <param name="hasCut"></param>
3204 /// <param name="hasHollow"></param>
3205 /// <param name="hasDimple"></param>
3206 /// <param name="hasProfileCut"></param>
3207 protected static void HasCutHollowDimpleProfileCut(PrimType primType, PrimitiveBaseShape shape, out bool hasCut, out bool hasHollow,
3208 out bool hasDimple, out bool hasProfileCut)
3209 {
3210 if (primType == PrimType.BOX
3211 ||
3212 primType == PrimType.CYLINDER
3213 ||
3214 primType == PrimType.PRISM)
3215
3216 hasCut = (shape.ProfileBegin > 0) || (shape.ProfileEnd > 0);
3217 else
3218 hasCut = (shape.PathBegin > 0) || (shape.PathEnd > 0);
3219
3220 hasHollow = shape.ProfileHollow > 0;
3221 hasDimple = (shape.ProfileBegin > 0) || (shape.ProfileEnd > 0); // taken from llSetPrimitiveParms
3222 hasProfileCut = hasDimple; // is it the same thing?
3223 }
3224
3225 public void SetVehicleFlags(int param, bool remove)
3226 {
3227 PhysicsActor pa = PhysActor;
3228 4039
3229 if (pa != null) 4040 return PrimType.BOX;
3230 pa.VehicleFlags(param, remove);
3231 } 4041 }
3232 4042
3233 public void SetGroup(UUID groupID, IClientAPI client) 4043 public void SetGroup(UUID groupID, IClientAPI client)
@@ -3238,8 +4048,8 @@ namespace OpenSim.Region.Framework.Scenes
3238// Name, groupID, OwnerID); 4048// Name, groupID, OwnerID);
3239 4049
3240 GroupID = groupID; 4050 GroupID = groupID;
3241 if (client != null) 4051// if (client != null)
3242 SendPropertiesToClient(client); 4052// SendPropertiesToClient(client);
3243 UpdateFlag = UpdateRequired.FULL; 4053 UpdateFlag = UpdateRequired.FULL;
3244 } 4054 }
3245 4055
@@ -3263,7 +4073,7 @@ namespace OpenSim.Region.Framework.Scenes
3263 4073
3264 if (pa != null) 4074 if (pa != null)
3265 { 4075 {
3266 pa.LockAngularMotion(RotationAxis); 4076 pa.LockAngularMotion(RotationAxisLocks);
3267 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa); 4077 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
3268 } 4078 }
3269 } 4079 }
@@ -3276,7 +4086,7 @@ namespace OpenSim.Region.Framework.Scenes
3276 public void SetScriptEvents(UUID scriptid, int events) 4086 public void SetScriptEvents(UUID scriptid, int events)
3277 { 4087 {
3278// m_log.DebugFormat( 4088// m_log.DebugFormat(
3279// "[SCENE OBJECT PART]: Set script events for script with id {0} on {1}/{2} to {3} in {4}", 4089// "[SCENE OBJECT PART]: Set script events for script with id {0} on {1}/{2} to {3} in {4}",
3280// scriptid, Name, ParentGroup.Name, events, ParentGroup.Scene.Name); 4090// scriptid, Name, ParentGroup.Name, events, ParentGroup.Scene.Name);
3281 4091
3282 // scriptEvents oldparts; 4092 // scriptEvents oldparts;
@@ -3313,7 +4123,7 @@ namespace OpenSim.Region.Framework.Scenes
3313 ScheduleFullUpdate(); 4123 ScheduleFullUpdate();
3314 } 4124 }
3315 } 4125 }
3316 4126
3317 /// <summary> 4127 /// <summary>
3318 /// Set the text displayed for this part. 4128 /// Set the text displayed for this part.
3319 /// </summary> 4129 /// </summary>
@@ -3334,67 +4144,16 @@ namespace OpenSim.Region.Framework.Scenes
3334 ParentGroup.StopMoveToTarget(); 4144 ParentGroup.StopMoveToTarget();
3335 } 4145 }
3336 4146
3337 public void StoreUndoState() 4147 public void StoreUndoState(ObjectChangeType change)
3338 { 4148 {
3339 StoreUndoState(false); 4149 lock (m_UndoLock)
3340 }
3341
3342 public void StoreUndoState(bool forGroup)
3343 {
3344 if (ParentGroup == null || ParentGroup.Scene == null)
3345 return;
3346
3347 if (Undoing)
3348 { 4150 {
3349// m_log.DebugFormat( 4151 if (m_UndoRedo == null)
3350// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId); 4152 m_UndoRedo = new UndoRedoState(5);
3351 return;
3352 }
3353
3354 if (IgnoreUndoUpdate)
3355 {
3356// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId);
3357 return;
3358 }
3359 4153
3360 lock (m_undo) 4154 if (!Undoing && !IgnoreUndoUpdate && ParentGroup != null) // just to read better - undo is in progress, or suspended
3361 {
3362 if (m_undo.Count > 0)
3363 { 4155 {
3364 UndoState last = m_undo[m_undo.Count - 1]; 4156 m_UndoRedo.StoreUndo(this, change);
3365 if (last != null)
3366 {
3367 // TODO: May need to fix for group comparison
3368 if (last.Compare(this))
3369 {
3370// m_log.DebugFormat(
3371// "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}",
3372// Name, LocalId, m_undo.Count);
3373
3374 return;
3375 }
3376 }
3377 }
3378
3379// m_log.DebugFormat(
3380// "[SCENE OBJECT PART]: Storing undo state for {0} {1}, forGroup {2}, initial stack size {3}",
3381// Name, LocalId, forGroup, m_undo.Count);
3382
3383 if (ParentGroup.Scene.MaxUndoCount > 0)
3384 {
3385 UndoState nUndo = new UndoState(this, forGroup);
3386
3387 m_undo.Add(nUndo);
3388
3389 if (m_undo.Count > ParentGroup.Scene.MaxUndoCount)
3390 m_undo.RemoveAt(0);
3391
3392 if (m_redo.Count > 0)
3393 m_redo.Clear();
3394
3395// m_log.DebugFormat(
3396// "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}",
3397// Name, LocalId, forGroup, m_undo.Count);
3398 } 4157 }
3399 } 4158 }
3400 } 4159 }
@@ -3406,186 +4165,47 @@ namespace OpenSim.Region.Framework.Scenes
3406 { 4165 {
3407 get 4166 get
3408 { 4167 {
3409 lock (m_undo) 4168 if (m_UndoRedo == null)
3410 return m_undo.Count; 4169 return 0;
4170 return m_UndoRedo.Count;
3411 } 4171 }
3412 } 4172 }
3413 4173
3414 public void Undo() 4174 public void Undo()
3415 { 4175 {
3416 lock (m_undo) 4176 lock (m_UndoLock)
3417 { 4177 {
3418// m_log.DebugFormat( 4178 if (m_UndoRedo == null || Undoing || ParentGroup == null)
3419// "[SCENE OBJECT PART]: Handling undo request for {0} {1}, stack size {2}", 4179 return;
3420// Name, LocalId, m_undo.Count);
3421
3422 if (m_undo.Count > 0)
3423 {
3424 UndoState goback = m_undo[m_undo.Count - 1];
3425 m_undo.RemoveAt(m_undo.Count - 1);
3426
3427 UndoState nUndo = null;
3428
3429 if (ParentGroup.Scene.MaxUndoCount > 0)
3430 {
3431 nUndo = new UndoState(this, goback.ForGroup);
3432 }
3433
3434 goback.PlaybackState(this);
3435
3436 if (nUndo != null)
3437 {
3438 m_redo.Add(nUndo);
3439
3440 if (m_redo.Count > ParentGroup.Scene.MaxUndoCount)
3441 m_redo.RemoveAt(0);
3442 }
3443 }
3444 4180
3445// m_log.DebugFormat( 4181 Undoing = true;
3446// "[SCENE OBJECT PART]: Handled undo request for {0} {1}, stack size now {2}", 4182 m_UndoRedo.Undo(this);
3447// Name, LocalId, m_undo.Count); 4183 Undoing = false;
3448 } 4184 }
3449 } 4185 }
3450 4186
3451 public void Redo() 4187 public void Redo()
3452 { 4188 {
3453 lock (m_undo) 4189 lock (m_UndoLock)
3454 { 4190 {
3455// m_log.DebugFormat( 4191 if (m_UndoRedo == null || Undoing || ParentGroup == null)
3456// "[SCENE OBJECT PART]: Handling redo request for {0} {1}, stack size {2}", 4192 return;
3457// Name, LocalId, m_redo.Count);
3458
3459 if (m_redo.Count > 0)
3460 {
3461 UndoState gofwd = m_redo[m_redo.Count - 1];
3462 m_redo.RemoveAt(m_redo.Count - 1);
3463
3464 if (ParentGroup.Scene.MaxUndoCount > 0)
3465 {
3466 UndoState nUndo = new UndoState(this, gofwd.ForGroup);
3467
3468 m_undo.Add(nUndo);
3469
3470 if (m_undo.Count > ParentGroup.Scene.MaxUndoCount)
3471 m_undo.RemoveAt(0);
3472 }
3473
3474 gofwd.PlayfwdState(this);
3475 4193
3476// m_log.DebugFormat( 4194 Undoing = true;
3477// "[SCENE OBJECT PART]: Handled redo request for {0} {1}, stack size now {2}", 4195 m_UndoRedo.Redo(this);
3478// Name, LocalId, m_redo.Count); 4196 Undoing = false;
3479 }
3480 } 4197 }
3481 } 4198 }
3482 4199
3483 public void ClearUndoState() 4200 public void ClearUndoState()
3484 { 4201 {
3485// m_log.DebugFormat("[SCENE OBJECT PART]: Clearing undo and redo stacks in {0} {1}", Name, LocalId); 4202 lock (m_UndoLock)
3486
3487 lock (m_undo)
3488 {
3489 m_undo.Clear();
3490 m_redo.Clear();
3491 }
3492 }
3493
3494 public EntityIntersection TestIntersection(Ray iray, Quaternion parentrot)
3495 {
3496 // In this case we're using a sphere with a radius of the largest dimension of the prim
3497 // TODO: Change to take shape into account
3498
3499 EntityIntersection result = new EntityIntersection();
3500 Vector3 vAbsolutePosition = AbsolutePosition;
3501 Vector3 vScale = Scale;
3502 Vector3 rOrigin = iray.Origin;
3503 Vector3 rDirection = iray.Direction;
3504
3505 //rDirection = rDirection.Normalize();
3506 // Buidling the first part of the Quadratic equation
3507 Vector3 r2ndDirection = rDirection*rDirection;
3508 float itestPart1 = r2ndDirection.X + r2ndDirection.Y + r2ndDirection.Z;
3509
3510 // Buidling the second part of the Quadratic equation
3511 Vector3 tmVal2 = rOrigin - vAbsolutePosition;
3512 Vector3 r2Direction = rDirection*2.0f;
3513 Vector3 tmVal3 = r2Direction*tmVal2;
3514
3515 float itestPart2 = tmVal3.X + tmVal3.Y + tmVal3.Z;
3516
3517 // Buidling the third part of the Quadratic equation
3518 Vector3 tmVal4 = rOrigin*rOrigin;
3519 Vector3 tmVal5 = vAbsolutePosition*vAbsolutePosition;
3520
3521 Vector3 tmVal6 = vAbsolutePosition*rOrigin;
3522
3523 // Set Radius to the largest dimension of the prim
3524 float radius = 0f;
3525 if (vScale.X > radius)
3526 radius = vScale.X;
3527 if (vScale.Y > radius)
3528 radius = vScale.Y;
3529 if (vScale.Z > radius)
3530 radius = vScale.Z;
3531
3532 // the second part of this is the default prim size
3533 // once we factor in the aabb of the prim we're adding we can
3534 // change this to;
3535 // radius = (radius / 2) - 0.01f;
3536 //
3537 radius = (radius / 2) + (0.5f / 2) - 0.1f;
3538
3539 //radius = radius;
3540
3541 float itestPart3 = tmVal4.X + tmVal4.Y + tmVal4.Z + tmVal5.X + tmVal5.Y + tmVal5.Z -
3542 (2.0f*(tmVal6.X + tmVal6.Y + tmVal6.Z + (radius*radius)));
3543
3544 // Yuk Quadradrics.. Solve first
3545 float rootsqr = (itestPart2*itestPart2) - (4.0f*itestPart1*itestPart3);
3546 if (rootsqr < 0.0f)
3547 {
3548 // No intersection
3549 return result;
3550 }
3551 float root = ((-itestPart2) - (float) Math.Sqrt((double) rootsqr))/(itestPart1*2.0f);
3552
3553 if (root < 0.0f)
3554 { 4203 {
3555 // perform second quadratic root solution 4204 if (m_UndoRedo == null || Undoing)
3556 root = ((-itestPart2) + (float) Math.Sqrt((double) rootsqr))/(itestPart1*2.0f); 4205 return;
3557 4206
3558 // is there any intersection? 4207 m_UndoRedo.Clear();
3559 if (root < 0.0f)
3560 {
3561 // nope, no intersection
3562 return result;
3563 }
3564 } 4208 }
3565
3566 // We got an intersection. putting together an EntityIntersection object with the
3567 // intersection information
3568 Vector3 ipoint =
3569 new Vector3(iray.Origin.X + (iray.Direction.X*root), iray.Origin.Y + (iray.Direction.Y*root),
3570 iray.Origin.Z + (iray.Direction.Z*root));
3571
3572 result.HitTF = true;
3573 result.ipoint = ipoint;
3574
3575 // Normal is calculated by the difference and then normalizing the result
3576 Vector3 normalpart = ipoint - vAbsolutePosition;
3577 result.normal = normalpart / normalpart.Length();
3578
3579 // It's funny how the Vector3 object has a Distance function, but the Axiom.Math object doesn't.
3580 // I can write a function to do it.. but I like the fact that this one is Static.
3581
3582 Vector3 distanceConvert1 = new Vector3(iray.Origin.X, iray.Origin.Y, iray.Origin.Z);
3583 Vector3 distanceConvert2 = new Vector3(ipoint.X, ipoint.Y, ipoint.Z);
3584 float distance = (float) Util.GetDistanceTo(distanceConvert1, distanceConvert2);
3585
3586 result.distance = distance;
3587
3588 return result;
3589 } 4209 }
3590 4210
3591 public EntityIntersection TestIntersectionOBB(Ray iray, Quaternion parentrot, bool frontFacesOnly, bool faceCenters) 4211 public EntityIntersection TestIntersectionOBB(Ray iray, Quaternion parentrot, bool frontFacesOnly, bool faceCenters)
@@ -3955,15 +4575,7 @@ namespace OpenSim.Region.Framework.Scenes
3955 public void UpdateExtraParam(ushort type, bool inUse, byte[] data) 4575 public void UpdateExtraParam(ushort type, bool inUse, byte[] data)
3956 { 4576 {
3957 m_shape.ReadInUpdateExtraParam(type, inUse, data); 4577 m_shape.ReadInUpdateExtraParam(type, inUse, data);
3958/* 4578
3959 if (type == 0x30)
3960 {
3961 if (m_shape.SculptEntry && m_shape.SculptTexture != UUID.Zero)
3962 {
3963 ParentGroup.Scene.AssetService.Get(m_shape.SculptTexture.ToString(), this, AssetReceived);
3964 }
3965 }
3966*/
3967 if (ParentGroup != null) 4579 if (ParentGroup != null)
3968 { 4580 {
3969 ParentGroup.HasGroupChanged = true; 4581 ParentGroup.HasGroupChanged = true;
@@ -4030,8 +4642,11 @@ namespace OpenSim.Region.Framework.Scenes
4030 if (god) 4642 if (god)
4031 baseMask = 0x7ffffff0; 4643 baseMask = 0x7ffffff0;
4032 4644
4033 // Are we the owner? 4645 bool canChange = (AgentID == OwnerID) || god;
4034 if ((AgentID == OwnerID) || god) 4646 if(!canChange)
4647 canChange = ParentGroup.Scene.Permissions.CanEditObjectPermissions(ParentGroup, AgentID);
4648
4649 if (canChange)
4035 { 4650 {
4036 switch (field) 4651 switch (field)
4037 { 4652 {
@@ -4039,7 +4654,7 @@ namespace OpenSim.Region.Framework.Scenes
4039 if (god) 4654 if (god)
4040 { 4655 {
4041 BaseMask = ApplyMask(BaseMask, set, mask); 4656 BaseMask = ApplyMask(BaseMask, set, mask);
4042 Inventory.ApplyGodPermissions(_baseMask); 4657 Inventory.ApplyGodPermissions(BaseMask);
4043 } 4658 }
4044 4659
4045 break; 4660 break;
@@ -4070,7 +4685,7 @@ namespace OpenSim.Region.Framework.Scenes
4070 } 4685 }
4071 NextOwnerMask = ApplyMask(NextOwnerMask, set, mask) & 4686 NextOwnerMask = ApplyMask(NextOwnerMask, set, mask) &
4072 baseMask; 4687 baseMask;
4073 // Prevent the client from creating no mod, no copy 4688 // Prevent the client from creating no copy, no transfer
4074 // objects 4689 // objects
4075 if ((NextOwnerMask & (uint)PermissionMask.Copy) == 0) 4690 if ((NextOwnerMask & (uint)PermissionMask.Copy) == 0)
4076 NextOwnerMask |= (uint)PermissionMask.Transfer; 4691 NextOwnerMask |= (uint)PermissionMask.Transfer;
@@ -4079,36 +4694,36 @@ namespace OpenSim.Region.Framework.Scenes
4079 4694
4080 break; 4695 break;
4081 } 4696 }
4082 4697 AggregateInnerPerms();
4083 SendFullUpdateToAllClients(); 4698 SendFullUpdateToAllClients();
4084 } 4699 }
4085 } 4700 }
4086 4701
4087 public void ClonePermissions(SceneObjectPart source) 4702 public void ClonePermissions(SceneObjectPart source)
4088 { 4703 {
4089 bool update = false; 4704 uint prevOwnerMask = OwnerMask;
4705 uint prevGroupMask = GroupMask;
4706 uint prevEveryoneMask = EveryoneMask;
4707 uint prevNextOwnerMask = NextOwnerMask;
4090 4708
4091 if (BaseMask != source.BaseMask || 4709 OwnerMask = source.OwnerMask & BaseMask;
4092 OwnerMask != source.OwnerMask || 4710 GroupMask = source.GroupMask & BaseMask;
4093 GroupMask != source.GroupMask || 4711 EveryoneMask = source.EveryoneMask & BaseMask;
4094 EveryoneMask != source.EveryoneMask || 4712 NextOwnerMask = source.NextOwnerMask & BaseMask;
4095 NextOwnerMask != source.NextOwnerMask)
4096 update = true;
4097 4713
4098 BaseMask = source.BaseMask; 4714 AggregateInnerPerms();
4099 OwnerMask = source.OwnerMask;
4100 GroupMask = source.GroupMask;
4101 EveryoneMask = source.EveryoneMask;
4102 NextOwnerMask = source.NextOwnerMask;
4103 4715
4104 if (update) 4716 if (OwnerMask != prevOwnerMask ||
4717 GroupMask != prevGroupMask ||
4718 EveryoneMask != prevEveryoneMask ||
4719 NextOwnerMask != prevNextOwnerMask)
4105 SendFullUpdateToAllClients(); 4720 SendFullUpdateToAllClients();
4106 } 4721 }
4107 4722
4108 public bool IsHingeJoint() 4723 public bool IsHingeJoint()
4109 { 4724 {
4110 // For now, we use the NINJA naming scheme for identifying joints. 4725 // For now, we use the NINJA naming scheme for identifying joints.
4111 // In the future, we can support other joint specification schemes such as a 4726 // In the future, we can support other joint specification schemes such as a
4112 // custom checkbox in the viewer GUI. 4727 // custom checkbox in the viewer GUI.
4113 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints) 4728 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
4114 { 4729 {
@@ -4124,7 +4739,7 @@ namespace OpenSim.Region.Framework.Scenes
4124 public bool IsBallJoint() 4739 public bool IsBallJoint()
4125 { 4740 {
4126 // For now, we use the NINJA naming scheme for identifying joints. 4741 // For now, we use the NINJA naming scheme for identifying joints.
4127 // In the future, we can support other joint specification schemes such as a 4742 // In the future, we can support other joint specification schemes such as a
4128 // custom checkbox in the viewer GUI. 4743 // custom checkbox in the viewer GUI.
4129 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints) 4744 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
4130 { 4745 {
@@ -4140,7 +4755,7 @@ namespace OpenSim.Region.Framework.Scenes
4140 public bool IsJoint() 4755 public bool IsJoint()
4141 { 4756 {
4142 // For now, we use the NINJA naming scheme for identifying joints. 4757 // For now, we use the NINJA naming scheme for identifying joints.
4143 // In the future, we can support other joint specification schemes such as a 4758 // In the future, we can support other joint specification schemes such as a
4144 // custom checkbox in the viewer GUI. 4759 // custom checkbox in the viewer GUI.
4145 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints) 4760 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
4146 { 4761 {
@@ -4157,18 +4772,19 @@ namespace OpenSim.Region.Framework.Scenes
4157 if (physdata.PhysShapeType == PhysShapeType.invalid || ParentGroup == null) 4772 if (physdata.PhysShapeType == PhysShapeType.invalid || ParentGroup == null)
4158 return; 4773 return;
4159 4774
4160 if (PhysicsShapeType != (byte)physdata.PhysShapeType) 4775 byte newtype = (byte)physdata.PhysShapeType;
4161 { 4776 if (PhysicsShapeType != newtype)
4162 PhysicsShapeType = (byte)physdata.PhysShapeType; 4777 PhysicsShapeType = newtype;
4163
4164 }
4165 4778
4166 if(Density != physdata.Density) 4779 if(Density != physdata.Density)
4167 Density = physdata.Density; 4780 Density = physdata.Density;
4781
4168 if(GravityModifier != physdata.GravitationModifier) 4782 if(GravityModifier != physdata.GravitationModifier)
4169 GravityModifier = physdata.GravitationModifier; 4783 GravityModifier = physdata.GravitationModifier;
4784
4170 if(Friction != physdata.Friction) 4785 if(Friction != physdata.Friction)
4171 Friction = physdata.Friction; 4786 Friction = physdata.Friction;
4787
4172 if(Restitution != physdata.Bounce) 4788 if(Restitution != physdata.Bounce)
4173 Restitution = physdata.Bounce; 4789 Restitution = physdata.Bounce;
4174 } 4790 }
@@ -4179,7 +4795,7 @@ namespace OpenSim.Region.Framework.Scenes
4179 /// <param name="SetTemporary"></param> 4795 /// <param name="SetTemporary"></param>
4180 /// <param name="SetPhantom"></param> 4796 /// <param name="SetPhantom"></param>
4181 /// <param name="SetVD"></param> 4797 /// <param name="SetVD"></param>
4182 public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD) 4798 public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD, bool building)
4183 { 4799 {
4184 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0); 4800 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0);
4185 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0); 4801 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0);
@@ -4189,134 +4805,85 @@ namespace OpenSim.Region.Framework.Scenes
4189 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD)) 4805 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD))
4190 return; 4806 return;
4191 4807
4192 PhysicsActor pa = PhysActor; 4808 VolumeDetectActive = SetVD;
4193
4194 // Special cases for VD. VD can only be called from a script
4195 // and can't be combined with changes to other states. So we can rely
4196 // that...
4197 // ... if VD is changed, all others are not.
4198 // ... if one of the others is changed, VD is not.
4199 if (SetVD) // VD is active, special logic applies
4200 {
4201 // State machine logic for VolumeDetect
4202 // More logic below
4203 bool phanReset = (SetPhantom != wasPhantom) && !SetPhantom;
4204
4205 if (phanReset) // Phantom changes from on to off switch VD off too
4206 {
4207 SetVD = false; // Switch it of for the course of this routine
4208 VolumeDetectActive = false; // and also permanently
4209
4210 if (pa != null)
4211 pa.SetVolumeDetect(0); // Let physics know about it too
4212 }
4213 else
4214 {
4215 // If volumedetect is active we don't want phantom to be applied.
4216 // If this is a new call to VD out of the state "phantom"
4217 // this will also cause the prim to be visible to physics
4218 SetPhantom = false;
4219 }
4220 }
4221 4809
4222 if (UsePhysics && IsJoint()) 4810 // volume detector implies phantom we need to decouple this mess
4223 { 4811 if (SetVD)
4224 SetPhantom = true; 4812 SetPhantom = true;
4225 } 4813 else if(wasVD)
4814 SetPhantom = false;
4226 4815
4227 if (UsePhysics) 4816 if (UsePhysics)
4228 {
4229 AddFlag(PrimFlags.Physics); 4817 AddFlag(PrimFlags.Physics);
4230 if (!wasUsingPhysics)
4231 {
4232 DoPhysicsPropertyUpdate(UsePhysics, false);
4233 }
4234 }
4235 else 4818 else
4236 {
4237 RemFlag(PrimFlags.Physics); 4819 RemFlag(PrimFlags.Physics);
4238 if (wasUsingPhysics)
4239 {
4240 DoPhysicsPropertyUpdate(UsePhysics, false);
4241 }
4242 }
4243 4820
4244 if (SetPhantom 4821 if (SetPhantom)
4245 || ParentGroup.IsAttachmentCheckFull()
4246 || PhysicsShapeType == (byte)PhysShapeType.none
4247 || (Shape.PathCurve == (byte)Extrusion.Flexible)) // note: this may have been changed above in the case of joints
4248 {
4249 AddFlag(PrimFlags.Phantom); 4822 AddFlag(PrimFlags.Phantom);
4250 4823 else
4251 if (PhysActor != null)
4252 {
4253 RemoveFromPhysics();
4254 pa = null;
4255 }
4256 }
4257 else // Not phantom
4258 {
4259 RemFlag(PrimFlags.Phantom); 4824 RemFlag(PrimFlags.Phantom);
4260 4825
4261 if (ParentGroup.Scene == null) 4826 if (SetTemporary)
4262 return; 4827 AddFlag(PrimFlags.TemporaryOnRez);
4828 else
4829 RemFlag(PrimFlags.TemporaryOnRez);
4263 4830
4264 if (ParentGroup.Scene.CollidablePrims && pa == null) 4831 if (ParentGroup.Scene == null)
4265 { 4832 return;
4266 AddToPhysics(UsePhysics, SetPhantom, false);
4267 pa = PhysActor;
4268 4833
4269 if (pa != null) 4834 PhysicsActor pa = PhysActor;
4270 {
4271 pa.SetMaterial(Material);
4272 pa.Position = GetWorldPosition();
4273 pa.Orientation = GetWorldRotation();
4274 DoPhysicsPropertyUpdate(UsePhysics, true);
4275 4835
4276 SubscribeForCollisionEvents(); 4836 if (pa != null && building && pa.Building != building)
4277 } 4837 pa.Building = building;
4278 }
4279 else // it already has a physical representation
4280 {
4281 DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status. If it's phantom this will remove the prim
4282 }
4283 }
4284 4838
4285 if (SetVD) 4839 if ((SetPhantom && !UsePhysics && !SetVD) || ParentGroup.IsAttachment || PhysicsShapeType == (byte)PhysShapeType.none
4840 || (Shape.PathCurve == (byte)Extrusion.Flexible))
4286 { 4841 {
4287 // If the above logic worked (this is urgent candidate to unit tests!)
4288 // we now have a physicsactor.
4289 // Defensive programming calls for a check here.
4290 // Better would be throwing an exception that could be catched by a unit test as the internal
4291 // logic should make sure, this Physactor is always here.
4292 if (pa != null) 4842 if (pa != null)
4293 { 4843 {
4294 pa.SetVolumeDetect(1); 4844 if(wasUsingPhysics)
4295 AddFlag(PrimFlags.Phantom); // We set this flag also if VD is active 4845 ParentGroup.Scene.RemovePhysicalPrim(1);
4296 VolumeDetectActive = true; 4846 RemoveFromPhysics();
4297 } 4847 }
4298 }
4299 else if (SetVD != wasVD)
4300 {
4301 // Remove VolumeDetect in any case. Note, it's safe to call SetVolumeDetect as often as you like
4302 // (mumbles, well, at least if you have infinte CPU powers :-))
4303 if (pa != null)
4304 pa.SetVolumeDetect(0);
4305 4848
4306 RemFlag(PrimFlags.Phantom); 4849 Stop();
4307 VolumeDetectActive = false;
4308 } 4850 }
4309 4851
4310 if (SetTemporary)
4311 {
4312 AddFlag(PrimFlags.TemporaryOnRez);
4313 }
4314 else 4852 else
4315 { 4853 {
4316 RemFlag(PrimFlags.TemporaryOnRez); 4854 if (ParentGroup.Scene.CollidablePrims)
4855 {
4856 if (pa == null)
4857 {
4858 AddToPhysics(UsePhysics, SetPhantom, building, false);
4859 pa = PhysActor;
4860
4861 if (pa != null)
4862 {
4863 pa.SetMaterial(Material);
4864 DoPhysicsPropertyUpdate(UsePhysics, true);
4865 }
4866 }
4867 else // it already has a physical representation
4868 {
4869
4870 DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status.
4871
4872 if(UsePhysics && !SetPhantom && m_localId == ParentGroup.RootPart.LocalId &&
4873 m_vehicleParams != null && m_vehicleParams.CameraDecoupled)
4874 AddFlag(PrimFlags.CameraDecoupled);
4875 else
4876 RemFlag(PrimFlags.CameraDecoupled);
4877
4878 if (pa.Building != building)
4879 pa.Building = building;
4880 }
4881
4882 UpdatePhysicsSubscribedEvents();
4883 }
4317 } 4884 }
4318 4885
4319 // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString()); 4886 // and last in case we have a new actor and not building
4320 4887
4321 if (ParentGroup != null) 4888 if (ParentGroup != null)
4322 { 4889 {
@@ -4328,58 +4895,14 @@ namespace OpenSim.Region.Framework.Scenes
4328 } 4895 }
4329 4896
4330 /// <summary> 4897 /// <summary>
4331 /// Subscribe for physics collision events if needed for scripts and sounds
4332 /// </summary>
4333 public void SubscribeForCollisionEvents()
4334 {
4335 PhysicsActor pa = PhysActor;
4336
4337 if (pa != null)
4338 {
4339 if (
4340 ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4341 ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4342 ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4343 ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4344 ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4345 ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4346 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision) != 0) ||
4347 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4348 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4349 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4350 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4351 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4352 (CollisionSound != UUID.Zero)
4353 )
4354 {
4355 if (!pa.SubscribedEvents())
4356 {
4357 // If not already subscribed for event, set up for a collision event.
4358 pa.OnCollisionUpdate += PhysicsCollision;
4359 pa.SubscribeEvents(1000);
4360 }
4361 }
4362 else
4363 {
4364 // There is no need to be subscribed to collisions so, if subscribed, remove subscription
4365 if (pa.SubscribedEvents())
4366 {
4367 pa.OnCollisionUpdate -= PhysicsCollision;
4368 pa.UnSubscribeEvents();
4369 }
4370 }
4371 }
4372 }
4373
4374 /// <summary>
4375 /// Adds this part to the physics scene. 4898 /// Adds this part to the physics scene.
4899 /// and sets the PhysActor property
4376 /// </summary> 4900 /// </summary>
4377 /// <remarks>This method also sets the PhysActor property.</remarks> 4901 /// <param name="isPhysical">Add this prim as physical.</param>
4378 /// <param name="rigidBody">Add this prim with a rigid body.</param> 4902 /// <param name="isPhantom">Add this prim as phantom.</param>
4379 /// <returns> 4903 /// <param name="building">tells physics to delay full construction of object</param>
4380 /// The physics actor. null if there was a failure. 4904 /// <param name="applyDynamics">applies velocities, force and torque</param>
4381 /// </returns> 4905 private void AddToPhysics(bool isPhysical, bool isPhantom, bool building, bool applyDynamics)
4382 private void AddToPhysics(bool isPhysical, bool isPhantom, bool applyDynamics)
4383 { 4906 {
4384 PhysicsActor pa; 4907 PhysicsActor pa;
4385 4908
@@ -4389,15 +4912,15 @@ namespace OpenSim.Region.Framework.Scenes
4389 try 4912 try
4390 { 4913 {
4391 pa = ParentGroup.Scene.PhysicsScene.AddPrimShape( 4914 pa = ParentGroup.Scene.PhysicsScene.AddPrimShape(
4392 string.Format("{0}/{1}", Name, UUID), 4915 string.Format("{0}/{1}", Name, UUID),
4393 Shape, 4916 Shape,
4394 AbsolutePosition, 4917 AbsolutePosition,
4395 Scale, 4918 Scale,
4396 GetWorldRotation(), 4919 GetWorldRotation(),
4397 isPhysical, 4920 isPhysical,
4398 isPhantom, 4921 isPhantom,
4399 PhysicsShapeType, 4922 PhysicsShapeType,
4400 m_localId); 4923 m_localId);
4401 } 4924 }
4402 catch (Exception e) 4925 catch (Exception e)
4403 { 4926 {
@@ -4414,12 +4937,37 @@ namespace OpenSim.Region.Framework.Scenes
4414 pa.GravModifier = GravityModifier; 4937 pa.GravModifier = GravityModifier;
4415 pa.Friction = Friction; 4938 pa.Friction = Friction;
4416 pa.Restitution = Restitution; 4939 pa.Restitution = Restitution;
4940 pa.Buoyancy = Buoyancy;
4941
4942 if(LocalId == ParentGroup.RootPart.LocalId)
4943 {
4944 pa.LockAngularMotion(RotationAxisLocks);
4945 }
4417 4946
4418 if (VolumeDetectActive) // change if not the default only 4947 if (VolumeDetectActive) // change if not the default only
4419 pa.SetVolumeDetect(1); 4948 pa.SetVolumeDetect(1);
4949
4950 bool isroot = (m_localId == ParentGroup.RootPart.LocalId);
4951
4952 if(isroot && m_physicsInertia != null)
4953 pa.SetInertiaData(m_physicsInertia);
4954
4955 if (isroot && m_vehicleParams != null )
4956 {
4957 m_vehicleParams.SetVehicle(pa);
4958 if(isPhysical && !isPhantom && m_vehicleParams.CameraDecoupled)
4959 AddFlag(PrimFlags.CameraDecoupled);
4960 else
4961 RemFlag(PrimFlags.CameraDecoupled);
4962 }
4963 else
4964 RemFlag(PrimFlags.CameraDecoupled);
4420 // we are going to tell rest of code about physics so better have this here 4965 // we are going to tell rest of code about physics so better have this here
4421 PhysActor = pa; 4966 PhysActor = pa;
4422 4967
4968 // DoPhysicsPropertyUpdate(isPhysical, true);
4969 // lets expand it here just with what it really needs to do
4970
4423 if (isPhysical) 4971 if (isPhysical)
4424 { 4972 {
4425 if (ParentGroup.RootPart.KeyframeMotion != null) 4973 if (ParentGroup.RootPart.KeyframeMotion != null)
@@ -4430,7 +4978,7 @@ namespace OpenSim.Region.Framework.Scenes
4430 pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate; 4978 pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
4431 pa.OnOutOfBounds += PhysicsOutOfBounds; 4979 pa.OnOutOfBounds += PhysicsOutOfBounds;
4432 4980
4433 if (ParentID != 0 && ParentID != LocalId) 4981 if (_parentID != 0 && _parentID != LocalId)
4434 { 4982 {
4435 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor; 4983 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
4436 4984
@@ -4441,19 +4989,31 @@ namespace OpenSim.Region.Framework.Scenes
4441 } 4989 }
4442 } 4990 }
4443 4991
4444 if (applyDynamics) 4992 if (applyDynamics && LocalId == ParentGroup.RootPart.LocalId)
4445 // do independent of isphysical so parameters get setted (at least some) 4993 // do independent of isphysical so parameters get setted (at least some)
4446 { 4994 {
4447 Velocity = velocity; 4995 Velocity = velocity;
4448 AngularVelocity = rotationalVelocity; 4996 AngularVelocity = rotationalVelocity;
4449// pa.Velocity = velocity; 4997
4450 pa.RotationalVelocity = rotationalVelocity; 4998 // if not vehicle and root part apply force and torque
4999 if ((m_vehicleParams == null || m_vehicleParams.Type == Vehicle.TYPE_NONE))
5000 {
5001 pa.Force = Force;
5002 pa.Torque = Torque;
5003 }
4451 } 5004 }
4452 5005
4453 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa); 5006// if (Shape.SculptEntry)
5007// CheckSculptAndLoad();
5008// else
5009 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
5010
5011 if (!building)
5012 pa.Building = false;
4454 } 5013 }
4455 5014
4456 PhysActor = pa; 5015 PhysActor = pa;
5016
4457 ParentGroup.Scene.EventManager.TriggerObjectAddedToPhysicalScene(this); 5017 ParentGroup.Scene.EventManager.TriggerObjectAddedToPhysicalScene(this);
4458 } 5018 }
4459 5019
@@ -4462,14 +5022,22 @@ namespace OpenSim.Region.Framework.Scenes
4462 /// </summary> 5022 /// </summary>
4463 /// <remarks> 5023 /// <remarks>
4464 /// This isn't the same as turning off physical, since even without being physical the prim has a physics 5024 /// This isn't the same as turning off physical, since even without being physical the prim has a physics
4465 /// representation for collision detection. Rather, this would be used in situations such as making a prim 5025 /// representation for collision detection.
4466 /// phantom.
4467 /// </remarks> 5026 /// </remarks>
4468 public void RemoveFromPhysics() 5027 public void RemoveFromPhysics()
4469 { 5028 {
4470 ParentGroup.Scene.EventManager.TriggerObjectRemovedFromPhysicalScene(this); 5029 PhysicsActor pa = PhysActor;
4471 if (ParentGroup.Scene.PhysicsScene != null) 5030 if (pa != null)
4472 ParentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); 5031 {
5032 pa.OnCollisionUpdate -= PhysicsCollision;
5033 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
5034 pa.OnOutOfBounds -= PhysicsOutOfBounds;
5035
5036 ParentGroup.Scene.PhysicsScene.RemovePrim(pa);
5037
5038 ParentGroup.Scene.EventManager.TriggerObjectRemovedFromPhysicalScene(this);
5039 }
5040 RemFlag(PrimFlags.CameraDecoupled);
4473 PhysActor = null; 5041 PhysActor = null;
4474 } 5042 }
4475 5043
@@ -4590,40 +5158,6 @@ namespace OpenSim.Region.Framework.Scenes
4590 } 5158 }
4591 5159
4592 /// <summary> 5160 /// <summary>
4593 /// If the part is a sculpt/mesh, retrieve the mesh data and reinsert it into the shape so that the physics
4594 /// engine can use it.
4595 /// </summary>
4596 /// <remarks>
4597 /// When the physics engine has finished with it, the sculpt data is discarded to save memory.
4598 /// </remarks>
4599/*
4600 public void CheckSculptAndLoad()
4601 {
4602// m_log.DebugFormat("Processing CheckSculptAndLoad for {0} {1}", Name, LocalId);
4603
4604 if (ParentGroup.IsDeleted)
4605 return;
4606
4607 if ((ParentGroup.RootPart.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) != 0)
4608 return;
4609
4610 if (Shape.SculptEntry && Shape.SculptTexture != UUID.Zero)
4611 {
4612 // check if a previously decoded sculpt map has been cached
4613 // We don't read the file here - the meshmerizer will do that later.
4614 // TODO: Could we simplify the meshmerizer code by reading and setting the data here?
4615 if (File.Exists(System.IO.Path.Combine("j2kDecodeCache", "smap_" + Shape.SculptTexture.ToString())))
4616 {
4617 SculptTextureCallback(null);
4618 }
4619 else
4620 {
4621 ParentGroup.Scene.AssetService.Get(Shape.SculptTexture.ToString(), this, AssetReceived);
4622 }
4623 }
4624 }
4625*/
4626 /// <summary>
4627 /// Update the texture entry for this part. 5161 /// Update the texture entry for this part.
4628 /// </summary> 5162 /// </summary>
4629 /// <param name="serializedTextureEntry"></param> 5163 /// <param name="serializedTextureEntry"></param>
@@ -4642,41 +5176,42 @@ namespace OpenSim.Region.Framework.Scenes
4642 5176
4643 Changed changeFlags = 0; 5177 Changed changeFlags = 0;
4644 5178
4645 Primitive.TextureEntryFace fallbackNewFace = newTex.DefaultTexture; 5179 Primitive.TextureEntryFace defaultNewFace = newTex.DefaultTexture;
4646 Primitive.TextureEntryFace fallbackOldFace = oldTex.DefaultTexture; 5180 Primitive.TextureEntryFace defaultOldFace = oldTex.DefaultTexture;
4647 5181
4648 // On Incoming packets, sometimes newText.DefaultTexture is null. The assumption is that all 5182 // On Incoming packets, sometimes newText.DefaultTexture is null. The assumption is that all
4649 // other prim-sides are set, but apparently that's not always the case. Lets assume packet/data corruption at this point. 5183 // other prim-sides are set, but apparently that's not always the case. Lets assume packet/data corruption at this point.
4650 if (fallbackNewFace == null) 5184 if (defaultNewFace == null)
4651 { 5185 {
4652 fallbackNewFace = new Primitive.TextureEntry(Util.BLANK_TEXTURE_UUID).CreateFace(0); 5186 defaultNewFace = new Primitive.TextureEntry(Util.BLANK_TEXTURE_UUID).CreateFace(0);
4653 newTex.DefaultTexture = fallbackNewFace; 5187 newTex.DefaultTexture = defaultNewFace;
4654 } 5188 }
4655 if (fallbackOldFace == null) 5189 if (defaultOldFace == null)
4656 { 5190 {
4657 fallbackOldFace = new Primitive.TextureEntry(Util.BLANK_TEXTURE_UUID).CreateFace(0); 5191 defaultOldFace = new Primitive.TextureEntry(Util.BLANK_TEXTURE_UUID).CreateFace(0);
4658 oldTex.DefaultTexture = fallbackOldFace; 5192 oldTex.DefaultTexture = defaultOldFace;
4659 } 5193 }
4660 5194
4661 // Materials capable viewers can send a ObjectImage packet 5195 // Materials capable viewers can send a ObjectImage packet
4662 // when nothing in TE has changed. MaterialID should be updated 5196 // when nothing in TE has changed. MaterialID should be updated
4663 // by the RenderMaterials CAP handler, so updating it here may cause a 5197 // by the RenderMaterials CAP handler, so updating it here may cause a
4664 // race condtion. Therefore, if no non-materials TE fields have changed, 5198 // race condtion. Therefore, if no non-materials TE fields have changed,
4665 // we should ignore any changes and not update Shape.TextureEntry 5199 // we should ignore any changes and not update Shape.TextureEntry
4666 5200
4667 bool otherFieldsChanged = false; 5201 bool otherFieldsChanged = false;
4668 5202 int nsides = GetNumberOfSides();
4669 for (int i = 0 ; i < GetNumberOfSides(); i++) 5203 for (int i = 0 ; i < nsides; i++)
4670 { 5204 {
4671 5205 Primitive.TextureEntryFace newFace = defaultNewFace;
4672 Primitive.TextureEntryFace newFace = newTex.DefaultTexture; 5206 Primitive.TextureEntryFace oldFace = defaultOldFace;
4673 Primitive.TextureEntryFace oldFace = oldTex.DefaultTexture;
4674
4675 if (oldTex.FaceTextures[i] != null) 5207 if (oldTex.FaceTextures[i] != null)
4676 oldFace = oldTex.FaceTextures[i]; 5208 oldFace = oldTex.FaceTextures[i];
4677 if (newTex.FaceTextures[i] != null) 5209 if (newTex.FaceTextures[i] != null)
4678 newFace = newTex.FaceTextures[i]; 5210 newFace = newTex.FaceTextures[i];
4679 5211
5212 if (oldFace.TextureID != newFace.TextureID)
5213 changeFlags |= Changed.TEXTURE;
5214
4680 Color4 oldRGBA = oldFace.RGBA; 5215 Color4 oldRGBA = oldFace.RGBA;
4681 Color4 newRGBA = newFace.RGBA; 5216 Color4 newRGBA = newFace.RGBA;
4682 5217
@@ -4686,9 +5221,6 @@ namespace OpenSim.Region.Framework.Scenes
4686 oldRGBA.A != newRGBA.A) 5221 oldRGBA.A != newRGBA.A)
4687 changeFlags |= Changed.COLOR; 5222 changeFlags |= Changed.COLOR;
4688 5223
4689 if (oldFace.TextureID != newFace.TextureID)
4690 changeFlags |= Changed.TEXTURE;
4691
4692 // Max change, skip the rest of testing 5224 // Max change, skip the rest of testing
4693 if (changeFlags == (Changed.TEXTURE | Changed.COLOR)) 5225 if (changeFlags == (Changed.TEXTURE | Changed.COLOR))
4694 break; 5226 break;
@@ -4706,24 +5238,56 @@ namespace OpenSim.Region.Framework.Scenes
4706 if (oldFace.Rotation != newFace.Rotation) otherFieldsChanged = true; 5238 if (oldFace.Rotation != newFace.Rotation) otherFieldsChanged = true;
4707 if (oldFace.Shiny != newFace.Shiny) otherFieldsChanged = true; 5239 if (oldFace.Shiny != newFace.Shiny) otherFieldsChanged = true;
4708 if (oldFace.TexMapType != newFace.TexMapType) otherFieldsChanged = true; 5240 if (oldFace.TexMapType != newFace.TexMapType) otherFieldsChanged = true;
5241 if(otherFieldsChanged)
5242 changeFlags |= Changed.TEXTURE;
4709 } 5243 }
4710 } 5244 }
4711 5245
4712 if (changeFlags != 0 || otherFieldsChanged) 5246 if (changeFlags == 0)
4713 { 5247 return;
4714 m_shape.TextureEntry = newTex.GetBytes(); 5248 m_shape.TextureEntry = newTex.GetBytes();
4715 if (changeFlags != 0) 5249 TriggerScriptChangedEvent(changeFlags);
4716 TriggerScriptChangedEvent(changeFlags); 5250 ParentGroup.HasGroupChanged = true;
4717 UpdateFlag = UpdateRequired.FULL; 5251 ScheduleFullUpdate();
4718 ParentGroup.HasGroupChanged = true; 5252 }
4719 5253
4720 //This is madness.. 5254 internal void UpdatePhysicsSubscribedEvents()
4721 //ParentGroup.ScheduleGroupForFullUpdate(); 5255 {
4722 //This is sparta 5256 PhysicsActor pa = PhysActor;
4723 ScheduleFullUpdate(); 5257 if (pa == null)
5258 return;
5259
5260 pa.OnCollisionUpdate -= PhysicsCollision;
5261
5262 bool hassound = (!VolumeDetectActive && CollisionSoundType >= 0 && ((Flags & PrimFlags.Physics) != 0));
5263
5264 scriptEvents CombinedEvents = AggregateScriptEvents;
5265
5266 // merge with root part
5267 if (ParentGroup != null && ParentGroup.RootPart != null)
5268 CombinedEvents |= ParentGroup.RootPart.AggregateScriptEvents;
5269
5270 // submit to this part case
5271 if (VolumeDetectActive)
5272 CombinedEvents &= PhyscicsVolumeDtcSubsEvents;
5273 else if ((Flags & PrimFlags.Phantom) != 0)
5274 CombinedEvents &= PhyscicsPhantonSubsEvents;
5275 else
5276 CombinedEvents &= PhysicsNeededSubsEvents;
5277
5278 if (hassound || CombinedEvents != 0)
5279 {
5280 // subscribe to physics updates.
5281 pa.OnCollisionUpdate += PhysicsCollision;
5282 pa.SubscribeEvents(50); // 20 reports per second
5283 }
5284 else
5285 {
5286 pa.UnSubscribeEvents();
4724 } 5287 }
4725 } 5288 }
4726 5289
5290
4727 public void aggregateScriptEvents() 5291 public void aggregateScriptEvents()
4728 { 5292 {
4729 if (ParentGroup == null || ParentGroup.RootPart == null) 5293 if (ParentGroup == null || ParentGroup.RootPart == null)
@@ -4761,17 +5325,6 @@ namespace OpenSim.Region.Framework.Scenes
4761 objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop; 5325 objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop;
4762 } 5326 }
4763 5327
4764 SubscribeForCollisionEvents();
4765
4766 //if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0)
4767 //{
4768 // ParentGroup.Scene.EventManager.OnScriptTimerEvent += handleTimerAccounting;
4769 //}
4770 //else
4771 //{
4772 // ParentGroup.Scene.EventManager.OnScriptTimerEvent -= handleTimerAccounting;
4773 //}
4774
4775 LocalFlags = (PrimFlags)objectflagupdate; 5328 LocalFlags = (PrimFlags)objectflagupdate;
4776 5329
4777 if (ParentGroup != null && ParentGroup.RootPart == this) 5330 if (ParentGroup != null && ParentGroup.RootPart == this)
@@ -4782,6 +5335,7 @@ namespace OpenSim.Region.Framework.Scenes
4782 { 5335 {
4783// m_log.DebugFormat( 5336// m_log.DebugFormat(
4784// "[SCENE OBJECT PART]: Scheduling part {0} {1} for full update in aggregateScriptEvents()", Name, LocalId); 5337// "[SCENE OBJECT PART]: Scheduling part {0} {1} for full update in aggregateScriptEvents()", Name, LocalId);
5338 UpdatePhysicsSubscribedEvents();
4785 ScheduleFullUpdate(); 5339 ScheduleFullUpdate();
4786 } 5340 }
4787 } 5341 }
@@ -4815,7 +5369,7 @@ namespace OpenSim.Region.Framework.Scenes
4815 { 5369 {
4816 return m_forceMouselook; 5370 return m_forceMouselook;
4817 } 5371 }
4818 5372
4819 public override string ToString() 5373 public override string ToString()
4820 { 5374 {
4821 return String.Format("{0} {1} (parent {2}))", Name, UUID, ParentGroup); 5375 return String.Format("{0} {1} (parent {2}))", Name, UUID, ParentGroup);
@@ -4832,7 +5386,7 @@ namespace OpenSim.Region.Framework.Scenes
4832 && (ParentGroup.RootPart != this 5386 && (ParentGroup.RootPart != this
4833 || ParentGroup.AttachedAvatar != remoteClient.AgentId && ParentGroup.HasPrivateAttachmentPoint)) 5387 || ParentGroup.AttachedAvatar != remoteClient.AgentId && ParentGroup.HasPrivateAttachmentPoint))
4834 return; 5388 return;
4835 5389
4836 // Causes this thread to dig into the Client Thread Data. 5390 // Causes this thread to dig into the Client Thread Data.
4837 // Remember your locking here! 5391 // Remember your locking here!
4838 remoteClient.SendEntityUpdate( 5392 remoteClient.SendEntityUpdate(
@@ -4840,9 +5394,9 @@ namespace OpenSim.Region.Framework.Scenes
4840 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity 5394 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
4841 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity); 5395 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
4842 5396
4843 ParentGroup.Scene.StatsReporter.AddObjectUpdates(1); 5397 ParentGroup.Scene.StatsReporter.AddObjectUpdates(1);
4844 } 5398 }
4845 5399
4846 public void AddScriptLPS(int count) 5400 public void AddScriptLPS(int count)
4847 { 5401 {
4848 ParentGroup.AddScriptLPS(count); 5402 ParentGroup.AddScriptLPS(count);
@@ -4856,7 +5410,7 @@ namespace OpenSim.Region.Framework.Scenes
4856 /// <param name="scene">The scene the prim is being rezzed into</param> 5410 /// <param name="scene">The scene the prim is being rezzed into</param>
4857 public void ApplyPermissionsOnRez(InventoryItemBase item, bool userInventory, Scene scene) 5411 public void ApplyPermissionsOnRez(InventoryItemBase item, bool userInventory, Scene scene)
4858 { 5412 {
4859 if ((OwnerID != item.Owner) || ((item.CurrentPermissions & SceneObjectGroup.SLAM) != 0) || ((item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0)) 5413 if ((OwnerID != item.Owner) || ((item.CurrentPermissions & (uint)PermissionMask.Slam) != 0) || ((item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0))
4860 { 5414 {
4861 if (scene.Permissions.PropagatePermissions()) 5415 if (scene.Permissions.PropagatePermissions())
4862 { 5416 {
@@ -4887,16 +5441,13 @@ namespace OpenSim.Region.Framework.Scenes
4887 5441
4888 if (OwnerID != item.Owner) 5442 if (OwnerID != item.Owner)
4889 { 5443 {
4890 //LogPermissions("Before ApplyNextOwnerPermissions"); 5444 if(OwnerID != GroupID)
5445 LastOwnerID = OwnerID;
5446 OwnerID = item.Owner;
5447 Inventory.ChangeInventoryOwner(item.Owner);
4891 5448
4892 if (scene.Permissions.PropagatePermissions()) 5449 if (scene.Permissions.PropagatePermissions())
4893 ApplyNextOwnerPermissions(); 5450 ApplyNextOwnerPermissions();
4894
4895 //LogPermissions("After ApplyNextOwnerPermissions");
4896
4897 LastOwnerID = OwnerID;
4898 OwnerID = item.Owner;
4899 Inventory.ChangeInventoryOwner(item.Owner);
4900 } 5451 }
4901 } 5452 }
4902 5453
@@ -4908,17 +5459,19 @@ namespace OpenSim.Region.Framework.Scenes
4908 { 5459 {
4909 PermissionsUtil.LogPermissions(Name, message, BaseMask, OwnerMask, NextOwnerMask); 5460 PermissionsUtil.LogPermissions(Name, message, BaseMask, OwnerMask, NextOwnerMask);
4910 } 5461 }
4911 5462
4912 public void ApplyNextOwnerPermissions() 5463 public void ApplyNextOwnerPermissions()
4913 { 5464 {
4914 // Export needs to be preserved in the base and everyone 5465 // Export needs to be preserved in the base and everyone
4915 // mask, but removed in the owner mask as a next owner 5466 // mask, but removed in the owner mask as a next owner
4916 // can never change the export status 5467 // can never change the export status
4917 BaseMask &= NextOwnerMask | (uint)PermissionMask.Export; 5468 BaseMask &= (NextOwnerMask | (uint)PermissionMask.Export);
4918 OwnerMask &= NextOwnerMask; 5469 OwnerMask &= NextOwnerMask;
4919 EveryoneMask &= NextOwnerMask | (uint)PermissionMask.Export; 5470 EveryoneMask &= (NextOwnerMask | (uint)PermissionMask.Export);
5471 GroupMask = 0; // Giving an object zaps group permissions
4920 5472
4921 Inventory.ApplyNextOwnerPermissions(); 5473 Inventory.ApplyNextOwnerPermissions();
5474 AggregateInnerPerms();
4922 } 5475 }
4923 5476
4924 public void UpdateLookAt() 5477 public void UpdateLookAt()
@@ -4970,6 +5523,19 @@ namespace OpenSim.Region.Framework.Scenes
4970 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));
4971 } 5524 }
4972 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 AggregateInnerPerms();
5537 }
5538
4973 /// <summary> 5539 /// <summary>
4974 /// Record an avatar sitting on this part. 5540 /// Record an avatar sitting on this part.
4975 /// </summary> 5541 /// </summary>
@@ -4990,7 +5556,8 @@ namespace OpenSim.Region.Framework.Scenes
4990 5556
4991 if (m_sittingAvatars.Add(sp)) 5557 if (m_sittingAvatars.Add(sp))
4992 { 5558 {
4993 ParentGroup.m_sittingAvatars.Add(sp); 5559 if(!ParentGroup.m_sittingAvatars.Contains(sp))
5560 ParentGroup.m_sittingAvatars.Add(sp);
4994 5561
4995 return true; 5562 return true;
4996 } 5563 }
@@ -5062,5 +5629,32 @@ namespace OpenSim.Region.Framework.Scenes
5062 return m_sittingAvatars.Count; 5629 return m_sittingAvatars.Count;
5063 } 5630 }
5064 } 5631 }
5632
5633 public void Stop()
5634 {
5635 Velocity = Vector3.Zero;
5636 AngularVelocity = Vector3.Zero;
5637 Acceleration = Vector3.Zero;
5638 APIDActive = false;
5639 }
5640
5641 // handle osVolumeDetect
5642 public void ScriptSetVolumeDetect(bool makeVolumeDetect)
5643 {
5644 if(_parentID == 0)
5645 {
5646 // if root prim do it via SOG
5647 ParentGroup.ScriptSetVolumeDetect(makeVolumeDetect);
5648 return;
5649 }
5650
5651 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0);
5652 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0);
5653 bool wasPhantom = ((Flags & PrimFlags.Phantom) != 0);
5654
5655 if(PhysActor != null)
5656 PhysActor.Building = true;
5657 UpdatePrimFlags(wasUsingPhysics,wasTemporary,wasPhantom,makeVolumeDetect,false);
5658 }
5065 } 5659 }
5066} \ No newline at end of file 5660}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index ec39726..30f7151 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Text;
29using System.Xml; 30using System.Xml;
30using System.IO; 31using System.IO;
31using System.Collections.Generic; 32using System.Collections.Generic;
@@ -46,10 +47,15 @@ namespace OpenSim.Region.Framework.Scenes
46 { 47 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 49
49 private string m_inventoryFileName = String.Empty;
50 private byte[] m_inventoryFileData = new byte[0]; 50 private byte[] m_inventoryFileData = new byte[0];
51 private byte[] m_inventoryFileNameBytes = new byte[0];
52 private string m_inventoryFileName = "";
51 private uint m_inventoryFileNameSerial = 0; 53 private uint m_inventoryFileNameSerial = 0;
52 54 private bool m_inventoryPrivileged = false;
55 private object m_inventoryFileLock = new object();
56
57 private Dictionary<UUID, ArrayList> m_scriptErrors = new Dictionary<UUID, ArrayList>();
58
53 /// <value> 59 /// <value>
54 /// The part to which the inventory belongs. 60 /// The part to which the inventory belongs.
55 /// </value> 61 /// </value>
@@ -70,7 +76,7 @@ namespace OpenSim.Region.Framework.Scenes
70 /// Tracks whether inventory has changed since the last persistent backup 76 /// Tracks whether inventory has changed since the last persistent backup
71 /// </summary> 77 /// </summary>
72 internal bool HasInventoryChanged; 78 internal bool HasInventoryChanged;
73 79
74 /// <value> 80 /// <value>
75 /// Inventory serial number 81 /// Inventory serial number
76 /// </value> 82 /// </value>
@@ -85,7 +91,10 @@ namespace OpenSim.Region.Framework.Scenes
85 /// </value> 91 /// </value>
86 protected internal TaskInventoryDictionary Items 92 protected internal TaskInventoryDictionary Items
87 { 93 {
88 get { return m_items; } 94 get
95 {
96 return m_items;
97 }
89 set 98 set
90 { 99 {
91 m_items = value; 100 m_items = value;
@@ -102,7 +111,7 @@ namespace OpenSim.Region.Framework.Scenes
102 return m_items.Count; 111 return m_items.Count;
103 } 112 }
104 } 113 }
105 114
106 /// <summary> 115 /// <summary>
107 /// Constructor 116 /// Constructor
108 /// </summary> 117 /// </summary>
@@ -133,39 +142,54 @@ namespace OpenSim.Region.Framework.Scenes
133 /// </remarks> 142 /// </remarks>
134 public void ResetInventoryIDs() 143 public void ResetInventoryIDs()
135 { 144 {
136 if (null == m_part) 145 if (m_part == null)
137 return; 146 return;
138 147
139 lock (m_items) 148 m_items.LockItemsForWrite(true);
149 if (m_items.Count == 0)
140 { 150 {
141 if (0 == m_items.Count) 151 m_items.LockItemsForWrite(false);
142 return; 152 return;
153 }
143 154
144 IList<TaskInventoryItem> items = GetInventoryItems(); 155 UUID partID = m_part.UUID;
145 m_items.Clear(); 156 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(m_items.Values);
157 m_items.Clear();
146 158
147 foreach (TaskInventoryItem item in items) 159 foreach (TaskInventoryItem item in items)
148 { 160 {
149 item.ResetIDs(m_part.UUID); 161 item.ResetIDs(partID);
150 m_items.Add(item.ItemID, item); 162 m_items.Add(item.ItemID, item);
151 }
152 } 163 }
164 m_inventorySerial++;
165 m_items.LockItemsForWrite(false);
153 } 166 }
154 167
155 public void ResetObjectID() 168 public void ResetObjectID()
156 { 169 {
157 lock (Items) 170 if (m_part == null)
171 return;
172
173 m_items.LockItemsForWrite(true);
174
175 if (m_items.Count == 0)
158 { 176 {
159 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 177 m_items.LockItemsForWrite(false);
160 Items.Clear(); 178 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 } 179 }
180
181 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(m_items.Values);
182 m_items.Clear();
183
184 UUID partID = m_part.UUID;
185 foreach (TaskInventoryItem item in items)
186 {
187 item.ParentPartID = partID;
188 item.ParentID = partID;
189 m_items.Add(item.ItemID, item);
190 }
191 m_inventorySerial++;
192 m_items.LockItemsForWrite(false);
169 } 193 }
170 194
171 /// <summary> 195 /// <summary>
@@ -174,18 +198,17 @@ namespace OpenSim.Region.Framework.Scenes
174 /// <param name="ownerId"></param> 198 /// <param name="ownerId"></param>
175 public void ChangeInventoryOwner(UUID ownerId) 199 public void ChangeInventoryOwner(UUID ownerId)
176 { 200 {
177 lock (Items) 201 if(m_part == null)
202 return;
203
204 m_items.LockItemsForWrite(true);
205 if (m_items.Count == 0)
178 { 206 {
179 if (0 == Items.Count) 207 m_items.LockItemsForWrite(false);
180 { 208 return;
181 return;
182 }
183 } 209 }
184 210
185 HasInventoryChanged = true; 211 foreach (TaskInventoryItem item in m_items.Values)
186 m_part.ParentGroup.HasGroupChanged = true;
187 List<TaskInventoryItem> items = GetInventoryItems();
188 foreach (TaskInventoryItem item in items)
189 { 212 {
190 if (ownerId != item.OwnerID) 213 if (ownerId != item.OwnerID)
191 item.LastOwnerID = item.OwnerID; 214 item.LastOwnerID = item.OwnerID;
@@ -195,6 +218,10 @@ namespace OpenSim.Region.Framework.Scenes
195 item.PermsGranter = UUID.Zero; 218 item.PermsGranter = UUID.Zero;
196 item.OwnerChanged = true; 219 item.OwnerChanged = true;
197 } 220 }
221 HasInventoryChanged = true;
222 m_part.ParentGroup.HasGroupChanged = true;
223 m_inventorySerial++;
224 m_items.LockItemsForWrite(false);
198 } 225 }
199 226
200 /// <summary> 227 /// <summary>
@@ -203,14 +230,16 @@ namespace OpenSim.Region.Framework.Scenes
203 /// <param name="groupID"></param> 230 /// <param name="groupID"></param>
204 public void ChangeInventoryGroup(UUID groupID) 231 public void ChangeInventoryGroup(UUID groupID)
205 { 232 {
206 lock (Items) 233 if(m_part == null)
234 return;
235
236 m_items.LockItemsForWrite(true);
237 if (m_items.Count == 0)
207 { 238 {
208 if (0 == Items.Count) 239 m_items.LockItemsForWrite(false);
209 { 240 return;
210 return;
211 }
212 } 241 }
213 242 m_inventorySerial++;
214 // Don't let this set the HasGroupChanged flag for attachments 243 // Don't let this set the HasGroupChanged flag for attachments
215 // as this happens during rez and we don't want a new asset 244 // as this happens during rez and we don't want a new asset
216 // for each attachment each time 245 // for each attachment each time
@@ -220,12 +249,10 @@ namespace OpenSim.Region.Framework.Scenes
220 m_part.ParentGroup.HasGroupChanged = true; 249 m_part.ParentGroup.HasGroupChanged = true;
221 } 250 }
222 251
223 List<TaskInventoryItem> items = GetInventoryItems(); 252 foreach (TaskInventoryItem item in m_items.Values)
224 foreach (TaskInventoryItem item in items) 253 item.GroupID = groupID;
225 { 254
226 if (groupID != item.GroupID) 255 m_items.LockItemsForWrite(false);
227 item.GroupID = groupID;
228 }
229 } 256 }
230 257
231 private void QueryScriptStates() 258 private void QueryScriptStates()
@@ -233,15 +260,18 @@ namespace OpenSim.Region.Framework.Scenes
233 if (m_part == null || m_part.ParentGroup == null || m_part.ParentGroup.Scene == null) 260 if (m_part == null || m_part.ParentGroup == null || m_part.ParentGroup.Scene == null)
234 return; 261 return;
235 262
236 lock (Items) 263 m_items.LockItemsForRead(true);
264 foreach (TaskInventoryItem item in m_items.Values)
237 { 265 {
238 foreach (TaskInventoryItem item in Items.Values) 266 if (item.InvType == (int)InventoryType.LSL)
239 { 267 {
240 bool running; 268 bool running;
241 if (TryGetScriptInstanceRunning(m_part.ParentGroup.Scene, item, out running)) 269 if (TryGetScriptInstanceRunning(m_part.ParentGroup.Scene, item, out running))
242 item.ScriptRunning = running; 270 item.ScriptRunning = running;
243 } 271 }
244 } 272 }
273
274 m_items.LockItemsForRead(false);
245 } 275 }
246 276
247 public bool TryGetScriptInstanceRunning(UUID itemId, out bool running) 277 public bool TryGetScriptInstanceRunning(UUID itemId, out bool running)
@@ -318,7 +348,10 @@ namespace OpenSim.Region.Framework.Scenes
318 { 348 {
319 List<TaskInventoryItem> scripts = GetInventoryItems(InventoryType.LSL); 349 List<TaskInventoryItem> scripts = GetInventoryItems(InventoryType.LSL);
320 foreach (TaskInventoryItem item in scripts) 350 foreach (TaskInventoryItem item in scripts)
351 {
321 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted); 352 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
353 m_part.RemoveScriptEvents(item.ItemID);
354 }
322 } 355 }
323 356
324 /// <summary> 357 /// <summary>
@@ -326,7 +359,9 @@ namespace OpenSim.Region.Framework.Scenes
326 /// </summary> 359 /// </summary>
327 public void StopScriptInstances() 360 public void StopScriptInstances()
328 { 361 {
329 GetInventoryItems(InventoryType.LSL).ForEach(i => StopScriptInstance(i)); 362 List<TaskInventoryItem> scripts = GetInventoryItems(InventoryType.LSL);
363 foreach (TaskInventoryItem item in scripts)
364 StopScriptInstance(item);
330 } 365 }
331 366
332 /// <summary> 367 /// <summary>
@@ -339,8 +374,11 @@ namespace OpenSim.Region.Framework.Scenes
339// m_log.DebugFormat("[PRIM INVENTORY]: Starting script {0} {1} in prim {2} {3} in {4}", 374// m_log.DebugFormat("[PRIM INVENTORY]: Starting script {0} {1} in prim {2} {3} in {4}",
340// item.Name, item.ItemID, m_part.Name, m_part.UUID, m_part.ParentGroup.Scene.RegionInfo.RegionName); 375// item.Name, item.ItemID, m_part.Name, m_part.UUID, m_part.ParentGroup.Scene.RegionInfo.RegionName);
341 376
342 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID)) 377 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item, m_part))
378 {
379 StoreScriptError(item.ItemID, "no permission");
343 return false; 380 return false;
381 }
344 382
345 m_part.AddFlag(PrimFlags.Scripted); 383 m_part.AddFlag(PrimFlags.Scripted);
346 384
@@ -350,14 +388,13 @@ namespace OpenSim.Region.Framework.Scenes
350 if (stateSource == 2 && // Prim crossing 388 if (stateSource == 2 && // Prim crossing
351 m_part.ParentGroup.Scene.m_trustBinaries) 389 m_part.ParentGroup.Scene.m_trustBinaries)
352 { 390 {
353 lock (m_items) 391 m_items.LockItemsForWrite(true);
354 { 392 m_items[item.ItemID].PermsMask = 0;
355 m_items[item.ItemID].PermsMask = 0; 393 m_items[item.ItemID].PermsGranter = UUID.Zero;
356 m_items[item.ItemID].PermsGranter = UUID.Zero; 394 m_items.LockItemsForWrite(false);
357 }
358
359 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 395 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
360 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); 396 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
397 StoreScriptErrors(item.ItemID, null);
361 m_part.ParentGroup.AddActiveScriptCount(1); 398 m_part.ParentGroup.AddActiveScriptCount(1);
362 m_part.ScheduleFullUpdate(); 399 m_part.ScheduleFullUpdate();
363 return true; 400 return true;
@@ -366,9 +403,11 @@ namespace OpenSim.Region.Framework.Scenes
366 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); 403 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
367 if (null == asset) 404 if (null == asset)
368 { 405 {
406 string msg = String.Format("asset ID {0} could not be found", item.AssetID);
407 StoreScriptError(item.ItemID, msg);
369 m_log.ErrorFormat( 408 m_log.ErrorFormat(
370 "[PRIM INVENTORY]: Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found", 409 "[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, 410 item.Name, item.ItemID, m_part.AbsolutePosition,
372 m_part.ParentGroup.Scene.RegionInfo.RegionName, item.AssetID); 411 m_part.ParentGroup.Scene.RegionInfo.RegionName, item.AssetID);
373 412
374 return false; 413 return false;
@@ -378,16 +417,18 @@ namespace OpenSim.Region.Framework.Scenes
378 if (m_part.ParentGroup.m_savedScriptState != null) 417 if (m_part.ParentGroup.m_savedScriptState != null)
379 item.OldItemID = RestoreSavedScriptState(item.LoadedItemID, item.OldItemID, item.ItemID); 418 item.OldItemID = RestoreSavedScriptState(item.LoadedItemID, item.OldItemID, item.ItemID);
380 419
381 lock (m_items) 420 m_items.LockItemsForWrite(true);
382 { 421
383 m_items[item.ItemID].OldItemID = item.OldItemID; 422 m_items[item.ItemID].OldItemID = item.OldItemID;
384 m_items[item.ItemID].PermsMask = 0; 423 m_items[item.ItemID].PermsMask = 0;
385 m_items[item.ItemID].PermsGranter = UUID.Zero; 424 m_items[item.ItemID].PermsGranter = UUID.Zero;
386 } 425
426 m_items.LockItemsForWrite(false);
387 427
388 string script = Utils.BytesToString(asset.Data); 428 string script = Utils.BytesToString(asset.Data);
389 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 429 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
390 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); 430 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
431 StoreScriptErrors(item.ItemID, null);
391 if (!item.ScriptRunning) 432 if (!item.ScriptRunning)
392 m_part.ParentGroup.Scene.EventManager.TriggerStopScript( 433 m_part.ParentGroup.Scene.EventManager.TriggerStopScript(
393 m_part.LocalId, item.ItemID); 434 m_part.LocalId, item.ItemID);
@@ -401,7 +442,7 @@ namespace OpenSim.Region.Framework.Scenes
401 private UUID RestoreSavedScriptState(UUID loadedID, UUID oldID, UUID newID) 442 private UUID RestoreSavedScriptState(UUID loadedID, UUID oldID, UUID newID)
402 { 443 {
403// m_log.DebugFormat( 444// m_log.DebugFormat(
404// "[PRIM INVENTORY]: Restoring scripted state for item {0}, oldID {1}, loadedID {2}", 445// "[PRIM INVENTORY]: Restoring scripted state for item {0}, oldID {1}, loadedID {2}",
405// newID, oldID, loadedID); 446// newID, oldID, loadedID);
406 447
407 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>(); 448 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
@@ -414,7 +455,7 @@ namespace OpenSim.Region.Framework.Scenes
414 if (m_part.ParentGroup.m_savedScriptState.ContainsKey(stateID)) 455 if (m_part.ParentGroup.m_savedScriptState.ContainsKey(stateID))
415 { 456 {
416 XmlDocument doc = new XmlDocument(); 457 XmlDocument doc = new XmlDocument();
417 458 doc.XmlResolver=null;
418 doc.LoadXml(m_part.ParentGroup.m_savedScriptState[stateID]); 459 doc.LoadXml(m_part.ParentGroup.m_savedScriptState[stateID]);
419 460
420 ////////// CRUFT WARNING /////////////////////////////////// 461 ////////// CRUFT WARNING ///////////////////////////////////
@@ -450,7 +491,7 @@ namespace OpenSim.Region.Framework.Scenes
450 491
451 m_part.ParentGroup.m_savedScriptState[stateID] = newDoc.OuterXml; 492 m_part.ParentGroup.m_savedScriptState[stateID] = newDoc.OuterXml;
452 } 493 }
453 494
454 foreach (IScriptModule e in engines) 495 foreach (IScriptModule e in engines)
455 { 496 {
456 if (e != null) 497 if (e != null)
@@ -466,22 +507,138 @@ namespace OpenSim.Region.Framework.Scenes
466 return stateID; 507 return stateID;
467 } 508 }
468 509
510 /// <summary>
511 /// Start a script which is in this prim's inventory.
512 /// Some processing may occur in the background, but this routine returns asap.
513 /// </summary>
514 /// <param name="itemId">
515 /// A <see cref="UUID"/>
516 /// </param>
469 public bool CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) 517 public bool CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
470 { 518 {
471 TaskInventoryItem item = GetInventoryItem(itemId); 519 lock (m_scriptErrors)
472 if (item != null) 520 {
521 // Indicate to CreateScriptInstanceInternal() we don't want it to wait for completion
522 m_scriptErrors.Remove(itemId);
523 }
524 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
525 return true;
526 }
527
528 private void CreateScriptInstanceInternal(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
529 {
530 m_items.LockItemsForRead(true);
531
532 if (m_items.ContainsKey(itemId))
473 { 533 {
474 return CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); 534 TaskInventoryItem it = m_items[itemId];
535 m_items.LockItemsForRead(false);
536
537 CreateScriptInstance(it, startParam, postOnRez, engine, stateSource);
475 } 538 }
476 else 539 else
477 { 540 {
478 m_log.ErrorFormat( 541 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}", 542 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); 543 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
544 StoreScriptError(itemId, msg);
545 m_log.ErrorFormat(
546 "[PRIM INVENTORY]: " +
547 "Couldn't start script with ID {0} since it {1}", itemId, msg);
548 }
549 }
482 550
483 return false; 551 /// <summary>
552 /// Start a script which is in this prim's inventory and return any compilation error messages.
553 /// </summary>
554 /// <param name="itemId">
555 /// A <see cref="UUID"/>
556 /// </param>
557 public ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
558 {
559 ArrayList errors;
560
561 // Indicate to CreateScriptInstanceInternal() we want it to
562 // post any compilation/loading error messages
563 lock (m_scriptErrors)
564 {
565 m_scriptErrors[itemId] = null;
484 } 566 }
567
568 // Perform compilation/loading
569 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
570
571 // Wait for and retrieve any errors
572 lock (m_scriptErrors)
573 {
574 while ((errors = m_scriptErrors[itemId]) == null)
575 {
576 if (!System.Threading.Monitor.Wait(m_scriptErrors, 15000))
577 {
578 m_log.ErrorFormat(
579 "[PRIM INVENTORY]: " +
580 "timedout waiting for script {0} errors", itemId);
581 errors = m_scriptErrors[itemId];
582 if (errors == null)
583 {
584 errors = new ArrayList(1);
585 errors.Add("timedout waiting for errors");
586 }
587 break;
588 }
589 }
590 m_scriptErrors.Remove(itemId);
591 }
592 return errors;
593 }
594
595 // Signal to CreateScriptInstanceEr() that compilation/loading is complete
596 private void StoreScriptErrors(UUID itemId, ArrayList errors)
597 {
598 lock (m_scriptErrors)
599 {
600 // If compilation/loading initiated via CreateScriptInstance(),
601 // it does not want the errors, so just get out
602 if (!m_scriptErrors.ContainsKey(itemId))
603 {
604 return;
605 }
606
607 // Initiated via CreateScriptInstanceEr(), if we know what the
608 // errors are, save them and wake CreateScriptInstanceEr().
609 if (errors != null)
610 {
611 m_scriptErrors[itemId] = errors;
612 System.Threading.Monitor.PulseAll(m_scriptErrors);
613 return;
614 }
615 }
616
617 // Initiated via CreateScriptInstanceEr() but we don't know what
618 // the errors are yet, so retrieve them from the script engine.
619 // This may involve some waiting internal to GetScriptErrors().
620 errors = GetScriptErrors(itemId);
621
622 // Get a default non-null value to indicate success.
623 if (errors == null)
624 {
625 errors = new ArrayList();
626 }
627
628 // Post to CreateScriptInstanceEr() and wake it up
629 lock (m_scriptErrors)
630 {
631 m_scriptErrors[itemId] = errors;
632 System.Threading.Monitor.PulseAll(m_scriptErrors);
633 }
634 }
635
636 // Like StoreScriptErrors(), but just posts a single string message
637 private void StoreScriptError(UUID itemId, string message)
638 {
639 ArrayList errors = new ArrayList(1);
640 errors.Add(message);
641 StoreScriptErrors(itemId, errors);
485 } 642 }
486 643
487 /// <summary> 644 /// <summary>
@@ -494,19 +651,11 @@ namespace OpenSim.Region.Framework.Scenes
494 /// </param> 651 /// </param>
495 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted) 652 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted)
496 { 653 {
497 bool scriptPresent = false; 654 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 { 655 {
507 if (!sceneObjectBeingDeleted) 656 if (!sceneObjectBeingDeleted)
508 m_part.RemoveScriptEvents(itemId); 657 m_part.RemoveScriptEvents(itemId);
509 658
510 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemId); 659 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemId);
511 m_part.ParentGroup.AddActiveScriptCount(-1); 660 m_part.ParentGroup.AddActiveScriptCount(-1);
512 } 661 }
@@ -515,7 +664,7 @@ namespace OpenSim.Region.Framework.Scenes
515 m_log.WarnFormat( 664 m_log.WarnFormat(
516 "[PRIM INVENTORY]: " + 665 "[PRIM INVENTORY]: " +
517 "Couldn't stop script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", 666 "Couldn't stop script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}",
518 itemId, m_part.Name, m_part.UUID, 667 itemId, m_part.Name, m_part.UUID,
519 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 668 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
520 } 669 }
521 } 670 }
@@ -544,7 +693,7 @@ namespace OpenSim.Region.Framework.Scenes
544 m_log.WarnFormat( 693 m_log.WarnFormat(
545 "[PRIM INVENTORY]: " + 694 "[PRIM INVENTORY]: " +
546 "Couldn't stop script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", 695 "Couldn't stop script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}",
547 itemId, m_part.Name, m_part.UUID, 696 itemId, m_part.Name, m_part.UUID,
548 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 697 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
549 } 698 }
550 } 699 }
@@ -573,14 +722,16 @@ namespace OpenSim.Region.Framework.Scenes
573 /// <returns></returns> 722 /// <returns></returns>
574 private bool InventoryContainsName(string name) 723 private bool InventoryContainsName(string name)
575 { 724 {
576 lock (m_items) 725 m_items.LockItemsForRead(true);
726 foreach (TaskInventoryItem item in m_items.Values)
577 { 727 {
578 foreach (TaskInventoryItem item in m_items.Values) 728 if (item.Name == name)
579 { 729 {
580 if (item.Name == name) 730 m_items.LockItemsForRead(false);
581 return true; 731 return true;
582 } 732 }
583 } 733 }
734 m_items.LockItemsForRead(false);
584 return false; 735 return false;
585 } 736 }
586 737
@@ -622,8 +773,9 @@ namespace OpenSim.Region.Framework.Scenes
622 /// <param name="item"></param> 773 /// <param name="item"></param>
623 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) 774 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop)
624 { 775 {
625 List<TaskInventoryItem> il = GetInventoryItems(); 776 m_items.LockItemsForRead(true);
626 777 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values);
778 m_items.LockItemsForRead(false);
627 foreach (TaskInventoryItem i in il) 779 foreach (TaskInventoryItem i in il)
628 { 780 {
629 if (i.Name == item.Name) 781 if (i.Name == item.Name)
@@ -661,16 +813,16 @@ namespace OpenSim.Region.Framework.Scenes
661 item.Name = name; 813 item.Name = name;
662 item.GroupID = m_part.GroupID; 814 item.GroupID = m_part.GroupID;
663 815
664 lock (m_items) 816 m_items.LockItemsForWrite(true);
665 m_items.Add(item.ItemID, item); 817 m_items.Add(item.ItemID, item);
666 818 m_items.LockItemsForWrite(false);
667 if (allowedDrop) 819 if (allowedDrop)
668 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); 820 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP);
669 else 821 else
670 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 822 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
671 823
824 m_part.AggregateInnerPerms();
672 m_inventorySerial++; 825 m_inventorySerial++;
673 //m_inventorySerial += 2;
674 HasInventoryChanged = true; 826 HasInventoryChanged = true;
675 m_part.ParentGroup.HasGroupChanged = true; 827 m_part.ParentGroup.HasGroupChanged = true;
676 } 828 }
@@ -684,15 +836,15 @@ namespace OpenSim.Region.Framework.Scenes
684 /// <param name="items"></param> 836 /// <param name="items"></param>
685 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items) 837 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items)
686 { 838 {
687 lock (m_items) 839 m_items.LockItemsForWrite(true);
840 foreach (TaskInventoryItem item in items)
688 { 841 {
689 foreach (TaskInventoryItem item in items) 842 m_items.Add(item.ItemID, item);
690 { 843// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
691 m_items.Add(item.ItemID, item);
692// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
693 }
694 m_inventorySerial++;
695 } 844 }
845 m_items.LockItemsForWrite(false);
846 m_part.AggregateInnerPerms();
847 m_inventorySerial++;
696 } 848 }
697 849
698 /// <summary> 850 /// <summary>
@@ -703,23 +855,24 @@ namespace OpenSim.Region.Framework.Scenes
703 public TaskInventoryItem GetInventoryItem(UUID itemId) 855 public TaskInventoryItem GetInventoryItem(UUID itemId)
704 { 856 {
705 TaskInventoryItem item; 857 TaskInventoryItem item;
706 858 m_items.LockItemsForRead(true);
707 lock (m_items) 859 m_items.TryGetValue(itemId, out item);
708 m_items.TryGetValue(itemId, out item); 860 m_items.LockItemsForRead(false);
709
710 return item; 861 return item;
711 } 862 }
712 863
713 public TaskInventoryItem GetInventoryItem(string name) 864 public TaskInventoryItem GetInventoryItem(string name)
714 { 865 {
715 lock (m_items) 866 m_items.LockItemsForRead(true);
867 foreach (TaskInventoryItem item in m_items.Values)
716 { 868 {
717 foreach (TaskInventoryItem item in m_items.Values) 869 if (item.Name == name)
718 { 870 {
719 if (item.Name == name) 871 m_items.LockItemsForRead(false);
720 return item; 872 return item;
721 } 873 }
722 } 874 }
875 m_items.LockItemsForRead(false);
723 876
724 return null; 877 return null;
725 } 878 }
@@ -728,41 +881,45 @@ namespace OpenSim.Region.Framework.Scenes
728 { 881 {
729 List<TaskInventoryItem> items = new List<TaskInventoryItem>(); 882 List<TaskInventoryItem> items = new List<TaskInventoryItem>();
730 883
731 lock (m_items) 884 m_items.LockItemsForRead(true);
885
886 foreach (TaskInventoryItem item in m_items.Values)
732 { 887 {
733 foreach (TaskInventoryItem item in m_items.Values) 888 if (item.Name == name)
734 { 889 items.Add(item);
735 if (item.Name == name)
736 items.Add(item);
737 }
738 } 890 }
739 891
892 m_items.LockItemsForRead(false);
893
740 return items; 894 return items;
741 } 895 }
742 896
743 public bool GetRezReadySceneObjects(TaskInventoryItem item, out List<SceneObjectGroup> objlist, out List<Vector3> veclist) 897 public bool GetRezReadySceneObjects(TaskInventoryItem item, out List<SceneObjectGroup> objlist, out List<Vector3> veclist, out Vector3 bbox, out float offsetHeight)
744 { 898 {
745 AssetBase rezAsset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); 899 AssetBase rezAsset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
746 900
747 if (null == rezAsset) 901 if (null == rezAsset)
748 { 902 {
749 m_log.WarnFormat( 903 m_log.WarnFormat(
750 "[PRIM INVENTORY]: Could not find asset {0} for inventory item {1} in {2}", 904 "[PRIM INVENTORY]: Could not find asset {0} for inventory item {1} in {2}",
751 item.AssetID, item.Name, m_part.Name); 905 item.AssetID, item.Name, m_part.Name);
752 objlist = null; 906 objlist = null;
753 veclist = null; 907 veclist = null;
908 bbox = Vector3.Zero;
909 offsetHeight = 0;
754 return false; 910 return false;
755 } 911 }
756 912
757 Vector3 bbox; 913 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 914
762 for (int i = 0; i < objlist.Count; i++) 915 for (int i = 0; i < objlist.Count; i++)
763 { 916 {
764 SceneObjectGroup group = objlist[i]; 917 SceneObjectGroup group = objlist[i];
765 918/*
919 group.RootPart.AttachPoint = group.RootPart.Shape.State;
920 group.RootPart.AttachedPos = group.AbsolutePosition;
921 group.RootPart.AttachRotation = group.GroupRotation;
922*/
766 group.ResetIDs(); 923 group.ResetIDs();
767 924
768 SceneObjectPart rootPart = group.GetPart(group.UUID); 925 SceneObjectPart rootPart = group.GetPart(group.UUID);
@@ -771,12 +928,14 @@ namespace OpenSim.Region.Framework.Scenes
771 // in the serialization, transfer the correct name from the inventory to the 928 // in the serialization, transfer the correct name from the inventory to the
772 // object itself before we rez. 929 // object itself before we rez.
773 // Only do these for the first object if we are rezzing a coalescence. 930 // Only do these for the first object if we are rezzing a coalescence.
774 if (i == 0) 931 // nahh dont mess with coalescence objects,
932 // the name in inventory can be change for inventory purpuses only
933 if (objlist.Count == 1)
775 { 934 {
776 rootPart.Name = item.Name; 935 rootPart.Name = item.Name;
777 rootPart.Description = item.Description; 936 rootPart.Description = item.Description;
778 } 937 }
779 938/* reverted to old code till part.ApplyPermissionsOnRez is better reviewed/fixed
780 group.SetGroup(m_part.GroupID, null); 939 group.SetGroup(m_part.GroupID, null);
781 940
782 foreach (SceneObjectPart part in group.Parts) 941 foreach (SceneObjectPart part in group.Parts)
@@ -792,13 +951,55 @@ namespace OpenSim.Region.Framework.Scenes
792 951
793 part.ApplyPermissionsOnRez(dest, false, m_part.ParentGroup.Scene); 952 part.ApplyPermissionsOnRez(dest, false, m_part.ParentGroup.Scene);
794 } 953 }
954*/
955// old code start
956 SceneObjectPart[] partList = group.Parts;
795 957
958 group.SetGroup(m_part.GroupID, null);
959
960 if ((rootPart.OwnerID != item.OwnerID) || (item.CurrentPermissions & (uint)PermissionMask.Slam) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0)
961 {
962 if (m_part.ParentGroup.Scene.Permissions.PropagatePermissions())
963 {
964 foreach (SceneObjectPart part in partList)
965 {
966 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
967 part.EveryoneMask = item.EveryonePermissions;
968 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
969 part.NextOwnerMask = item.NextPermissions;
970 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
971 part.GroupMask = item.GroupPermissions;
972 }
973
974 group.ApplyNextOwnerPermissions();
975 }
976 }
977
978 foreach (SceneObjectPart part in partList)
979 {
980 if ((part.OwnerID != item.OwnerID) || (item.CurrentPermissions & (uint)PermissionMask.Slam) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0)
981 {
982 if(part.GroupID != part.OwnerID)
983 part.LastOwnerID = part.OwnerID;
984 part.OwnerID = item.OwnerID;
985 part.Inventory.ChangeInventoryOwner(item.OwnerID);
986 }
987
988 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
989 part.EveryoneMask = item.EveryonePermissions;
990 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
991 part.NextOwnerMask = item.NextPermissions;
992 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
993 part.GroupMask = item.GroupPermissions;
994 }
995// old code end
796 rootPart.TrimPermissions(); 996 rootPart.TrimPermissions();
997 group.InvalidateDeepEffectivePerms();
797 } 998 }
798 999
799 return true; 1000 return true;
800 } 1001 }
801 1002
802 /// <summary> 1003 /// <summary>
803 /// Update an existing inventory item. 1004 /// Update an existing inventory item.
804 /// </summary> 1005 /// </summary>
@@ -817,11 +1018,12 @@ namespace OpenSim.Region.Framework.Scenes
817 1018
818 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged) 1019 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
819 { 1020 {
820 TaskInventoryItem it = GetInventoryItem(item.ItemID); 1021 m_items.LockItemsForWrite(true);
821 if (it != null) 1022
1023 if (m_items.ContainsKey(item.ItemID))
822 { 1024 {
823// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name); 1025// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name);
824 1026
825 item.ParentID = m_part.UUID; 1027 item.ParentID = m_part.UUID;
826 item.ParentPartID = m_part.UUID; 1028 item.ParentPartID = m_part.UUID;
827 1029
@@ -830,24 +1032,26 @@ namespace OpenSim.Region.Framework.Scenes
830 if (item.GroupPermissions != (uint)PermissionMask.None) 1032 if (item.GroupPermissions != (uint)PermissionMask.None)
831 item.GroupID = m_part.GroupID; 1033 item.GroupID = m_part.GroupID;
832 1034
1035 if(item.OwnerID == UUID.Zero) // viewer to internal enconding of group owned
1036 item.OwnerID = item.GroupID;
1037
833 if (item.AssetID == UUID.Zero) 1038 if (item.AssetID == UUID.Zero)
834 item.AssetID = it.AssetID; 1039 item.AssetID = m_items[item.ItemID].AssetID;
835 1040
836 lock (m_items) 1041 m_items[item.ItemID] = item;
837 { 1042
838 m_items[item.ItemID] = item; 1043 m_inventorySerial++;
839 m_inventorySerial++;
840 }
841
842 if (fireScriptEvents) 1044 if (fireScriptEvents)
843 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 1045 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
844 1046
845 if (considerChanged) 1047 if (considerChanged)
846 { 1048 {
1049 m_part.ParentGroup.InvalidateDeepEffectivePerms();
847 HasInventoryChanged = true; 1050 HasInventoryChanged = true;
848 m_part.ParentGroup.HasGroupChanged = true; 1051 m_part.ParentGroup.HasGroupChanged = true;
849 } 1052 }
850 1053 m_items.LockItemsForWrite(false);
1054
851 return true; 1055 return true;
852 } 1056 }
853 else 1057 else
@@ -855,11 +1059,12 @@ namespace OpenSim.Region.Framework.Scenes
855 m_log.ErrorFormat( 1059 m_log.ErrorFormat(
856 "[PRIM INVENTORY]: " + 1060 "[PRIM INVENTORY]: " +
857 "Tried to retrieve item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory", 1061 "Tried to retrieve item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory",
858 item.ItemID, m_part.Name, m_part.UUID, 1062 item.ItemID, m_part.Name, m_part.UUID,
859 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 1063 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
860 } 1064 }
861 return false; 1065 m_items.LockItemsForWrite(false);
862 1066
1067 return false;
863 } 1068 }
864 1069
865 /// <summary> 1070 /// <summary>
@@ -870,160 +1075,194 @@ namespace OpenSim.Region.Framework.Scenes
870 /// in this prim's inventory.</returns> 1075 /// in this prim's inventory.</returns>
871 public int RemoveInventoryItem(UUID itemID) 1076 public int RemoveInventoryItem(UUID itemID)
872 { 1077 {
873 TaskInventoryItem item = GetInventoryItem(itemID); 1078 m_items.LockItemsForRead(true);
874 if (item != null) 1079
1080 if (m_items.ContainsKey(itemID))
875 { 1081 {
876 int type = m_items[itemID].InvType; 1082 int type = m_items[itemID].InvType;
877 if (type == 10) // Script 1083 m_items.LockItemsForRead(false);
1084 if (type == (int)InventoryType.LSL) // Script
878 { 1085 {
879 // route it through here, to handle script cleanup tasks 1086 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
880 RemoveScriptInstance(itemID, false);
881 } 1087 }
1088 m_items.LockItemsForWrite(true);
882 m_items.Remove(itemID); 1089 m_items.Remove(itemID);
1090 m_items.LockItemsForWrite(false);
1091
1092 m_part.ParentGroup.InvalidateDeepEffectivePerms();
1093
883 m_inventorySerial++; 1094 m_inventorySerial++;
884 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 1095 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
885 1096
886 HasInventoryChanged = true; 1097 HasInventoryChanged = true;
887 m_part.ParentGroup.HasGroupChanged = true; 1098 m_part.ParentGroup.HasGroupChanged = true;
888 1099
889 if (!ContainsScripts()) 1100 int scriptcount = 0;
1101 m_items.LockItemsForRead(true);
1102 foreach (TaskInventoryItem item in m_items.Values)
1103 {
1104 if (item.Type == (int)InventoryType.LSL)
1105 {
1106 scriptcount++;
1107 }
1108 }
1109 m_items.LockItemsForRead(false);
1110
1111
1112 if (scriptcount <= 0)
1113 {
890 m_part.RemFlag(PrimFlags.Scripted); 1114 m_part.RemFlag(PrimFlags.Scripted);
1115 }
891 1116
892 m_part.ScheduleFullUpdate(); 1117 m_part.ScheduleFullUpdate();
893 1118
894 return type; 1119 return type;
895
896 } 1120 }
897 else 1121 else
898 { 1122 {
1123 m_items.LockItemsForRead(false);
899 m_log.ErrorFormat( 1124 m_log.ErrorFormat(
900 "[PRIM INVENTORY]: " + 1125 "[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", 1126 "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, 1127 itemID, m_part.Name, m_part.UUID);
903 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
904 } 1128 }
905 1129
906 return -1; 1130 return -1;
907 } 1131 }
908 1132
909 private bool CreateInventoryFile()
910 {
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 1133
915 if (m_inventoryFileName == String.Empty || 1134 /// <summary>
916 m_inventoryFileNameSerial < m_inventorySerial) 1135 /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client
1136 /// </summary>
1137 /// <param name="xferManager"></param>
1138 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
1139 {
1140 lock (m_inventoryFileLock)
917 { 1141 {
918 // Something changed, we need to create a new file 1142 bool changed = false;
919 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp";
920 m_inventoryFileNameSerial = m_inventorySerial;
921 1143
922 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero); 1144 m_items.LockItemsForRead(true);
923 1145
924 lock (m_items) 1146 if (m_inventorySerial == 0) // No inventory
925 { 1147 {
926 foreach (TaskInventoryItem item in m_items.Values) 1148 m_items.LockItemsForRead(false);
927 { 1149 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
928// m_log.DebugFormat( 1150 return;
929// "[PRIM INVENTORY]: Adding item {0} {1} for serial {2} on prim {3} {4} {5}", 1151 }
930// item.Name, item.ItemID, m_inventorySerial, m_part.Name, m_part.UUID, m_part.LocalId);
931 1152
932 UUID ownerID = item.OwnerID; 1153 if (m_items.Count == 0) // No inventory
933 uint everyoneMask = 0; 1154 {
934 uint baseMask = item.BasePermissions; 1155 m_items.LockItemsForRead(false);
935 uint ownerMask = item.CurrentPermissions; 1156 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
936 uint groupMask = item.GroupPermissions; 1157 return;
1158 }
937 1159
938 invString.AddItemStart(); 1160 if (m_inventoryFileNameSerial != m_inventorySerial)
939 invString.AddNameValueLine("item_id", item.ItemID.ToString()); 1161 {
940 invString.AddNameValueLine("parent_id", m_part.UUID.ToString()); 1162 m_inventoryFileNameSerial = m_inventorySerial;
1163 changed = true;
1164 }
941 1165
942 invString.AddPermissionsStart(); 1166 m_items.LockItemsForRead(false);
943 1167
944 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); 1168 if (m_inventoryFileData.Length < 2)
945 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); 1169 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 1170
950 invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); 1171 bool includeAssets = false;
951 invString.AddNameValueLine("owner_id", ownerID.ToString()); 1172 if (m_part.ParentGroup.Scene.Permissions.CanEditObjectInventory(m_part.UUID, client.AgentId))
1173 includeAssets = true;
952 1174
953 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); 1175 if (m_inventoryPrivileged != includeAssets)
1176 changed = true;
954 1177
955 invString.AddNameValueLine("group_id", item.GroupID.ToString()); 1178 if (!changed)
956 invString.AddSectionEnd(); 1179 {
1180 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
1181 client.SendTaskInventory(m_part.UUID, (short)m_inventoryFileNameSerial,
1182 m_inventoryFileNameBytes);
957 1183
958 invString.AddNameValueLine("asset_id", item.AssetID.ToString()); 1184 return;
959 invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type)); 1185 }
960 invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType));
961 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
962 1186
963 invString.AddSaleStart(); 1187 m_inventoryPrivileged = includeAssets;
964 invString.AddNameValueLine("sale_type", "not");
965 invString.AddNameValueLine("sale_price", "0");
966 invString.AddSectionEnd();
967 1188
968 invString.AddNameValueLine("name", item.Name + "|"); 1189 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
969 invString.AddNameValueLine("desc", item.Description + "|");
970 1190
971 invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); 1191 m_items.LockItemsForRead(true);
972 invString.AddSectionEnd();
973 }
974 }
975 1192
976 m_inventoryFileData = Utils.StringToBytes(invString.BuildString); 1193 foreach (TaskInventoryItem item in m_items.Values)
1194 {
1195 UUID ownerID = item.OwnerID;
1196 UUID groupID = item.GroupID;
1197 uint everyoneMask = item.EveryonePermissions;
1198 uint baseMask = item.BasePermissions;
1199 uint ownerMask = item.CurrentPermissions;
1200 uint groupMask = item.GroupPermissions;
977 1201
978 return true; 1202 invString.AddItemStart();
979 } 1203 invString.AddNameValueLine("item_id", item.ItemID.ToString());
1204 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
980 1205
981 // No need to recreate, the existing file is fine 1206 invString.AddPermissionsStart();
982 return false;
983 }
984 1207
985 /// <summary> 1208 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
986 /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client 1209 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
987 /// </summary> 1210 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
988 /// <param name="xferManager"></param> 1211 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
989 public void RequestInventoryFile(IClientAPI client, IXfer xferManager) 1212 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
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 {
997// m_log.DebugFormat(
998// "[PRIM INVENTORY]: Not sending inventory data for part {0} {1} {2} for {3} since no items",
999// m_part.Name, m_part.LocalId, m_part.UUID, client.Name);
1000 1213
1001 client.SendTaskInventory(m_part.UUID, 0, new byte[0]); 1214 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
1002 return; 1215
1216 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
1217
1218 invString.AddNameValueLine("group_id",groupID.ToString());
1219 if(groupID != UUID.Zero && ownerID == groupID)
1220 {
1221 invString.AddNameValueLine("owner_id", UUID.Zero.ToString());
1222 invString.AddNameValueLine("group_owned","1");
1223 }
1224 else
1225 {
1226 invString.AddNameValueLine("owner_id", ownerID.ToString());
1227 invString.AddNameValueLine("group_owned","0");
1228 }
1229
1230 invString.AddSectionEnd();
1231
1232 if (includeAssets)
1233 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
1234 else
1235 invString.AddNameValueLine("asset_id", UUID.Zero.ToString());
1236 invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type));
1237 invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType));
1238 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
1239
1240 invString.AddSaleStart();
1241 invString.AddNameValueLine("sale_type", "not");
1242 invString.AddNameValueLine("sale_price", "0");
1243 invString.AddSectionEnd();
1244
1245 invString.AddNameValueLine("name", item.Name + "|");
1246 invString.AddNameValueLine("desc", item.Description + "|");
1247
1248 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
1249 invString.AddSectionEnd();
1003 } 1250 }
1004 1251
1005 CreateInventoryFile(); 1252 m_items.LockItemsForRead(false);
1006 1253
1007 // In principle, we should only do the rest if the inventory changed; 1254 m_inventoryFileData = Utils.StringToBytes(invString.GetString());
1008 // by sending m_inventorySerial to the client, it ought to know 1255
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) 1256 if (m_inventoryFileData.Length > 2)
1015 { 1257 {
1016 // Add the file for Xfer 1258 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp";
1017 // m_log.DebugFormat( 1259 m_inventoryFileNameBytes = Util.StringToBytes256(m_inventoryFileName);
1018 // "[PRIM INVENTORY]: Adding inventory file {0} (length {1}) for transfer on {2} {3} {4}",
1019 // m_inventoryFileName, m_inventoryFileData.Length, m_part.Name, m_part.UUID, m_part.LocalId);
1020
1021 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData); 1260 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
1261 client.SendTaskInventory(m_part.UUID, (short)m_inventoryFileNameSerial,m_inventoryFileNameBytes);
1262 return;
1022 } 1263 }
1023 1264
1024 // Tell the client we're ready to Xfer the file 1265 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1025 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
1026 Util.StringToBytes256(m_inventoryFileName));
1027 } 1266 }
1028 } 1267 }
1029 1268
@@ -1033,67 +1272,80 @@ namespace OpenSim.Region.Framework.Scenes
1033 /// <param name="datastore"></param> 1272 /// <param name="datastore"></param>
1034 public void ProcessInventoryBackup(ISimulationDataService datastore) 1273 public void ProcessInventoryBackup(ISimulationDataService datastore)
1035 { 1274 {
1036 if (HasInventoryChanged) 1275// Removed this because linking will cause an immediate delete of the new
1037 { 1276// child prim from the database and the subsequent storing of the prim sees
1277// the inventory of it as unchanged and doesn't store it at all. The overhead
1278// of storing prim inventory needlessly is much less than the aggravation
1279// of prim inventory loss.
1280// if (HasInventoryChanged)
1281// {
1282 m_items.LockItemsForRead(true);
1283 ICollection<TaskInventoryItem> itemsvalues = m_items.Values;
1038 HasInventoryChanged = false; 1284 HasInventoryChanged = false;
1039 List<TaskInventoryItem> items = GetInventoryItems(); 1285 m_items.LockItemsForRead(false);
1040 datastore.StorePrimInventory(m_part.UUID, items); 1286 try
1041 1287 {
1042 } 1288 datastore.StorePrimInventory(m_part.UUID, itemsvalues);
1289 }
1290 catch {}
1291// }
1043 } 1292 }
1044 1293
1045 public class InventoryStringBuilder 1294 public class InventoryStringBuilder
1046 { 1295 {
1047 public string BuildString = String.Empty; 1296 private StringBuilder BuildString = new StringBuilder(1024);
1048 1297
1049 public InventoryStringBuilder(UUID folderID, UUID parentID) 1298 public InventoryStringBuilder(UUID folderID, UUID parentID)
1050 { 1299 {
1051 BuildString += "\tinv_object\t0\n\t{\n"; 1300 BuildString.Append("\tinv_object\t0\n\t{\n");
1052 AddNameValueLine("obj_id", folderID.ToString()); 1301 AddNameValueLine("obj_id", folderID.ToString());
1053 AddNameValueLine("parent_id", parentID.ToString()); 1302 AddNameValueLine("parent_id", parentID.ToString());
1054 AddNameValueLine("type", "category"); 1303 AddNameValueLine("type", "category");
1055 AddNameValueLine("name", "Contents|"); 1304 AddNameValueLine("name", "Contents|\n\t}");
1056 AddSectionEnd();
1057 } 1305 }
1058 1306
1059 public void AddItemStart() 1307 public void AddItemStart()
1060 { 1308 {
1061 BuildString += "\tinv_item\t0\n"; 1309 BuildString.Append("\tinv_item\t0\n\t{\n");
1062 AddSectionStart();
1063 } 1310 }
1064 1311
1065 public void AddPermissionsStart() 1312 public void AddPermissionsStart()
1066 { 1313 {
1067 BuildString += "\tpermissions 0\n"; 1314 BuildString.Append("\tpermissions 0\n\t{\n");
1068 AddSectionStart();
1069 } 1315 }
1070 1316
1071 public void AddSaleStart() 1317 public void AddSaleStart()
1072 { 1318 {
1073 BuildString += "\tsale_info\t0\n"; 1319 BuildString.Append("\tsale_info\t0\n\t{\n");
1074 AddSectionStart();
1075 } 1320 }
1076 1321
1077 protected void AddSectionStart() 1322 protected void AddSectionStart()
1078 { 1323 {
1079 BuildString += "\t{\n"; 1324 BuildString.Append("\t{\n");
1080 } 1325 }
1081 1326
1082 public void AddSectionEnd() 1327 public void AddSectionEnd()
1083 { 1328 {
1084 BuildString += "\t}\n"; 1329 BuildString.Append("\t}\n");
1085 } 1330 }
1086 1331
1087 public void AddLine(string addLine) 1332 public void AddLine(string addLine)
1088 { 1333 {
1089 BuildString += addLine; 1334 BuildString.Append(addLine);
1090 } 1335 }
1091 1336
1092 public void AddNameValueLine(string name, string value) 1337 public void AddNameValueLine(string name, string value)
1093 { 1338 {
1094 BuildString += "\t\t"; 1339 BuildString.Append("\t\t");
1095 BuildString += name + "\t"; 1340 BuildString.Append(name);
1096 BuildString += value + "\n"; 1341 BuildString.Append("\t");
1342 BuildString.Append(value);
1343 BuildString.Append("\n");
1344 }
1345
1346 public String GetString()
1347 {
1348 return BuildString.ToString();
1097 } 1349 }
1098 1350
1099 public void Close() 1351 public void Close()
@@ -1101,71 +1353,74 @@ namespace OpenSim.Region.Framework.Scenes
1101 } 1353 }
1102 } 1354 }
1103 1355
1356 public void AggregateInnerPerms(ref uint owner, ref uint group, ref uint everyone)
1357 {
1358 foreach (TaskInventoryItem item in m_items.Values)
1359 {
1360 if(item.InvType == (sbyte)InventoryType.Landmark)
1361 continue;
1362 owner &= item.CurrentPermissions;
1363 group &= item.GroupPermissions;
1364 everyone &= item.EveryonePermissions;
1365 }
1366 }
1367
1104 public uint MaskEffectivePermissions() 1368 public uint MaskEffectivePermissions()
1105 { 1369 {
1370 // used to propagate permissions restrictions outwards
1371 // Modify does not propagate outwards.
1106 uint mask=0x7fffffff; 1372 uint mask=0x7fffffff;
1107 1373
1108 lock (m_items) 1374 foreach (TaskInventoryItem item in m_items.Values)
1109 { 1375 {
1110 foreach (TaskInventoryItem item in m_items.Values) 1376 if(item.InvType == (sbyte)InventoryType.Landmark)
1111 { 1377 continue;
1112 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0) 1378
1113 mask &= ~((uint)PermissionMask.Copy >> 13); 1379 // apply current to normal permission bits
1114 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0) 1380 uint newperms = item.CurrentPermissions;
1115 mask &= ~((uint)PermissionMask.Transfer >> 13); 1381
1116 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0) 1382 if ((newperms & (uint)PermissionMask.Copy) == 0)
1117 mask &= ~((uint)PermissionMask.Modify >> 13); 1383 mask &= ~(uint)PermissionMask.Copy;
1118 1384 if ((newperms & (uint)PermissionMask.Transfer) == 0)
1119 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) 1385 mask &= ~(uint)PermissionMask.Transfer;
1120 mask &= ~(uint)PermissionMask.Copy; 1386 if ((newperms & (uint)PermissionMask.Export) == 0)
1121 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0) 1387 mask &= ~((uint)PermissionMask.Export);
1122 mask &= ~(uint)PermissionMask.Transfer; 1388
1123 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0) 1389 // apply next owner restricted by current to folded bits
1124 mask &= ~(uint)PermissionMask.Modify; 1390 newperms &= item.NextPermissions;
1125 } 1391
1392 if ((newperms & (uint)PermissionMask.Copy) == 0)
1393 mask &= ~((uint)PermissionMask.FoldedCopy);
1394 if ((newperms & (uint)PermissionMask.Transfer) == 0)
1395 mask &= ~((uint)PermissionMask.FoldedTransfer);
1396 if ((newperms & (uint)PermissionMask.Export) == 0)
1397 mask &= ~((uint)PermissionMask.FoldedExport);
1398
1126 } 1399 }
1127
1128 return mask; 1400 return mask;
1129 } 1401 }
1130 1402
1131 public void ApplyNextOwnerPermissions() 1403 public void ApplyNextOwnerPermissions()
1132 { 1404 {
1133 lock (m_items) 1405 foreach (TaskInventoryItem item in m_items.Values)
1134 { 1406 {
1135 foreach (TaskInventoryItem item in m_items.Values) 1407 item.CurrentPermissions &= item.NextPermissions;
1136 { 1408 item.BasePermissions &= item.NextPermissions;
1137// m_log.DebugFormat ( 1409 item.EveryonePermissions &= item.NextPermissions;
1138// "[SCENE OBJECT PART INVENTORY]: Applying next permissions {0} to {1} in {2} with current {3}, base {4}, everyone {5}", 1410 item.OwnerChanged = true;
1139// item.NextPermissions, item.Name, m_part.Name, item.CurrentPermissions, item.BasePermissions, item.EveryonePermissions); 1411 item.PermsMask = 0;
1140 1412 item.PermsGranter = UUID.Zero;
1141 if (item.InvType == (int)InventoryType.Object)
1142 {
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 }
1155 } 1413 }
1156 } 1414 }
1157 1415
1158 public void ApplyGodPermissions(uint perms) 1416 public void ApplyGodPermissions(uint perms)
1159 { 1417 {
1160 lock (m_items) 1418 foreach (TaskInventoryItem item in m_items.Values)
1161 { 1419 {
1162 foreach (TaskInventoryItem item in m_items.Values) 1420 item.CurrentPermissions = perms;
1163 { 1421 item.BasePermissions = perms;
1164 item.CurrentPermissions = perms;
1165 item.BasePermissions = perms;
1166 }
1167 } 1422 }
1168 1423
1169 m_inventorySerial++; 1424 m_inventorySerial++;
1170 HasInventoryChanged = true; 1425 HasInventoryChanged = true;
1171 } 1426 }
@@ -1176,14 +1431,11 @@ namespace OpenSim.Region.Framework.Scenes
1176 /// <returns></returns> 1431 /// <returns></returns>
1177 public bool ContainsScripts() 1432 public bool ContainsScripts()
1178 { 1433 {
1179 lock (m_items) 1434 foreach (TaskInventoryItem item in m_items.Values)
1180 { 1435 {
1181 foreach (TaskInventoryItem item in m_items.Values) 1436 if (item.InvType == (int)InventoryType.LSL)
1182 { 1437 {
1183 if (item.InvType == (int)InventoryType.LSL) 1438 return true;
1184 {
1185 return true;
1186 }
1187 } 1439 }
1188 } 1440 }
1189 1441
@@ -1197,17 +1449,13 @@ namespace OpenSim.Region.Framework.Scenes
1197 public int ScriptCount() 1449 public int ScriptCount()
1198 { 1450 {
1199 int count = 0; 1451 int count = 0;
1200 lock (m_items) 1452 m_items.LockItemsForRead(true);
1453 foreach (TaskInventoryItem item in m_items.Values)
1201 { 1454 {
1202 foreach (TaskInventoryItem item in m_items.Values) 1455 if (item.InvType == (int)InventoryType.LSL)
1203 { 1456 count++;
1204 if (item.InvType == (int)InventoryType.LSL)
1205 {
1206 count++;
1207 }
1208 }
1209 } 1457 }
1210 1458 m_items.LockItemsForRead(false);
1211 return count; 1459 return count;
1212 } 1460 }
1213 /// <summary> 1461 /// <summary>
@@ -1230,9 +1478,7 @@ namespace OpenSim.Region.Framework.Scenes
1230 if (engine != null) 1478 if (engine != null)
1231 { 1479 {
1232 if (engine.GetScriptState(item.ItemID)) 1480 if (engine.GetScriptState(item.ItemID))
1233 {
1234 count++; 1481 count++;
1235 }
1236 } 1482 }
1237 } 1483 }
1238 } 1484 }
@@ -1241,50 +1487,52 @@ namespace OpenSim.Region.Framework.Scenes
1241 1487
1242 public List<UUID> GetInventoryList() 1488 public List<UUID> GetInventoryList()
1243 { 1489 {
1244 List<UUID> ret = new List<UUID>(); 1490 m_items.LockItemsForRead(true);
1245 1491
1246 lock (m_items) 1492 List<UUID> ret = new List<UUID>(m_items.Count);
1247 { 1493 foreach (TaskInventoryItem item in m_items.Values)
1248 foreach (TaskInventoryItem item in m_items.Values) 1494 ret.Add(item.ItemID);
1249 ret.Add(item.ItemID);
1250 }
1251 1495
1496 m_items.LockItemsForRead(false);
1252 return ret; 1497 return ret;
1253 } 1498 }
1254 1499
1255 public List<TaskInventoryItem> GetInventoryItems() 1500 public List<TaskInventoryItem> GetInventoryItems()
1256 { 1501 {
1257 List<TaskInventoryItem> ret = new List<TaskInventoryItem>(); 1502 m_items.LockItemsForRead(true);
1258 1503 List<TaskInventoryItem> ret = new List<TaskInventoryItem>(m_items.Values);
1259 lock (m_items) 1504 m_items.LockItemsForRead(false);
1260 ret = new List<TaskInventoryItem>(m_items.Values);
1261 1505
1262 return ret; 1506 return ret;
1263 } 1507 }
1264 1508
1265 public List<TaskInventoryItem> GetInventoryItems(InventoryType type) 1509 public List<TaskInventoryItem> GetInventoryItems(InventoryType type)
1266 { 1510 {
1267 List<TaskInventoryItem> ret = new List<TaskInventoryItem>(); 1511 m_items.LockItemsForRead(true);
1268 1512
1269 lock (m_items) 1513 List<TaskInventoryItem> ret = new List<TaskInventoryItem>(m_items.Count);
1270 { 1514 foreach (TaskInventoryItem item in m_items.Values)
1271 foreach (TaskInventoryItem item in m_items.Values) 1515 if (item.InvType == (int)type)
1272 if (item.InvType == (int)type) 1516 ret.Add(item);
1273 ret.Add(item);
1274 }
1275 1517
1518 m_items.LockItemsForRead(false);
1276 return ret; 1519 return ret;
1277 } 1520 }
1278 1521
1279 public Dictionary<UUID, string> GetScriptStates() 1522 public Dictionary<UUID, string> GetScriptStates()
1280 { 1523 {
1281 Dictionary<UUID, string> ret = new Dictionary<UUID, string>(); 1524 return GetScriptStates(false);
1282 1525 }
1526
1527 public Dictionary<UUID, string> GetScriptStates(bool oldIDs)
1528 {
1529 Dictionary<UUID, string> ret = new Dictionary<UUID, string>();
1530
1283 if (m_part.ParentGroup.Scene == null) // Group not in a scene 1531 if (m_part.ParentGroup.Scene == null) // Group not in a scene
1284 return ret; 1532 return ret;
1285 1533
1286 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>(); 1534 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
1287 1535
1288 if (engines.Length == 0) // No engine at all 1536 if (engines.Length == 0) // No engine at all
1289 return ret; 1537 return ret;
1290 1538
@@ -1303,17 +1551,24 @@ namespace OpenSim.Region.Framework.Scenes
1303 string n = e.GetXMLState(item.ItemID); 1551 string n = e.GetXMLState(item.ItemID);
1304 if (n != String.Empty) 1552 if (n != String.Empty)
1305 { 1553 {
1306 if (!ret.ContainsKey(item.ItemID)) 1554 if (oldIDs)
1307 ret[item.ItemID] = n; 1555 {
1556 if (!ret.ContainsKey(item.OldItemID))
1557 ret[item.OldItemID] = n;
1558 }
1559 else
1560 {
1561 if (!ret.ContainsKey(item.ItemID))
1562 ret[item.ItemID] = n;
1563 }
1308 break; 1564 break;
1309 } 1565 }
1310 } 1566 }
1311 } 1567 }
1312 } 1568 }
1313
1314 return ret; 1569 return ret;
1315 } 1570 }
1316 1571
1317 public void ResumeScripts() 1572 public void ResumeScripts()
1318 { 1573 {
1319 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>(); 1574 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 1fddd91..74f765d 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -90,7 +90,26 @@ 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 // simple yes or no isGOD from god level >= 200
96 // should only be set by GodController
97 // we have two to suport legacy behaviour
98 // IsViewerUIGod was controlled by viewer in older versions
99 // IsGod may now be also controled by viewer acording to options
100 public bool IsViewerUIGod { get; set; }
101 public bool IsGod { get; set; }
102
103 private PresenceType m_presenceType;
104 public PresenceType PresenceType
105 {
106 get {return m_presenceType;}
107 private set
108 {
109 m_presenceType = value;
110 IsNPC = (m_presenceType == PresenceType.Npc);
111 }
112 }
94 113
95 private ScenePresenceStateMachine m_stateMachine; 114 private ScenePresenceStateMachine m_stateMachine;
96 115
@@ -98,8 +117,8 @@ namespace OpenSim.Region.Framework.Scenes
98 /// The current state of this presence. Governs only the existence lifecycle. See ScenePresenceStateMachine 117 /// The current state of this presence. Governs only the existence lifecycle. See ScenePresenceStateMachine
99 /// for more details. 118 /// for more details.
100 /// </summary> 119 /// </summary>
101 public ScenePresenceState LifecycleState 120 public ScenePresenceState LifecycleState
102 { 121 {
103 get 122 get
104 { 123 {
105 return m_stateMachine.GetState(); 124 return m_stateMachine.GetState();
@@ -116,7 +135,7 @@ namespace OpenSim.Region.Framework.Scenes
116 /// the viewer fires these in quick succession. 135 /// the viewer fires these in quick succession.
117 /// </summary> 136 /// </summary>
118 /// <remarks> 137 /// <remarks>
119 /// TODO: The child -> agent transition should be folded into LifecycleState and the CompleteMovement 138 /// TODO: The child -> agent transition should be folded into LifecycleState and the CompleteMovement
120 /// regulation done there. 139 /// regulation done there.
121 /// </remarks> 140 /// </remarks>
122 private object m_completeMovementLock = new object(); 141 private object m_completeMovementLock = new object();
@@ -124,7 +143,7 @@ namespace OpenSim.Region.Framework.Scenes
124// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes(); 143// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes();
125 private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags)); 144 private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags));
126 private static readonly Vector3 HEAD_ADJUSTMENT = new Vector3(0f, 0f, 0.3f); 145 private static readonly Vector3 HEAD_ADJUSTMENT = new Vector3(0f, 0f, 0.3f);
127 146
128 /// <summary> 147 /// <summary>
129 /// Experimentally determined "fudge factor" to make sit-target positions 148 /// Experimentally determined "fudge factor" to make sit-target positions
130 /// the same as in SecondLife. Fudge factor was tested for 36 different 149 /// the same as in SecondLife. Fudge factor was tested for 36 different
@@ -134,21 +153,116 @@ namespace OpenSim.Region.Framework.Scenes
134 /// issue #1716 153 /// issue #1716
135 /// </summary> 154 /// </summary>
136 public static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.4f); 155 public static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.4f);
156 public bool LegacySitOffsets = true;
137 157
138 /// <summary> 158 /// <summary>
139 /// Movement updates for agents in neighboring regions are sent directly to clients. 159 /// Movement updates for agents in neighboring regions are sent directly to clients.
140 /// This value only affects how often agent positions are sent to neighbor regions 160 /// This value only affects how often agent positions are sent to neighbor regions
141 /// for things such as distance-based update prioritization 161 /// for things such as distance-based update prioritization
162 /// this are the square of real distances
142 /// </summary> 163 /// </summary>
143 public static readonly float SIGNIFICANT_MOVEMENT = 2.0f; 164 public static readonly float MOVEMENT = .25f;
165 public static readonly float SIGNIFICANT_MOVEMENT = 16.0f;
166 public static readonly float CHILDUPDATES_MOVEMENT = 100.0f;
167 public static readonly float CHILDUPDATES_TIME = 2000f; // min time between child updates (ms)
144 168
145 public UUID currentParcelUUID = UUID.Zero; 169 private UUID m_previusParcelUUID = UUID.Zero;
170 private UUID m_currentParcelUUID = UUID.Zero;
171 private bool m_previusParcelHide = false;
172 private bool m_currentParcelHide = false;
173 private object parcelLock = new Object();
174 public double ParcelDwellTickMS;
175
176 public UUID currentParcelUUID
177 {
178 get { return m_currentParcelUUID; }
179 set
180 {
181 lock (parcelLock)
182 {
183 bool oldhide = m_currentParcelHide;
184 bool checksame = true;
185 if (value != m_currentParcelUUID)
186 {
187 ParcelDwellTickMS = Util.GetTimeStampMS();
188 m_previusParcelHide = m_currentParcelHide;
189 m_previusParcelUUID = m_currentParcelUUID;
190 checksame = false;
191 }
192 m_currentParcelUUID = value;
193 m_currentParcelHide = false;
194
195 ILandObject land = m_scene.LandChannel.GetLandObject(AbsolutePosition.X, AbsolutePosition.Y);
196 if (land != null && !land.LandData.SeeAVs)
197 m_currentParcelHide = true;
198
199 if (m_previusParcelUUID != UUID.Zero || checksame)
200 ParcelCrossCheck(m_currentParcelUUID, m_previusParcelUUID, m_currentParcelHide, m_previusParcelHide, oldhide,checksame);
201 }
202 }
203 }
204
205 public void sitSOGmoved()
206 {
207/*
208 if (IsDeleted || !IsSatOnObject)
209 //what me? nahh
210 return;
211 if (IsInTransit)
212 return;
213
214 ILandObject land = m_scene.LandChannel.GetLandObject(AbsolutePosition.X, AbsolutePosition.Y);
215 if (land == null)
216 return; //??
217 UUID parcelID = land.LandData.GlobalID;
218 if (m_currentParcelUUID != parcelID)
219 currentParcelUUID = parcelID;
220*/
221 }
222
223 public bool ParcelAllowThisAvatarSounds
224 {
225 get
226 {
227 try
228 {
229 lock (parcelLock)
230 {
231 ILandObject land = m_scene.LandChannel.GetLandObject(AbsolutePosition.X, AbsolutePosition.Y);
232 if (land == null)
233 return true;
234 if (land.LandData.AnyAVSounds)
235 return true;
236 if (!land.LandData.GroupAVSounds)
237 return false;
238 return ControllingClient.IsGroupMember(land.LandData.GroupID);
239 }
240 }
241 catch
242 {
243 return true;
244 }
245 }
246 }
247
248 public bool ParcelHideThisAvatar
249 {
250 get
251 {
252 return m_currentParcelHide;
253 }
254 }
146 255
147 /// <value> 256 /// <value>
148 /// The animator for this avatar 257 /// The animator for this avatar
149 /// </value> 258 /// </value>
150 public ScenePresenceAnimator Animator { get; private set; } 259 public ScenePresenceAnimator Animator { get; private set; }
151 260
261 /// <value>
262 /// Server Side Animation Override
263 /// </value>
264 public MovementAnimationOverrides Overrides { get; private set; }
265 public String sitAnimation = "SIT";
152 /// <summary> 266 /// <summary>
153 /// Attachments recorded on this avatar. 267 /// Attachments recorded on this avatar.
154 /// </summary> 268 /// </summary>
@@ -164,21 +278,19 @@ namespace OpenSim.Region.Framework.Scenes
164 private ScriptControlled IgnoredControls = ScriptControlled.CONTROL_ZERO; 278 private ScriptControlled IgnoredControls = ScriptControlled.CONTROL_ZERO;
165 private ScriptControlled LastCommands = ScriptControlled.CONTROL_ZERO; 279 private ScriptControlled LastCommands = ScriptControlled.CONTROL_ZERO;
166 private bool MouseDown = false; 280 private bool MouseDown = false;
167// private SceneObjectGroup proxyObjectGroup;
168 //private SceneObjectPart proxyObjectPart = null;
169 public Vector3 lastKnownAllowedPosition; 281 public Vector3 lastKnownAllowedPosition;
170 public bool sentMessageAboutRestrictedParcelFlyingDown; 282 public bool sentMessageAboutRestrictedParcelFlyingDown;
283
171 public Vector4 CollisionPlane = Vector4.UnitW; 284 public Vector4 CollisionPlane = Vector4.UnitW;
172 285
286 public Vector4 m_lastCollisionPlane = Vector4.UnitW;
287 private byte m_lastState;
173 private Vector3 m_lastPosition; 288 private Vector3 m_lastPosition;
174 private Quaternion m_lastRotation; 289 private Quaternion m_lastRotation;
175 private Vector3 m_lastVelocity; 290 private Vector3 m_lastVelocity;
176 private Vector3 m_lastSize = new Vector3(0.45f,0.6f,1.9f); 291 private Vector3 m_lastSize = new Vector3(0.45f,0.6f,1.9f);
292 private bool SentInitialData = false;
177 293
178 private bool m_followCamAuto = false;
179
180
181 private Vector3? m_forceToApply;
182 private int m_userFlags; 294 private int m_userFlags;
183 public int UserFlags 295 public int UserFlags
184 { 296 {
@@ -192,23 +304,14 @@ namespace OpenSim.Region.Framework.Scenes
192 set { PhysicsActor.Flying = value; } 304 set { PhysicsActor.Flying = value; }
193 } 305 }
194 306
195 // add for fly velocity control 307 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 { 308 {
204 get { return PhysicsActor != null && PhysicsActor.IsColliding; } 309 get { return PhysicsActor != null && PhysicsActor.IsColliding; }
205 // We would expect setting IsColliding to be private but it's used by a hack in Scene 310 // We would expect setting IsColliding to be private but it's used by a hack in Scene
206 set { PhysicsActor.IsColliding = value; } 311 set { PhysicsActor.IsColliding = value; }
207 } 312 }
208 313
209// private int m_lastColCount = -1; //KF: Look for Collision chnages 314 private List<uint> m_lastColliders = new List<uint>();
210// 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
212 315
213 private TeleportFlags m_teleportFlags; 316 private TeleportFlags m_teleportFlags;
214 public TeleportFlags TeleportFlags 317 public TeleportFlags TeleportFlags
@@ -233,9 +336,18 @@ namespace OpenSim.Region.Framework.Scenes
233 336
234 private float m_sitAvatarHeight = 2.0f; 337 private float m_sitAvatarHeight = 2.0f;
235 338
339 private bool m_childUpdatesBusy = false;
340 private int m_lastChildUpdatesTime;
341 private int m_lastChildAgentUpdateGodLevel;
342 private float m_lastChildAgentUpdateDrawDistance;
236 private Vector3 m_lastChildAgentUpdatePosition; 343 private Vector3 m_lastChildAgentUpdatePosition;
237// private Vector3 m_lastChildAgentUpdateCamPosition; 344// private Vector3 m_lastChildAgentUpdateCamPosition;
238 345
346 private Vector3 m_lastCameraRayCastCam;
347 private Vector3 m_lastCameraRayCastPos;
348
349 private float m_FOV = 1.04f;
350
239 private const int LAND_VELOCITYMAG_MAX = 12; 351 private const int LAND_VELOCITYMAG_MAX = 12;
240 352
241 private const float FLY_ROLL_MAX_RADIANS = 1.1f; 353 private const float FLY_ROLL_MAX_RADIANS = 1.1f;
@@ -244,32 +356,51 @@ namespace OpenSim.Region.Framework.Scenes
244 private const float FLY_ROLL_RESET_RADIANS_PER_UPDATE = 0.02f; 356 private const float FLY_ROLL_RESET_RADIANS_PER_UPDATE = 0.02f;
245 357
246 private float m_health = 100f; 358 private float m_health = 100f;
359 private float m_healRate = 1f;
360 private float m_healRatePerFrame = 0.05f;
247 361
248 protected ulong crossingFromRegion; 362 private readonly Vector3[] Dir_Vectors = new Vector3[12];
249 363
250 private readonly Vector3[] Dir_Vectors = new Vector3[11]; 364 protected int m_reprioritizationLastTime;
251 365 protected bool m_reprioritizationBusy;
252 protected Timer m_reprioritization_timer; 366 protected Vector3 m_reprioritizationLastPosition;
253 protected bool m_reprioritizing; 367 protected float m_reprioritizationLastDrawDistance;
254 protected bool m_reprioritization_called;
255 368
256 private Quaternion m_headrotation = Quaternion.Identity; 369 private Quaternion m_headrotation = Quaternion.Identity;
257 370
258 //PauPaw:Proper PID Controler for autopilot************ 371 //PauPaw:Proper PID Controler for autopilot************
259 public bool MovingToTarget { get; private set; } 372
260 public Vector3 MoveToPositionTarget { get; private set; } 373 private bool m_movingToTarget;
374 public bool MovingToTarget
375 {
376 get {return m_movingToTarget;}
377 private set {m_movingToTarget = value; }
378 }
379
380 private Vector3 m_moveToPositionTarget;
381 public Vector3 MoveToPositionTarget
382 {
383 get {return m_moveToPositionTarget;}
384 private set {m_moveToPositionTarget = value; }
385 }
386
387 private float m_moveToSpeed;
388 public float MoveToSpeed
389 {
390 get {return m_moveToSpeed;}
391 private set {m_moveToSpeed = value; }
392 }
393
394 private double m_delayedStop = -1.0;
261 395
262 /// <summary> 396 /// <summary>
263 /// Controls whether an avatar automatically moving to a target will land when it gets there (if flying). 397 /// Controls whether an avatar automatically moving to a target will land when it gets there (if flying).
264 /// </summary> 398 /// </summary>
265 public bool LandAtTarget { get; private set; } 399 public bool LandAtTarget { get; private set; }
266 400
267 private int m_movementUpdateCount;
268 private const int NumMovementsBetweenRayCast = 5;
269
270 private bool CameraConstraintActive; 401 private bool CameraConstraintActive;
271 //private int m_moveToPositionStateStatus; 402
272 //***************************************************** 403 private object m_collisionEventLock = new Object();
273 404
274 private int m_movementAnimationUpdateCounter = 0; 405 private int m_movementAnimationUpdateCounter = 0;
275 406
@@ -287,7 +418,6 @@ namespace OpenSim.Region.Framework.Scenes
287 } 418 }
288 } 419 }
289 420
290 public bool SentInitialDataToClient { get; private set; }
291 421
292 /// <summary> 422 /// <summary>
293 /// Copy of the script states while the agent is in transit. This state may 423 /// Copy of the script states while the agent is in transit. This state may
@@ -303,7 +433,7 @@ namespace OpenSim.Region.Framework.Scenes
303 /// <summary> 433 /// <summary>
304 /// Implemented Control Flags 434 /// Implemented Control Flags
305 /// </summary> 435 /// </summary>
306 private enum Dir_ControlFlags 436 private enum Dir_ControlFlags:uint
307 { 437 {
308 DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS, 438 DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS,
309 DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG, 439 DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG,
@@ -315,13 +445,15 @@ namespace OpenSim.Region.Framework.Scenes
315 DIR_CONTROL_FLAG_BACKWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG, 445 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, 446 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, 447 DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG,
448 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 449 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
319 } 450 }
320 451
321 /// <summary> 452 /// <summary>
322 /// Position at which a significant movement was made 453 /// Position at which a significant movement was made
323 /// </summary> 454 /// </summary>
324 private Vector3 posLastSignificantMove; 455 private Vector3 posLastSignificantMove;
456 private Vector3 posLastMove;
325 457
326 #region For teleports and crossings callbacks 458 #region For teleports and crossings callbacks
327 459
@@ -346,10 +478,7 @@ namespace OpenSim.Region.Framework.Scenes
346 /// </summary> 478 /// </summary>
347 private object m_originRegionIDAccessLock = new object(); 479 private object m_originRegionIDAccessLock = new object();
348 480
349 /// <summary> 481
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); 482 private AutoResetEvent m_updateAgentReceivedAfterTransferEvent = new AutoResetEvent(false);
354 483
355 /// <summary> 484 /// <summary>
@@ -366,6 +495,14 @@ namespace OpenSim.Region.Framework.Scenes
366 /// </value> 495 /// </value>
367 private IScriptModule[] m_scriptEngines; 496 private IScriptModule[] m_scriptEngines;
368 497
498 private enum LandingPointBehavior
499 {
500 OS = 1,
501 SL = 2
502 }
503
504 private LandingPointBehavior m_LandingPointBehavior = LandingPointBehavior.OS;
505
369 #region Properties 506 #region Properties
370 507
371 /// <summary> 508 /// <summary>
@@ -379,11 +516,6 @@ namespace OpenSim.Region.Framework.Scenes
379 public uint MovementFlag { get; private set; } 516 public uint MovementFlag { get; private set; }
380 517
381 /// <summary> 518 /// <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? 519 /// Is the agent stop control flag currently active?
388 /// </summary> 520 /// </summary>
389 public bool AgentControlStopActive { get; private set; } 521 public bool AgentControlStopActive { get; private set; }
@@ -396,28 +528,21 @@ namespace OpenSim.Region.Framework.Scenes
396 get { return m_invulnerable; } 528 get { return m_invulnerable; }
397 } 529 }
398 530
399 private int m_userLevel; 531 public GodController GodController { get; private set; }
400
401 public int UserLevel
402 {
403 get { return m_userLevel; }
404 private set { m_userLevel = value; }
405 }
406
407 private int m_godLevel;
408
409 public int GodLevel
410 {
411 get { return m_godLevel; }
412 private set { m_godLevel = value; }
413 }
414 532
415 private ulong m_rootRegionHandle; 533 private ulong m_rootRegionHandle;
534 private Vector3 m_rootRegionPosition = new Vector3();
416 535
417 public ulong RegionHandle 536 public ulong RegionHandle
418 { 537 {
419 get { return m_rootRegionHandle; } 538 get { return m_rootRegionHandle; }
420 private set { m_rootRegionHandle = value; } 539 private set
540 {
541 m_rootRegionHandle = value;
542 // position rounded to lower multiple of 256m
543 m_rootRegionPosition.X = (float)((m_rootRegionHandle >> 32) & 0xffffff00);
544 m_rootRegionPosition.Y = (float)(m_rootRegionHandle & 0xffffff00);
545 }
421 } 546 }
422 547
423 #region Client Camera 548 #region Client Camera
@@ -425,17 +550,13 @@ namespace OpenSim.Region.Framework.Scenes
425 /// <summary> 550 /// <summary>
426 /// Position of agent's camera in world (region cordinates) 551 /// Position of agent's camera in world (region cordinates)
427 /// </summary> 552 /// </summary>
428 protected Vector3 m_lastCameraPosition; 553// protected Vector3 m_lastCameraPosition;
429 554
430 private Vector4 m_lastCameraCollisionPlane = new Vector4(0f, 0f, 0f, 1); 555 private Vector4 m_lastCameraCollisionPlane = new Vector4(0f, 0f, 0f, 1);
431 private bool m_doingCamRayCast = false; 556 private bool m_doingCamRayCast = false;
432 557
433 public Vector3 CameraPosition { get; set; } 558 public Vector3 CameraPosition { get; set; }
434 559 public Quaternion CameraRotation { get; private set; }
435 public Quaternion CameraRotation
436 {
437 get { return Util.Axes2Rot(CameraAtAxis, CameraLeftAxis, CameraUpAxis); }
438 }
439 560
440 // Use these three vectors to figure out what the agent is looking at 561 // Use these three vectors to figure out what the agent is looking at
441 // Convert it to a Matrix and/or Quaternion 562 // Convert it to a Matrix and/or Quaternion
@@ -449,39 +570,51 @@ namespace OpenSim.Region.Framework.Scenes
449 get 570 get
450 { 571 {
451 Vector3 a = new Vector3(CameraAtAxis.X, CameraAtAxis.Y, 0); 572 Vector3 a = new Vector3(CameraAtAxis.X, CameraAtAxis.Y, 0);
452 573 a.Normalize();
453 if (a == Vector3.Zero) 574 return a;
454 return a;
455
456 return Util.GetNormalizedVector(a);
457 } 575 }
458 } 576 }
459 #endregion 577 #endregion
460 578
461 public string Firstname { get; private set; } 579 public string Firstname { get; private set; }
462 public string Lastname { get; private set; } 580 public string Lastname { get; private set; }
463 581
582 public bool haveGroupInformation;
583 public bool gotCrossUpdate;
584 public byte crossingFlags;
585
464 public string Grouptitle 586 public string Grouptitle
465 { 587 {
466 get { return UseFakeGroupTitle ? "(Loading)" : m_groupTitle; } 588 get { return m_groupTitle; }
467 set { m_groupTitle = value; } 589 set { m_groupTitle = value; }
468 } 590 }
469 private string m_groupTitle; 591 private string m_groupTitle;
470 592
471 /// <summary>
472 /// When this is 'true', return a dummy group title instead of the real group title. This is
473 /// used as part of a hack to force viewers to update the displayed avatar name.
474 /// </summary>
475 public bool UseFakeGroupTitle { get; set; }
476
477
478 // Agent's Draw distance. 593 // Agent's Draw distance.
479 public float DrawDistance { get; set; } 594 private float m_drawDistance = 255f;
595 public float DrawDistance
596 {
597 get
598 {
599 return m_drawDistance;
600 }
601 set
602 {
603 m_drawDistance = Util.Clamp(value, 32f, m_scene.MaxDrawDistance);
604 }
605 }
606
607 public float RegionViewDistance
608 {
609 get
610 {
611 return Util.Clamp(m_drawDistance, 32f, m_scene.MaxRegionViewDistance);
612 }
613 }
480 614
481 public bool AllowMovement { get; set; } 615 public bool AllowMovement { get; set; }
482 616
483 private bool m_setAlwaysRun; 617 private bool m_setAlwaysRun;
484
485 public bool SetAlwaysRun 618 public bool SetAlwaysRun
486 { 619 {
487 get 620 get
@@ -557,12 +690,16 @@ namespace OpenSim.Region.Framework.Scenes
557 // in the sim unless the avatar is on a sit target. While 690 // in the sim unless the avatar is on a sit target. While
558 // on a sit target, m_pos will contain the desired offset 691 // on a sit target, m_pos will contain the desired offset
559 // without the parent rotation applied. 692 // without the parent rotation applied.
560 SceneObjectPart sitPart = ParentPart; 693 if (ParentPart != null)
561 694 {
562 if (sitPart != null) 695 SceneObjectPart rootPart = ParentPart.ParentGroup.RootPart;
563 return sitPart.ParentGroup.AbsolutePosition + (m_pos * sitPart.GetWorldRotation()); 696 // if (sitPart != null)
697 // return sitPart.AbsolutePosition + (m_pos * sitPart.GetWorldRotation());
698 if (rootPart != null)
699 return rootPart.AbsolutePosition + (m_pos * rootPart.GetWorldRotation());
700 }
564 } 701 }
565 702
566 return m_pos; 703 return m_pos;
567 } 704 }
568 set 705 set
@@ -614,11 +751,8 @@ namespace OpenSim.Region.Framework.Scenes
614 } 751 }
615 752
616 /// <summary> 753 /// <summary>
617 /// Velocity of the avatar with respect to its local reference frame. 754 /// Current velocity of the avatar.
618 /// </summary> 755 /// </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 756 public override Vector3 Velocity
623 { 757 {
624 get 758 get
@@ -631,21 +765,12 @@ namespace OpenSim.Region.Framework.Scenes
631// "[SCENE PRESENCE]: Set velocity {0} for {1} in {2} via getting Velocity!", 765// "[SCENE PRESENCE]: Set velocity {0} for {1} in {2} via getting Velocity!",
632// m_velocity, Name, Scene.RegionInfo.RegionName); 766// m_velocity, Name, Scene.RegionInfo.RegionName);
633 } 767 }
634// else if (ParentPart != null)
635// {
636// return ParentPart.ParentGroup.Velocity;
637// }
638 768
639 return m_velocity; 769 return m_velocity;
640 } 770 }
641 771
642 set 772 set
643 { 773 {
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) 774 if (PhysicsActor != null)
650 { 775 {
651 try 776 try
@@ -658,27 +783,42 @@ namespace OpenSim.Region.Framework.Scenes
658 } 783 }
659 } 784 }
660 785
661 m_velocity = value; 786 m_velocity = value;
787
788// m_log.DebugFormat(
789// "[SCENE PRESENCE]: In {0} set velocity of {1} to {2}",
790// Scene.RegionInfo.RegionName, Name, m_velocity);
662 } 791 }
663 } 792 }
664/* 793
665 public override Vector3 AngularVelocity 794 // requested Velocity for physics engines avatar motors
795 // only makes sense if there is a physical rep
796 public Vector3 TargetVelocity
666 { 797 {
667 get 798 get
668 { 799 {
669 if (PhysicsActor != null) 800 if (PhysicsActor != null)
670 { 801 return PhysicsActor.TargetVelocity;
671 m_rotationalvelocity = PhysicsActor.RotationalVelocity; 802 else
803 return Vector3.Zero;
804 }
672 805
673 // m_log.DebugFormat( 806 set
674 // "[SCENE PRESENCE]: Set velocity {0} for {1} in {2} via getting Velocity!", 807 {
675 // m_velocity, Name, Scene.RegionInfo.RegionName); 808 if (PhysicsActor != null)
809 {
810 try
811 {
812 PhysicsActor.TargetVelocity = value;
813 }
814 catch (Exception e)
815 {
816 m_log.Error("[SCENE PRESENCE]: TARGETVELOCITY " + e.Message);
817 }
676 } 818 }
677
678 return m_rotationalvelocity;
679 } 819 }
680 } 820 }
681*/ 821
682 private Quaternion m_bodyRot = Quaternion.Identity; 822 private Quaternion m_bodyRot = Quaternion.Identity;
683 823
684 /// <summary> 824 /// <summary>
@@ -691,9 +831,9 @@ namespace OpenSim.Region.Framework.Scenes
691 /// </remarks> 831 /// </remarks>
692 public Quaternion Rotation 832 public Quaternion Rotation
693 { 833 {
694 get 834 get
695 { 835 {
696 return m_bodyRot; 836 return m_bodyRot;
697 } 837 }
698 838
699 set 839 set
@@ -758,16 +898,42 @@ namespace OpenSim.Region.Framework.Scenes
758 set { m_health = value; } 898 set { m_health = value; }
759 } 899 }
760 900
901 public float HealRate
902 {
903 get { return m_healRate; }
904 set
905 {
906 if(value > 100.0f)
907 m_healRate = 100.0f;
908 else if (value <= 0.0)
909 m_healRate = 0.0f;
910 else
911 m_healRate = value;
912
913 if(Scene != null)
914 m_healRatePerFrame = m_healRate * Scene.FrameTime;
915 else
916 m_healRatePerFrame = 0.05f;
917 }
918 }
919
920
761 /// <summary> 921 /// <summary>
762 /// Get rotation relative to the world. 922 /// Gets the world rotation of this presence.
763 /// </summary> 923 /// </summary>
924 /// <remarks>
925 /// Unlike Rotation, this returns the world rotation no matter whether the avatar is sitting on a prim or not.
926 /// </remarks>
764 /// <returns></returns> 927 /// <returns></returns>
765 public Quaternion GetWorldRotation() 928 public Quaternion GetWorldRotation()
766 { 929 {
767 SceneObjectPart sitPart = ParentPart; 930 if (IsSatOnObject)
931 {
932 SceneObjectPart sitPart = ParentPart;
768 933
769 if (sitPart != null) 934 if (sitPart != null)
770 return sitPart.GetWorldRotation() * Rotation; 935 return sitPart.GetWorldRotation() * Rotation;
936 }
771 937
772 return Rotation; 938 return Rotation;
773 } 939 }
@@ -793,26 +959,7 @@ namespace OpenSim.Region.Framework.Scenes
793 seeds = Scene.CapsModule.GetChildrenSeeds(UUID); 959 seeds = Scene.CapsModule.GetChildrenSeeds(UUID);
794 else 960 else
795 seeds = new Dictionary<ulong, string>(); 961 seeds = new Dictionary<ulong, string>();
796
797 List<ulong> old = new List<ulong>();
798 foreach (ulong handle in seeds.Keys)
799 {
800 uint x, y;
801 Util.RegionHandleToRegionLoc(handle, out x, out y);
802
803 if (Util.IsOutsideView(DrawDistance, x, Scene.RegionInfo.RegionLocX, y, Scene.RegionInfo.RegionLocY))
804 {
805 old.Add(handle);
806 }
807 }
808 DropOldNeighbours(old);
809
810 if (Scene.CapsModule != null)
811 Scene.CapsModule.SetChildrenSeed(UUID, seeds);
812
813 KnownRegions = seeds; 962 KnownRegions = seeds;
814 //m_log.Debug(" ++++++++++AFTER+++++++++++++ ");
815 //DumpKnownRegions();
816 } 963 }
817 964
818 public void DumpKnownRegions() 965 public void DumpKnownRegions()
@@ -827,20 +974,20 @@ namespace OpenSim.Region.Framework.Scenes
827 } 974 }
828 975
829 private bool m_mouseLook; 976 private bool m_mouseLook;
830// private bool m_leftButtonDown; 977 private bool m_leftButtonDown;
831 978
832 private bool m_inTransit; 979 private bool m_inTransit;
833 980
834 /// <summary> 981 /// <summary>
835 /// This signals whether the presence is in transit between neighbouring regions. 982 /// This signals whether the presence is in transit between neighbouring regions.
836 /// </summary> 983 /// </summary>
837 /// <remarks> 984 /// <remarks>
838 /// It is not set when the presence is teleporting or logging in/out directly to a region. 985 /// It is not set when the presence is teleporting or logging in/out directly to a region.
839 /// </remarks> 986 /// </remarks>
840 public bool IsInTransit 987 public bool IsInTransit
841 { 988 {
842 get { return m_inTransit; } 989 get { return m_inTransit; }
843 set { 990 set {
844 if(value) 991 if(value)
845 { 992 {
846 if (Flying) 993 if (Flying)
@@ -851,14 +998,11 @@ namespace OpenSim.Region.Framework.Scenes
851 m_inTransit = value; 998 m_inTransit = value;
852 } 999 }
853 } 1000 }
1001 // this is is only valid if IsInTransit is true
1002 // only false on HG tps
1003 // used work arounf viewers asking source region about destination user
1004 public bool IsInLocalTransit {get; set; }
854 1005
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 1006
863 /// <summary> 1007 /// <summary>
864 /// Modifier for agent movement if we get an AGENT_CONTROL_STOP whilst walking or running 1008 /// Modifier for agent movement if we get an AGENT_CONTROL_STOP whilst walking or running
@@ -866,7 +1010,20 @@ namespace OpenSim.Region.Framework.Scenes
866 /// <remarks> 1010 /// <remarks>
867 /// AGENT_CONTRL_STOP comes about if user holds down space key on viewers. 1011 /// AGENT_CONTRL_STOP comes about if user holds down space key on viewers.
868 /// </remarks> 1012 /// </remarks>
869 private float AgentControlStopSlowWhilstMoving = 0.5f; 1013 private const float AgentControlStopSlowVel = 0.2f;
1014 // velocities
1015 public const float AgentControlNudgeVel = 1.0f; // setting this diferent from normal as no effect currently
1016 public const float AgentControlNormalVel = 1.0f;
1017
1018 // old normal speed was tuned to match sl normal plus Fast modifiers
1019 // so we need to rescale it
1020 private float m_speedModifier = 1.0f;
1021
1022 public float SpeedModifier
1023 {
1024 get { return m_speedModifier; }
1025 set { m_speedModifier = value; }
1026 }
870 1027
871 private bool m_forceFly; 1028 private bool m_forceFly;
872 1029
@@ -889,35 +1046,32 @@ namespace OpenSim.Region.Framework.Scenes
889 get { return Util.GetViewerName(m_scene.AuthenticateHandler.GetAgentCircuitData(ControllingClient.CircuitCode)); } 1046 get { return Util.GetViewerName(m_scene.AuthenticateHandler.GetAgentCircuitData(ControllingClient.CircuitCode)); }
890 } 1047 }
891 1048
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 1049 #endregion
898 1050
899 #region Constructor(s) 1051 #region Constructor(s)
900 1052
901 public ScenePresence( 1053 public ScenePresence(
902 IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type) 1054 IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type)
903 { 1055 {
1056 m_scene = world;
904 AttachmentsSyncLock = new Object(); 1057 AttachmentsSyncLock = new Object();
905 AllowMovement = true; 1058 AllowMovement = true;
906 IsChildAgent = true; 1059 IsChildAgent = true;
907 IsLoggingIn = false; 1060 IsLoggingIn = false;
908 m_sendCoarseLocationsMethod = SendCoarseLocationsDefault; 1061 m_sendCoarseLocationsMethod = SendCoarseLocationsDefault;
909 Animator = new ScenePresenceAnimator(this); 1062 Animator = new ScenePresenceAnimator(this);
1063 Overrides = new MovementAnimationOverrides();
910 PresenceType = type; 1064 PresenceType = type;
911 // DrawDistance = world.DefaultDrawDistance; 1065 DrawDistance = world.DefaultDrawDistance;
912 DrawDistance = Constants.RegionSize;
913 RegionHandle = world.RegionInfo.RegionHandle; 1066 RegionHandle = world.RegionInfo.RegionHandle;
914 ControllingClient = client; 1067 ControllingClient = client;
915 Firstname = ControllingClient.FirstName; 1068 Firstname = ControllingClient.FirstName;
916 Lastname = ControllingClient.LastName; 1069 Lastname = ControllingClient.LastName;
917 m_name = String.Format("{0} {1}", Firstname, Lastname); 1070 m_name = String.Format("{0} {1}", Firstname, Lastname);
918 m_scene = world;
919 m_uuid = client.AgentId; 1071 m_uuid = client.AgentId;
920 LocalId = m_scene.AllocateLocalId(); 1072 LocalId = m_scene.AllocateLocalId();
1073 LegacySitOffsets = m_scene.LegacySitOffsets;
1074 IsInLocalTransit = true;
921 1075
922 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid); 1076 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid);
923 if (account != null) 1077 if (account != null)
@@ -925,32 +1079,52 @@ namespace OpenSim.Region.Framework.Scenes
925 else 1079 else
926 m_userFlags = 0; 1080 m_userFlags = 0;
927 1081
1082 int userlevel = 0;
928 if (account != null) 1083 if (account != null)
929 UserLevel = account.UserLevel; 1084 userlevel = account.UserLevel;
1085
1086 GodController = new GodController(world, this, userlevel);
930 1087
931 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); 1088 // IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
932 if (gm != null) 1089 // if (gm != null)
933 Grouptitle = gm.GetGroupTitle(m_uuid); 1090 // Grouptitle = gm.GetGroupTitle(m_uuid);
934 1091
935 m_scriptEngines = m_scene.RequestModuleInterfaces<IScriptModule>(); 1092 m_scriptEngines = m_scene.RequestModuleInterfaces<IScriptModule>();
936
937 AbsolutePosition = posLastSignificantMove = CameraPosition =
938 m_lastCameraPosition = ControllingClient.StartPos;
939 1093
940 m_reprioritization_timer = new Timer(world.ReprioritizationInterval); 1094 AbsolutePosition = posLastMove = posLastSignificantMove = CameraPosition =
941 m_reprioritization_timer.Elapsed += new ElapsedEventHandler(Reprioritize); 1095 m_reprioritizationLastPosition = ControllingClient.StartPos;
942 m_reprioritization_timer.AutoReset = false; 1096
1097 m_reprioritizationLastDrawDistance = DrawDistance;
1098
1099 // disable updates workjobs for now
1100 m_childUpdatesBusy = true;
1101 m_reprioritizationBusy = true;
943 1102
944 AdjustKnownSeeds(); 1103 AdjustKnownSeeds();
945 1104
946 RegisterToEvents(); 1105 RegisterToClientEvents();
947 SetDirectionVectors(); 1106 SetDirectionVectors();
948 1107
949 Appearance = appearance; 1108 Appearance = appearance;
950 1109
951 m_stateMachine = new ScenePresenceStateMachine(this); 1110 m_stateMachine = new ScenePresenceStateMachine(this);
1111
1112 HealRate = 0.5f;
1113
1114 IConfig sconfig = m_scene.Config.Configs["EntityTransfer"];
1115 if (sconfig != null)
1116 {
1117 string lpb = sconfig.GetString("LandingPointBehavior", "LandingPointBehavior_OS");
1118 if (lpb == "LandingPointBehavior_SL")
1119 m_LandingPointBehavior = LandingPointBehavior.SL;
1120 }
1121
1122 ControllingClient.RefreshGroupMembership();
1123
952 } 1124 }
953 1125
1126 private float lastHealthSent = 0;
1127
954 private void RegionHeartbeatEnd(Scene scene) 1128 private void RegionHeartbeatEnd(Scene scene)
955 { 1129 {
956 if (IsChildAgent) 1130 if (IsChildAgent)
@@ -973,12 +1147,29 @@ namespace OpenSim.Region.Framework.Scenes
973 } 1147 }
974 else 1148 else
975 { 1149 {
976 m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd; 1150// m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd;
1151 }
1152 }
1153
1154 if(m_healRatePerFrame != 0f && Health != 100.0f)
1155 {
1156 float last = Health;
1157 Health += m_healRatePerFrame;
1158 if(Health > 100.0f)
1159 {
1160 Health = 100.0f;
1161 lastHealthSent = Health;
1162 ControllingClient.SendHealth(Health);
1163 }
1164 else if(Math.Abs(Health - lastHealthSent) > 1.0)
1165 {
1166 lastHealthSent = Health;
1167 ControllingClient.SendHealth(Health);
977 } 1168 }
978 } 1169 }
979 } 1170 }
980 1171
981 public void RegisterToEvents() 1172 public void RegisterToClientEvents()
982 { 1173 {
983 ControllingClient.OnCompleteMovementToRegion += CompleteMovement; 1174 ControllingClient.OnCompleteMovementToRegion += CompleteMovement;
984 ControllingClient.OnAgentUpdate += HandleAgentUpdate; 1175 ControllingClient.OnAgentUpdate += HandleAgentUpdate;
@@ -988,28 +1179,48 @@ namespace OpenSim.Region.Framework.Scenes
988 ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun; 1179 ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun;
989 ControllingClient.OnStartAnim += HandleStartAnim; 1180 ControllingClient.OnStartAnim += HandleStartAnim;
990 ControllingClient.OnStopAnim += HandleStopAnim; 1181 ControllingClient.OnStopAnim += HandleStopAnim;
1182 ControllingClient.OnChangeAnim += avnHandleChangeAnim;
991 ControllingClient.OnForceReleaseControls += HandleForceReleaseControls; 1183 ControllingClient.OnForceReleaseControls += HandleForceReleaseControls;
992 ControllingClient.OnAutoPilotGo += MoveToTarget; 1184 ControllingClient.OnAutoPilotGo += MoveToTargetHandle;
1185 ControllingClient.OnUpdateThrottles += RaiseUpdateThrottles;
1186// ControllingClient.OnAgentFOV += HandleAgentFOV;
993 1187
994 // ControllingClient.OnChildAgentStatus += new StatusChange(this.ChildStatusChange); 1188 // ControllingClient.OnChildAgentStatus += new StatusChange(this.ChildStatusChange);
995 // ControllingClient.OnStopMovement += new GenericCall2(this.StopMovement); 1189 // ControllingClient.OnStopMovement += new GenericCall2(this.StopMovement);
996 } 1190 }
997 1191
998 private void SetDirectionVectors() 1192 public void RemoveClientEvents()
999 { 1193 {
1000 Dir_Vectors[0] = Vector3.UnitX; //FORWARD 1194 ControllingClient.OnCompleteMovementToRegion -= CompleteMovement;
1001 Dir_Vectors[1] = -Vector3.UnitX; //BACK 1195 ControllingClient.OnAgentUpdate -= HandleAgentUpdate;
1002 Dir_Vectors[2] = Vector3.UnitY; //LEFT 1196 ControllingClient.OnAgentCameraUpdate -= HandleAgentCamerasUpdate;
1003 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT 1197 ControllingClient.OnAgentRequestSit -= HandleAgentRequestSit;
1004 Dir_Vectors[4] = Vector3.UnitZ; //UP 1198 ControllingClient.OnAgentSit -= HandleAgentSit;
1005 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN 1199 ControllingClient.OnSetAlwaysRun -= HandleSetAlwaysRun;
1006 Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE 1200 ControllingClient.OnStartAnim -= HandleStartAnim;
1007 Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE 1201 ControllingClient.OnStopAnim -= HandleStopAnim;
1008 Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE 1202 ControllingClient.OnChangeAnim -= avnHandleChangeAnim;
1009 Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE 1203 ControllingClient.OnForceReleaseControls -= HandleForceReleaseControls;
1010 Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge 1204 ControllingClient.OnAutoPilotGo -= MoveToTargetHandle;
1205 ControllingClient.OnUpdateThrottles -= RaiseUpdateThrottles;
1206// ControllingClient.OnAgentFOV += HandleAgentFOV;
1011 } 1207 }
1012 1208
1209 private void SetDirectionVectors()
1210 {
1211 Dir_Vectors[0] = new Vector3(AgentControlNormalVel,0,0); //FORWARD
1212 Dir_Vectors[1] = new Vector3(-AgentControlNormalVel,0,0);; //BACK
1213 Dir_Vectors[2] = new Vector3(0,AgentControlNormalVel,0); //LEFT
1214 Dir_Vectors[3] = new Vector3(0,-AgentControlNormalVel,0); //RIGHT
1215 Dir_Vectors[4] = new Vector3(0,0,AgentControlNormalVel); //UP
1216 Dir_Vectors[5] = new Vector3(0,0,-AgentControlNormalVel); //DOWN
1217 Dir_Vectors[6] = new Vector3(AgentControlNudgeVel, 0f, 0f); //FORWARD_NUDGE
1218 Dir_Vectors[7] = new Vector3(-AgentControlNudgeVel, 0f, 0f); //BACK_NUDGE
1219 Dir_Vectors[8] = new Vector3(0f, AgentControlNudgeVel, 0f); //LEFT_NUDGE
1220 Dir_Vectors[9] = new Vector3(0f, -AgentControlNudgeVel, 0f); //RIGHT_NUDGE
1221 Dir_Vectors[10] = new Vector3(0f, 0f, AgentControlNudgeVel); //UP_Nudge
1222 Dir_Vectors[11] = new Vector3(0f, 0f, -AgentControlNudgeVel); //DOWN_Nudge
1223 }
1013 #endregion 1224 #endregion
1014 1225
1015 #region Status Methods 1226 #region Status Methods
@@ -1026,18 +1237,29 @@ namespace OpenSim.Region.Framework.Scenes
1026 /// This method is on the critical path for transferring an avatar from one region to another. Delay here 1237 /// This method is on the critical path for transferring an avatar from one region to another. Delay here
1027 /// delays that crossing. 1238 /// delays that crossing.
1028 /// </remarks> 1239 /// </remarks>
1029 private bool MakeRootAgent(Vector3 pos, bool isFlying) 1240
1241 // constants for physics position search
1242 const float PhysSearchHeight = 600f;
1243 const float PhysMinSkipGap = 50f;
1244 const int PhysNumberCollisions = 30;
1245
1246 // only in use as part of completemovement
1247 // other uses need fix
1248 private bool MakeRootAgent(Vector3 pos, bool isFlying, ref Vector3 lookat)
1030 { 1249 {
1250 //int ts = Util.EnvironmentTickCount();
1251
1031 lock (m_completeMovementLock) 1252 lock (m_completeMovementLock)
1032 { 1253 {
1033 if (!IsChildAgent) 1254 if (!IsChildAgent)
1034 return false; 1255 return false;
1035 1256
1257 //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); 1258 //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
1037 1259
1038 // m_log.InfoFormat( 1260 // m_log.InfoFormat(
1039 // "[SCENE]: Upgrading child to root agent for {0} in {1}", 1261 // "[SCENE]: Upgrading child to root agent for {0} in {1}",
1040 // Name, m_scene.RegionInfo.RegionName); 1262 // Name, m_scene.RegionInfo.RegionName);
1041 1263
1042 if (ParentUUID != UUID.Zero) 1264 if (ParentUUID != UUID.Zero)
1043 { 1265 {
@@ -1046,20 +1268,33 @@ namespace OpenSim.Region.Framework.Scenes
1046 if (part == null) 1268 if (part == null)
1047 { 1269 {
1048 m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID); 1270 m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID);
1271 ParentID = 0;
1272 ParentPart = null;
1273 PrevSitOffset = Vector3.Zero;
1274 HandleForceReleaseControls(ControllingClient, UUID); // needs testing
1275 IsLoggingIn = false;
1049 } 1276 }
1050 else 1277 else
1051 { 1278 {
1052 part.AddSittingAvatar(this); 1279 part.AddSittingAvatar(this);
1053 // ParentPosition = part.GetWorldPosition(); 1280 // if not actually on the target invalidate it
1281 if(gotCrossUpdate && (crossingFlags & 0x04) == 0)
1282 part.SitTargetAvatar = UUID.Zero;
1283
1054 ParentID = part.LocalId; 1284 ParentID = part.LocalId;
1055 ParentPart = part; 1285 ParentPart = part;
1056 m_pos = PrevSitOffset; 1286 m_pos = PrevSitOffset;
1057 // pos = ParentPosition;
1058 pos = part.GetWorldPosition(); 1287 pos = part.GetWorldPosition();
1288 PhysicsActor partPhysActor = part.PhysActor;
1289 if(partPhysActor != null)
1290 {
1291 partPhysActor.OnPhysicsRequestingCameraData -=
1292 physActor_OnPhysicsRequestingCameraData;
1293 partPhysActor.OnPhysicsRequestingCameraData +=
1294 physActor_OnPhysicsRequestingCameraData;
1295 }
1059 } 1296 }
1060 ParentUUID = UUID.Zero; 1297 ParentUUID = UUID.Zero;
1061
1062 // Animator.TrySetMovementAnimation("SIT");
1063 } 1298 }
1064 else 1299 else
1065 { 1300 {
@@ -1069,135 +1304,144 @@ namespace OpenSim.Region.Framework.Scenes
1069 IsChildAgent = false; 1304 IsChildAgent = false;
1070 } 1305 }
1071 1306
1307 //m_log.DebugFormat("[MakeRootAgent] out lock: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1308
1072 // Must reset this here so that a teleport to a region next to an existing region does not keep the flag 1309 // 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. 1310 // 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 1311 // Should not be needed if we are not trying to tell this region to close
1075// DoNotCloseAfterTeleport = false; 1312 // DoNotCloseAfterTeleport = false;
1076
1077 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
1078 if (gm != null)
1079 Grouptitle = gm.GetGroupTitle(m_uuid);
1080
1081 AgentCircuitData aCircuit = m_scene.AuthenticateHandler.GetAgentCircuitData(ControllingClient.CircuitCode);
1082 uint teleportFlags = (aCircuit == null) ? 0 : aCircuit.teleportFlags;
1083 if ((teleportFlags & (uint)TeleportFlags.ViaHGLogin) != 0)
1084 {
1085 // 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").
1087 // 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.
1089 ForceViewersUpdateName();
1090 }
1091 1313
1092 RegionHandle = m_scene.RegionInfo.RegionHandle; 1314 RegionHandle = m_scene.RegionInfo.RegionHandle;
1093 1315
1094 m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene); 1316 m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene);
1317 //m_log.DebugFormat("[MakeRootAgent] TriggerSetRootAgentScene: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1095 1318
1096 UUID groupUUID = ControllingClient.ActiveGroupId; 1319 if (ParentID == 0)
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 { 1320 {
1104 if (groupUUID != UUID.Zero && gm != null) 1321 bool positionChanged = false;
1105 { 1322 bool success = true;
1106 GroupRecord record = gm.GetGroupRecord(groupUUID); 1323 if (m_LandingPointBehavior == LandingPointBehavior.OS)
1107 if (record != null) 1324 success = CheckAndAdjustLandingPoint_OS(ref pos, ref lookat, ref positionChanged);
1108 groupName = record.GroupName; 1325 else
1326 success = CheckAndAdjustLandingPoint_SL(ref pos, ref lookat, ref positionChanged);
1109 1327
1110 GroupMembershipData groupMembershipData = gm.GetMembershipData(groupUUID, m_uuid); 1328 if (!success)
1329 m_log.DebugFormat("[SCENE PRESENCE MakeRootAgent]: houston we have a problem.. {0} ({1} got banned)", Name, UUID);
1111 1330
1112 if (groupMembershipData != null) 1331 if (pos.X < 0f || pos.Y < 0f
1113 groupPowers = groupMembershipData.GroupPowers; 1332 || pos.X >= m_scene.RegionInfo.RegionSizeX
1333 || pos.Y >= m_scene.RegionInfo.RegionSizeY)
1334 {
1335 m_log.WarnFormat(
1336 "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Clamping",
1337 pos, Name, UUID);
1338
1339 if (pos.X < 0f)
1340 pos.X = 0.5f;
1341 else if(pos.X >= m_scene.RegionInfo.RegionSizeX)
1342 pos.X = m_scene.RegionInfo.RegionSizeX - 0.5f;
1343 if (pos.Y < 0f)
1344 pos.Y = 0.5f;
1345 else if(pos.Y >= m_scene.RegionInfo.RegionSizeY)
1346 pos.Y = m_scene.RegionInfo.RegionSizeY - 0.5f;
1114 } 1347 }
1115 1348
1116 ControllingClient.SendAgentDataUpdate( 1349 float groundHeight = m_scene.GetGroundHeight(pos.X, pos.Y) + .01f;
1117 m_uuid, groupUUID, Firstname, Lastname, groupPowers, groupName, Grouptitle); 1350 float physTestHeight;
1118 }
1119 catch (Exception e)
1120 {
1121 m_log.Error("[AGENTUPDATE]: Error ", e);
1122 }
1123 // ------------------------------------
1124 1351
1125 if (ParentID == 0) 1352 if(PhysSearchHeight < groundHeight + 100f)
1126 { 1353 physTestHeight = groundHeight + 100f;
1127 // Moved this from SendInitialData to ensure that Appearance is initialized 1354 else
1128 // before the inventory is processed in MakeRootAgent. This fixes a race condition 1355 physTestHeight = PhysSearchHeight;
1129 // related to the handling of attachments
1130 //m_scene.GetAvatarAppearance(ControllingClient, out Appearance);
1131 1356
1132 /* RA 20140111: Commented out these TestBorderCross's. 1357 float localAVHalfHeight = 0.8f;
1133 * Not sure why this code is here. It is not checking all the borders 1358 if (Appearance != null && Appearance.AvatarHeight > 0)
1134 * and 'in region' sanity checking is done in CheckAndAdjustLandingPoint and below. 1359 localAVHalfHeight = 0.5f * Appearance.AvatarHeight;
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 1360
1141 if (m_scene.TestBorderCross(pos, Cardinals.N)) 1361 groundHeight += localAVHalfHeight;
1142 { 1362 if (groundHeight > pos.Z)
1143 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N); 1363 pos.Z = groundHeight;
1144 pos.Y = crossedBorder.BorderLine.Z - 1;
1145 }
1146 */
1147 1364
1148 CheckAndAdjustLandingPoint(ref pos); 1365 bool checkPhysics = !positionChanged &&
1366 m_scene.SupportsRayCastFiltered() &&
1367 pos.Z < physTestHeight &&
1368 ((m_teleportFlags & (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID)) ==
1369 (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID)
1370 || (m_teleportFlags & TeleportFlags.ViaLocation) != 0
1371 || (m_teleportFlags & TeleportFlags.ViaHGLogin) != 0);
1149 1372
1150 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) 1373 if(checkPhysics)
1151 { 1374 {
1152 m_log.WarnFormat( 1375 // land check was done above
1153 "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Clamping", 1376 RayFilterFlags rayfilter = RayFilterFlags.BackFaceCull;
1154 pos, Name, UUID); 1377 rayfilter |= RayFilterFlags.PrimsNonPhantomAgents;
1155 1378
1156 if (pos.X < 0f) pos.X = 0f; 1379 int physcount = PhysNumberCollisions;
1157 if (pos.Y < 0f) pos.Y = 0f;
1158 if (pos.Z < 0f) pos.Z = 0f;
1159 }
1160 1380
1161 float localAVHeight = 1.56f; 1381 float dist = physTestHeight - groundHeight + localAVHalfHeight;
1162 if (Appearance.AvatarHeight > 0)
1163 localAVHeight = Appearance.AvatarHeight;
1164 1382
1165 float posZLimit = 0; 1383 Vector3 direction = new Vector3(0f, 0f, -1f);
1384 Vector3 RayStart = pos;
1385 RayStart.Z = physTestHeight;
1166 1386
1167 if (pos.X < m_scene.RegionInfo.RegionSizeX && pos.Y < m_scene.RegionInfo.RegionSizeY) 1387 List<ContactResult> physresults =
1168 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y]; 1388 (List<ContactResult>)m_scene.RayCastFiltered(RayStart, direction, dist, physcount, rayfilter);
1169 1389 if (physresults != null && physresults.Count > 0)
1170 float newPosZ = posZLimit + localAVHeight / 2; 1390 {
1171 if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) 1391 float dest = physresults[0].Pos.Z;
1172 { 1392
1173 pos.Z = newPosZ; 1393 if(physresults.Count > 1)
1394 {
1395 physresults.Sort(delegate(ContactResult a, ContactResult b)
1396 {
1397 return a.Depth.CompareTo(b.Depth);
1398 });
1399
1400 int sel = 0;
1401 int count = physresults.Count;
1402 float curd = physresults[0].Depth;
1403 float nextd = curd + PhysMinSkipGap;
1404 float maxDepth = dist - pos.Z;
1405 for(int i = 1; i < count; i++)
1406 {
1407 curd = physresults[i].Depth;
1408 if(curd >= nextd)
1409 {
1410 sel = i;
1411 if(curd >= maxDepth)
1412 break;
1413 }
1414 nextd = curd + PhysMinSkipGap;
1415 }
1416 dest = physresults[sel].Pos.Z;
1417 }
1418
1419 dest += localAVHalfHeight;
1420 if(dest > pos.Z)
1421 pos.Z = dest;
1422 }
1174 } 1423 }
1424
1175 AbsolutePosition = pos; 1425 AbsolutePosition = pos;
1176 1426
1177// m_log.DebugFormat( 1427// m_log.DebugFormat(
1178// "Set pos {0}, vel {1} in {1} to {2} from input position of {3} on MakeRootAgent", 1428// "Set pos {0}, vel {1} in {1} to {2} from input position of {3} on MakeRootAgent",
1179// Name, Scene.Name, AbsolutePosition, pos); 1429// Name, Scene.Name, AbsolutePosition, pos);
1180// 1430//
1181 if (m_teleportFlags == TeleportFlags.Default) 1431 if (m_teleportFlags == TeleportFlags.Default)
1182 { 1432 {
1433 Vector3 vel = Velocity;
1183 AddToPhysicalScene(isFlying); 1434 AddToPhysicalScene(isFlying);
1184// 1435 if (PhysicsActor != null)
1185// Console.WriteLine( 1436 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 } 1437 }
1190 else 1438 else
1191 { 1439 {
1192 AddToPhysicalScene(isFlying); 1440 AddToPhysicalScene(isFlying);
1193 }
1194 1441
1195 // XXX: This is to trigger any secondary teleport needed for a megaregion when the user has teleported to a 1442 // reset camera to avatar pos
1196 // location outside the 'root region' (the south-west 256x256 corner). This is the earlist we can do it 1443 CameraPosition = pos;
1197 // since it requires a physics actor to be present. If it is left any later, then physics appears to reset 1444 }
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 1445
1202 if (ForceFly) 1446 if (ForceFly)
1203 { 1447 {
@@ -1209,53 +1453,16 @@ namespace OpenSim.Region.Framework.Scenes
1209 } 1453 }
1210 } 1454 }
1211 1455
1212 // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying 1456 //m_log.DebugFormat("[MakeRootAgent] position and physical: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1213 // avatar to return to the standing position in mid-air. On login it looks like this is being sent
1214 // elsewhere anyway
1215 // Animator.SendAnimPack();
1216
1217 m_scene.SwapRootAgentCount(false); 1457 m_scene.SwapRootAgentCount(false);
1218 1458
1219 if (Scene.AttachmentsModule != null)
1220 {
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 }
1243
1244 SendAvatarDataToAllClients();
1245
1246 // send the animations of the other presences to me
1247 m_scene.ForEachRootScenePresence(delegate(ScenePresence presence)
1248 {
1249 if (presence != this)
1250 presence.Animator.SendAnimPackToClient(ControllingClient);
1251 });
1252
1253 // If we don't reset the movement flag here, an avatar that crosses to a neighbouring sim and returns will 1459 // 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 1460 // 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. 1461 // recorded, which stops the input from being processed.
1256 MovementFlag = ForceUpdateMovementFlagValue; 1462 MovementFlag = 0;
1257 1463
1258 m_scene.EventManager.TriggerOnMakeRootAgent(this); 1464 m_scene.EventManager.TriggerOnMakeRootAgent(this);
1465 //m_log.DebugFormat("[MakeRootAgent] TriggerOnMakeRootAgent and done: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1259 1466
1260 return true; 1467 return true;
1261 } 1468 }
@@ -1304,12 +1511,13 @@ namespace OpenSim.Region.Framework.Scenes
1304 /// Group Title. So the following trick makes viewers update the avatar's name by briefly changing 1511 /// 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. 1512 /// the group title (to "(Loading)"), and then restoring it.
1306 /// </remarks> 1513 /// </remarks>
1514/*
1307 public void ForceViewersUpdateName() 1515 public void ForceViewersUpdateName()
1308 { 1516 {
1309 m_log.DebugFormat("[SCENE PRESENCE]: Forcing viewers to update the avatar name for " + Name); 1517 m_log.DebugFormat("[SCENE PRESENCE]: Forcing viewers to update the avatar name for " + Name);
1310 1518
1311 UseFakeGroupTitle = true; 1519 UseFakeGroupTitle = true;
1312 SendAvatarDataToAllClients(false); 1520
1313 1521
1314 Util.FireAndForget(o => 1522 Util.FireAndForget(o =>
1315 { 1523 {
@@ -1323,7 +1531,7 @@ namespace OpenSim.Region.Framework.Scenes
1323 SendAvatarDataToAllClients(false); 1531 SendAvatarDataToAllClients(false);
1324 }, null, "Scenepresence.ForceViewersUpdateName"); 1532 }, null, "Scenepresence.ForceViewersUpdateName");
1325 } 1533 }
1326 1534*/
1327 public int GetStateSource() 1535 public int GetStateSource()
1328 { 1536 {
1329 AgentCircuitData aCircuit = m_scene.AuthenticateHandler.GetAgentCircuitData(UUID); 1537 AgentCircuitData aCircuit = m_scene.AuthenticateHandler.GetAgentCircuitData(UUID);
@@ -1347,11 +1555,17 @@ namespace OpenSim.Region.Framework.Scenes
1347 /// It doesn't get called for a teleport. Reason being, an agent that 1555 /// It doesn't get called for a teleport. Reason being, an agent that
1348 /// teleports out may not end up anywhere near this region 1556 /// teleports out may not end up anywhere near this region
1349 /// </remarks> 1557 /// </remarks>
1350 public void MakeChildAgent() 1558 public void MakeChildAgent(ulong newRegionHandle)
1351 { 1559 {
1560 haveGroupInformation = false;
1561 gotCrossUpdate = false;
1562 crossingFlags = 0;
1352 m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd; 1563 m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd;
1353 1564
1354 m_log.DebugFormat("[SCENE PRESENCE]: Making {0} a child agent in {1}", Name, Scene.RegionInfo.RegionName); 1565 RegionHandle = newRegionHandle;
1566
1567 m_log.DebugFormat("[SCENE PRESENCE]: Making {0} a child agent in {1} from root region {2}",
1568 Name, Scene.RegionInfo.RegionName, newRegionHandle);
1355 1569
1356 // Reset the m_originRegionID as it has dual use as a flag to signal that the UpdateAgent() call orignating 1570 // 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. 1571 // from the source simulator has completed on a V2 teleport.
@@ -1371,7 +1585,7 @@ namespace OpenSim.Region.Framework.Scenes
1371 else 1585 else
1372 Animator.ResetAnimations(); 1586 Animator.ResetAnimations();
1373 1587
1374 1588
1375// m_log.DebugFormat( 1589// m_log.DebugFormat(
1376// "[SCENE PRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}", 1590// "[SCENE PRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}",
1377// Name, UUID, m_scene.RegionInfo.RegionName); 1591// Name, UUID, m_scene.RegionInfo.RegionName);
@@ -1379,14 +1593,21 @@ namespace OpenSim.Region.Framework.Scenes
1379 // Don't zero out the velocity since this can cause problems when an avatar is making a region crossing, 1593 // Don't zero out the velocity since this can cause problems when an avatar is making a region crossing,
1380 // depending on the exact timing. This shouldn't matter anyway since child agent positions are not updated. 1594 // depending on the exact timing. This shouldn't matter anyway since child agent positions are not updated.
1381 //Velocity = new Vector3(0, 0, 0); 1595 //Velocity = new Vector3(0, 0, 0);
1382 1596
1383 IsChildAgent = true; 1597 IsChildAgent = true;
1384 m_scene.SwapRootAgentCount(true); 1598 m_scene.SwapRootAgentCount(true);
1385 RemoveFromPhysicalScene(); 1599 RemoveFromPhysicalScene();
1386 ParentID = 0; // Child agents can't be sitting 1600 ParentID = 0; // Child agents can't be sitting
1387 1601
1602// we dont have land information for child
1603 m_previusParcelHide = false;
1604 m_previusParcelUUID = UUID.Zero;
1605 m_currentParcelHide = false;
1606 m_currentParcelUUID = UUID.Zero;
1388 // FIXME: Set RegionHandle to the region handle of the scene this agent is moving into 1607 // FIXME: Set RegionHandle to the region handle of the scene this agent is moving into
1389 1608
1609 CollisionPlane = Vector4.UnitW;
1610
1390 m_scene.EventManager.TriggerOnMakeChildAgent(this); 1611 m_scene.EventManager.TriggerOnMakeChildAgent(this);
1391 } 1612 }
1392 1613
@@ -1398,9 +1619,10 @@ namespace OpenSim.Region.Framework.Scenes
1398 if (PhysicsActor != null) 1619 if (PhysicsActor != null)
1399 { 1620 {
1400// PhysicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients; 1621// PhysicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients;
1401 PhysicsActor.UnSubscribeEvents(); 1622
1402 PhysicsActor.OnOutOfBounds -= OutOfBoundsCall; 1623 PhysicsActor.OnOutOfBounds -= OutOfBoundsCall;
1403 PhysicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate; 1624 PhysicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate;
1625 PhysicsActor.UnSubscribeEvents();
1404 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor); 1626 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor);
1405 PhysicsActor = null; 1627 PhysicsActor = null;
1406 } 1628 }
@@ -1423,12 +1645,16 @@ namespace OpenSim.Region.Framework.Scenes
1423 1645
1424 public void TeleportWithMomentum(Vector3 pos, Vector3? v) 1646 public void TeleportWithMomentum(Vector3 pos, Vector3? v)
1425 { 1647 {
1648 if(!CheckLocalTPLandingPoint(ref pos))
1649 return;
1650
1426 if (ParentID != (uint)0) 1651 if (ParentID != (uint)0)
1427 StandUp(); 1652 StandUp();
1653
1428 bool isFlying = Flying; 1654 bool isFlying = Flying;
1429 Vector3 vel = Velocity; 1655 Vector3 vel = Velocity;
1430 RemoveFromPhysicalScene(); 1656 RemoveFromPhysicalScene();
1431 CheckLandingPoint(ref pos); 1657
1432 AbsolutePosition = pos; 1658 AbsolutePosition = pos;
1433 AddToPhysicalScene(isFlying); 1659 AddToPhysicalScene(isFlying);
1434 if (PhysicsActor != null) 1660 if (PhysicsActor != null)
@@ -1438,11 +1664,29 @@ namespace OpenSim.Region.Framework.Scenes
1438 else 1664 else
1439 PhysicsActor.SetMomentum(vel); 1665 PhysicsActor.SetMomentum(vel);
1440 } 1666 }
1667
1668 SendTerseUpdateToAllClients();
1669 }
1670
1671 public void TeleportOnEject(Vector3 pos)
1672 {
1673 if (ParentID != (uint)0)
1674 StandUp();
1675
1676 bool isFlying = Flying;
1677 RemoveFromPhysicalScene();
1678
1679 AbsolutePosition = pos;
1680
1681 AddToPhysicalScene(isFlying);
1682 SendTerseUpdateToAllClients();
1441 } 1683 }
1442 1684
1443 public void avnLocalTeleport(Vector3 newpos, Vector3? newvel, bool rotateToVelXY) 1685 public void avnLocalTeleport(Vector3 newpos, Vector3? newvel, bool rotateToVelXY)
1444 { 1686 {
1445 CheckLandingPoint(ref newpos); 1687 if(!CheckLocalTPLandingPoint(ref newpos))
1688 return;
1689
1446 AbsolutePosition = newpos; 1690 AbsolutePosition = newpos;
1447 1691
1448 if (newvel.HasValue) 1692 if (newvel.HasValue)
@@ -1469,11 +1713,15 @@ namespace OpenSim.Region.Framework.Scenes
1469 } 1713 }
1470 } 1714 }
1471 } 1715 }
1716 SendTerseUpdateToAllClients();
1472 } 1717 }
1473 1718
1474 public void StopFlying() 1719 public void StopFlying()
1475 { 1720 {
1476 Vector3 pos = AbsolutePosition; 1721 if (IsInTransit)
1722 return;
1723
1724 Vector3 pos = AbsolutePosition;
1477 if (Appearance.AvatarHeight != 127.0f) 1725 if (Appearance.AvatarHeight != 127.0f)
1478 pos += new Vector3(0f, 0f, (Appearance.AvatarHeight / 6f)); 1726 pos += new Vector3(0f, 0f, (Appearance.AvatarHeight / 6f));
1479 else 1727 else
@@ -1492,7 +1740,7 @@ namespace OpenSim.Region.Framework.Scenes
1492 else 1740 else
1493 CollisionPlane = new Vector4(0, 0, 0, pos.Z - (1.56f / 6f)); 1741 CollisionPlane = new Vector4(0, 0, 0, pos.Z - (1.56f / 6f));
1494 1742
1495 ControllingClient.SendAgentTerseUpdate(this); 1743 SendAgentTerseUpdate(this);
1496 } 1744 }
1497 1745
1498 /// <summary> 1746 /// <summary>
@@ -1501,7 +1749,7 @@ namespace OpenSim.Region.Framework.Scenes
1501 /// <param name="amount">Postive or negative roll amount in radians</param> 1749 /// <param name="amount">Postive or negative roll amount in radians</param>
1502 private void ApplyFlyingRoll(float amount, bool PressingUp, bool PressingDown) 1750 private void ApplyFlyingRoll(float amount, bool PressingUp, bool PressingDown)
1503 { 1751 {
1504 1752
1505 float rollAmount = Util.Clamp(m_AngularVelocity.Z + amount, -FLY_ROLL_MAX_RADIANS, FLY_ROLL_MAX_RADIANS); 1753 float rollAmount = Util.Clamp(m_AngularVelocity.Z + amount, -FLY_ROLL_MAX_RADIANS, FLY_ROLL_MAX_RADIANS);
1506 m_AngularVelocity.Z = rollAmount; 1754 m_AngularVelocity.Z = rollAmount;
1507 1755
@@ -1553,17 +1801,14 @@ namespace OpenSim.Region.Framework.Scenes
1553 1801
1554 if (m_AngularVelocity.Z > 0) 1802 if (m_AngularVelocity.Z > 0)
1555 { 1803 {
1556
1557 float leftOverToMin = m_AngularVelocity.Z - rollMinRadians; 1804 float leftOverToMin = m_AngularVelocity.Z - rollMinRadians;
1558 if (amount > leftOverToMin) 1805 if (amount > leftOverToMin)
1559 return -leftOverToMin; 1806 return -leftOverToMin;
1560 else 1807 else
1561 return -amount; 1808 return -amount;
1562
1563 } 1809 }
1564 else 1810 else
1565 { 1811 {
1566
1567 float leftOverToMin = -m_AngularVelocity.Z - rollMinRadians; 1812 float leftOverToMin = -m_AngularVelocity.Z - rollMinRadians;
1568 if (amount > leftOverToMin) 1813 if (amount > leftOverToMin)
1569 return leftOverToMin; 1814 return leftOverToMin;
@@ -1571,22 +1816,65 @@ namespace OpenSim.Region.Framework.Scenes
1571 return amount; 1816 return amount;
1572 } 1817 }
1573 } 1818 }
1574
1575
1576 1819
1577 // neighbouring regions we have enabled a child agent in 1820 // neighbouring regions we have enabled a child agent in
1578 // holds the seed cap for the child agent in that region 1821 // holds the seed cap for the child agent in that region
1579 private Dictionary<ulong, string> m_knownChildRegions = new Dictionary<ulong, string>(); 1822 private Dictionary<ulong, string> m_knownChildRegions = new Dictionary<ulong, string>();
1580 1823
1581 public void AddNeighbourRegion(ulong regionHandle, string cap) 1824 struct spRegionSizeInfo
1825 {
1826 public int sizeX;
1827 public int sizeY;
1828 }
1829
1830 private Dictionary<ulong, spRegionSizeInfo> m_knownChildRegionsSizeInfo = new Dictionary<ulong, spRegionSizeInfo>();
1831
1832 public void AddNeighbourRegion(GridRegion region, string capsPath)
1833 {
1834 lock (m_knownChildRegions)
1835 {
1836 ulong regionHandle = region.RegionHandle;
1837 m_knownChildRegions.Add(regionHandle,capsPath);
1838
1839 spRegionSizeInfo sizeInfo = new spRegionSizeInfo();
1840 sizeInfo.sizeX = region.RegionSizeX;
1841 sizeInfo.sizeY = region.RegionSizeY;
1842 m_knownChildRegionsSizeInfo[regionHandle] = sizeInfo;
1843 }
1844 }
1845
1846 public void AddNeighbourRegionSizeInfo(GridRegion region)
1847 {
1848 lock (m_knownChildRegions)
1849 {
1850 spRegionSizeInfo sizeInfo = new spRegionSizeInfo();
1851 sizeInfo.sizeX = region.RegionSizeX;
1852 sizeInfo.sizeY = region.RegionSizeY;
1853 ulong regionHandle = region.RegionHandle;
1854
1855 if (!m_knownChildRegionsSizeInfo.ContainsKey(regionHandle))
1856 {
1857 m_knownChildRegionsSizeInfo.Add(regionHandle, sizeInfo);
1858
1859 }
1860 else
1861 m_knownChildRegionsSizeInfo[regionHandle] = sizeInfo;
1862 }
1863 }
1864
1865 public void SetNeighbourRegionSizeInfo(List<GridRegion> regionsList)
1582 { 1866 {
1583 lock (m_knownChildRegions) 1867 lock (m_knownChildRegions)
1584 { 1868 {
1585 if (!m_knownChildRegions.ContainsKey(regionHandle)) 1869 m_knownChildRegionsSizeInfo.Clear();
1870
1871 foreach (GridRegion region in regionsList)
1586 { 1872 {
1587 uint x, y; 1873 spRegionSizeInfo sizeInfo = new spRegionSizeInfo();
1588 Utils.LongToUInts(regionHandle, out x, out y); 1874 sizeInfo.sizeX = region.RegionSizeX;
1589 m_knownChildRegions.Add(regionHandle, cap); 1875 sizeInfo.sizeY = region.RegionSizeY;
1876 ulong regionHandle = region.RegionHandle;
1877 m_knownChildRegionsSizeInfo.Add(regionHandle, sizeInfo);
1590 } 1878 }
1591 } 1879 }
1592 } 1880 }
@@ -1600,9 +1888,16 @@ namespace OpenSim.Region.Framework.Scenes
1600 //if (m_knownChildRegions.ContainsKey(regionHandle)) 1888 //if (m_knownChildRegions.ContainsKey(regionHandle))
1601 // m_log.DebugFormat(" !!! removing known region {0} in {1}. Count = {2}", regionHandle, Scene.RegionInfo.RegionName, m_knownChildRegions.Count); 1889 // m_log.DebugFormat(" !!! removing known region {0} in {1}. Count = {2}", regionHandle, Scene.RegionInfo.RegionName, m_knownChildRegions.Count);
1602 m_knownChildRegions.Remove(regionHandle); 1890 m_knownChildRegions.Remove(regionHandle);
1891 m_knownChildRegionsSizeInfo.Remove(regionHandle);
1603 } 1892 }
1604 } 1893 }
1605 1894
1895 public bool knowsNeighbourRegion(ulong regionHandle)
1896 {
1897 lock (m_knownChildRegions)
1898 return m_knownChildRegions.ContainsKey(regionHandle);
1899 }
1900
1606 public void DropOldNeighbours(List<ulong> oldRegions) 1901 public void DropOldNeighbours(List<ulong> oldRegions)
1607 { 1902 {
1608 foreach (ulong handle in oldRegions) 1903 foreach (ulong handle in oldRegions)
@@ -1612,6 +1907,13 @@ namespace OpenSim.Region.Framework.Scenes
1612 } 1907 }
1613 } 1908 }
1614 1909
1910 public void DropThisRootRegionFromNeighbours()
1911 {
1912 ulong handle = m_scene.RegionInfo.RegionHandle;
1913 RemoveNeighbourRegion(handle);
1914 Scene.CapsModule.DropChildSeed(UUID, handle);
1915 }
1916
1615 public Dictionary<ulong, string> KnownRegions 1917 public Dictionary<ulong, string> KnownRegions
1616 { 1918 {
1617 get 1919 get
@@ -1632,7 +1934,8 @@ namespace OpenSim.Region.Framework.Scenes
1632 { 1934 {
1633 get 1935 get
1634 { 1936 {
1635 return new List<ulong>(KnownRegions.Keys); 1937 lock (m_knownChildRegions)
1938 return new List<ulong>(m_knownChildRegions.Keys);
1636 } 1939 }
1637 } 1940 }
1638 1941
@@ -1662,35 +1965,66 @@ namespace OpenSim.Region.Framework.Scenes
1662 public void SetSize(Vector3 size, float feetoffset) 1965 public void SetSize(Vector3 size, float feetoffset)
1663 { 1966 {
1664 if (PhysicsActor != null && !IsChildAgent) 1967 if (PhysicsActor != null && !IsChildAgent)
1665 { 1968 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 } 1969 }
1672 1970
1673 private bool WaitForUpdateAgent(IClientAPI client) 1971 private bool WaitForUpdateAgent(IClientAPI client)
1674 { 1972 {
1675 // Before the source region executes UpdateAgent 1973 // Before the source region executes UpdateAgent
1676 // (which triggers Scene.IncomingUpdateChildAgent(AgentData cAgentData) here in the destination, 1974 // (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 1975 // 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 1976 // viewer (in turn triggered by the source region sending it a TeleportFinish event) waits until it's non-zero
1679 m_updateAgentReceivedAfterTransferEvent.WaitOne(10000);
1680 1977
1681 UUID originID = UUID.Zero; 1978 try
1979 {
1980 if(m_updateAgentReceivedAfterTransferEvent.WaitOne(10000))
1981 {
1982 UUID originID = UUID.Zero;
1682 1983
1683 lock (m_originRegionIDAccessLock) 1984 lock (m_originRegionIDAccessLock)
1684 originID = m_originRegionID; 1985 originID = m_originRegionID;
1986 if (originID.Equals(UUID.Zero))
1987 {
1988 // Movement into region will fail
1989 m_log.WarnFormat("[SCENE PRESENCE]: Update agent {0} at {1} got invalid origin region id ", client.Name, Scene.Name);
1990 return false;
1991 }
1992 return true;
1993 }
1994 else
1995 {
1996 m_log.WarnFormat("[SCENE PRESENCE]: Update agent {0} at {1} did not receive agent update ", client.Name, Scene.Name);
1997 return false;
1998 }
1999 }
2000 catch { }
1685 2001
1686 if (originID.Equals(UUID.Zero)) 2002 return false;
2003 }
2004
2005 public void RotateToLookAt(Vector3 lookAt)
2006 {
2007 if(ParentID == 0)
1687 { 2008 {
1688 // Movement into region will fail 2009 float n = lookAt.X * lookAt.X + lookAt.Y * lookAt.Y;
1689 m_log.WarnFormat("[SCENE PRESENCE]: Update agent {0} never arrived in {1}", client.Name, Scene.Name); 2010 if(n < 0.0001f)
1690 return false; 2011 {
2012 Rotation = Quaternion.Identity;
2013 return;
2014 }
2015 n = lookAt.X/(float)Math.Sqrt(n);
2016 float angle = (float)Math.Acos(n);
2017 angle *= 0.5f;
2018 float s = (float)Math.Sin(angle);
2019 if(lookAt.Y < 0)
2020 s = -s;
2021 Rotation = new Quaternion(
2022 0f,
2023 0f,
2024 s,
2025 (float)Math.Cos(angle)
2026 );
1691 } 2027 }
1692
1693 return true;
1694 } 2028 }
1695 2029
1696 /// <summary> 2030 /// <summary>
@@ -1704,62 +2038,72 @@ namespace OpenSim.Region.Framework.Scenes
1704 /// </param> 2038 /// </param>
1705 public void CompleteMovement(IClientAPI client, bool openChildAgents) 2039 public void CompleteMovement(IClientAPI client, bool openChildAgents)
1706 { 2040 {
1707// DateTime startTime = DateTime.Now; 2041 int ts = Util.EnvironmentTickCount();
1708 2042
1709 m_log.InfoFormat( 2043 m_log.InfoFormat(
1710 "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}", 2044 "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}",
1711 client.Name, Scene.Name, AbsolutePosition); 2045 client.Name, Scene.Name, AbsolutePosition);
1712 2046
1713 bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); // Get this ahead of time because IsInTransit modifies 'm_AgentControlFlags' 2047 m_inTransit = true;
1714 2048
1715 IsInTransit = true;
1716 try 2049 try
1717 { 2050 {
1718 // Make sure it's not a login agent. We don't want to wait for updates during login 2051 // 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))) 2052 if (!IsNPC && !IsRealLogin(m_teleportFlags))
1720 { 2053 {
2054
1721 // Let's wait until UpdateAgent (called by departing region) is done 2055 // Let's wait until UpdateAgent (called by departing region) is done
1722 if (!WaitForUpdateAgent(client)) 2056 if (!WaitForUpdateAgent(client))
1723 // The sending region never sent the UpdateAgent data, we have to refuse 2057 // The sending region never sent the UpdateAgent data, we have to refuse
1724 return; 2058 return;
1725 } 2059 }
1726 2060
1727 Vector3 look = Velocity; 2061 //m_log.DebugFormat("[CompleteMovement] WaitForUpdateAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1728 2062
1729 // if ((look.X == 0) && (look.Y == 0) && (look.Z == 0)) 2063 bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
1730 if ((Math.Abs(look.X) < 0.1) && (Math.Abs(look.Y) < 0.1) && (Math.Abs(look.Z) < 0.1))
1731 {
1732 look = new Vector3(0.99f, 0.042f, 0);
1733 }
1734 2064
1735 // Prevent teleporting to an underground location 2065 Vector3 look = Lookat;
1736 // (may crash client otherwise) 2066 look.Z = 0f;
1737 // 2067 if ((Math.Abs(look.X) < 0.01) && (Math.Abs(look.Y) < 0.01))
1738 Vector3 pos = AbsolutePosition;
1739 float ground = m_scene.GetGroundHeight(pos.X, pos.Y);
1740 if (pos.Z < ground + 1.5f)
1741 { 2068 {
1742 pos.Z = ground + 1.5f; 2069 look = Velocity;
1743 AbsolutePosition = pos; 2070 look.Normalize();
2071 if ((Math.Abs(look.X) < 0.01) && (Math.Abs(look.Y) < 0.01) )
2072 look = new Vector3(0.99f, 0.042f, 0);
1744 } 2073 }
1745 2074
1746 if (!MakeRootAgent(AbsolutePosition, flying)) 2075 // Check Default Location (Also See EntityTransferModule.TeleportAgentWithinRegion)
2076 if (AbsolutePosition.X == 128f && AbsolutePosition.Y == 128f && AbsolutePosition.Z == 22.5f)
2077 AbsolutePosition = Scene.RegionInfo.DefaultLandingPoint;
2078
2079 if (!MakeRootAgent(AbsolutePosition, flying, ref look))
1747 { 2080 {
1748 m_log.DebugFormat( 2081 m_log.DebugFormat(
1749 "[SCENE PRESENCE]: Aborting CompleteMovement call for {0} in {1} as they are already root", 2082 "[SCENE PRESENCE]: Aborting CompleteMovement call for {0} in {1} as they are already root",
1750 Name, Scene.Name); 2083 Name, Scene.Name);
1751 2084
1752 return; 2085 return;
1753 } 2086 }
1754 2087
1755 // Tell the client that we're totally ready
1756 ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look);
1757 2088
1758 // Child agents send initial data up in LLUDPServer.HandleUseCircuitCode() 2089 //m_log.DebugFormat("[CompleteMovement] MakeRootAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1759 if (!SentInitialDataToClient)
1760 SendInitialDataToClient();
1761 2090
1762 // m_log.DebugFormat("[SCENE PRESENCE] Completed movement"); 2091 if(!haveGroupInformation && !IsChildAgent && !IsNPC)
2092 {
2093 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
2094 if (gm != null)
2095 Grouptitle = gm.GetGroupTitle(m_uuid);
2096
2097 //m_log.DebugFormat("[CompleteMovement] Missing Grouptitle: {0}ms", Util.EnvironmentTickCountSubtract(ts));
2098
2099 InventoryFolderBase cof = m_scene.InventoryService.GetFolderForType(client.AgentId, (FolderType)46);
2100 if (cof == null)
2101 COF = UUID.Zero;
2102 else
2103 COF = cof.ID;
2104
2105 m_log.DebugFormat("[CompleteMovement]: Missing COF for {0} is {1}", client.AgentId, COF);
2106 }
1763 2107
1764 if (!string.IsNullOrEmpty(m_callbackURI)) 2108 if (!string.IsNullOrEmpty(m_callbackURI))
1765 { 2109 {
@@ -1768,69 +2112,260 @@ namespace OpenSim.Region.Framework.Scenes
1768 // here until we know for sure that the agent is active in this region. Sending AgentMovementComplete 2112 // 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 2113 // 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. 2114 // region as the current region, meaning that a close sent before then will fail the teleport.
1771 // System.Threading.Thread.Sleep(2000); 2115 // System.Threading.Thread.Sleep(2000);
1772 2116
1773 m_log.DebugFormat( 2117 m_log.DebugFormat(
1774 "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}", 2118 "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}",
1775 client.Name, client.AgentId, m_callbackURI); 2119 client.Name, client.AgentId, m_callbackURI);
1776 2120
1777 Scene.SimulationService.ReleaseAgent(m_originRegionID, UUID, m_callbackURI); 2121 UUID originID;
2122
2123 lock (m_originRegionIDAccessLock)
2124 originID = m_originRegionID;
2125
2126 Scene.SimulationService.ReleaseAgent(originID, UUID, m_callbackURI);
1778 m_callbackURI = null; 2127 m_callbackURI = null;
2128 //m_log.DebugFormat("[CompleteMovement] ReleaseAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1779 } 2129 }
1780 // else 2130// else
1781 // { 2131// {
1782 // m_log.DebugFormat( 2132// m_log.DebugFormat(
1783 // "[SCENE PRESENCE]: No callback provided on CompleteMovement of {0} {1} to {2}", 2133// "[SCENE PRESENCE]: No callback provided on CompleteMovement of {0} {1} to {2}",
1784 // client.Name, client.AgentId, m_scene.RegionInfo.RegionName); 2134// client.Name, client.AgentId, m_scene.RegionInfo.RegionName);
1785 // } 2135// }
2136
2137
2138 // Tell the client that we're totally ready
2139 ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look);
2140 //m_log.DebugFormat("[CompleteMovement] MoveAgentIntoRegion: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1786 2141
1787 ValidateAndSendAppearanceAndAgentData(); 2142 bool isHGTP = (m_teleportFlags & TeleportFlags.ViaHGLogin) != 0;
1788 2143
1789 // Create child agents in neighbouring regions 2144 int delayctnr = Util.EnvironmentTickCount();
1790 if (openChildAgents && !IsChildAgent) 2145
2146 if (!IsChildAgent)
1791 { 2147 {
1792 IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); 2148 if( ParentPart != null && !IsNPC && (crossingFlags & 0x08) != 0)
1793 if (m_agentTransfer != null)
1794 { 2149 {
1795 // Note: this call can take a while, because it notifies each of the simulator's neighbours. 2150
1796 // It's important that we don't allow the avatar to cross regions meanwhile, as that will 2151// SceneObjectPart root = ParentPart.ParentGroup.RootPart;
1797 // cause serious errors. We've prevented that from happening by setting IsInTransit=true. 2152// if(root.LocalId != ParentPart.LocalId)
1798 m_agentTransfer.EnableChildAgents(this); 2153// ControllingClient.SendEntityTerseUpdateImmediate(root);
2154// ControllingClient.SendEntityTerseUpdateImmediate(ParentPart);
2155 ParentPart.ParentGroup.SendFullUpdateToClient(ControllingClient);
1799 } 2156 }
1800 2157
1801 IFriendsModule friendsModule = m_scene.RequestModuleInterface<IFriendsModule>(); 2158 // verify baked textures and cache
1802 if (friendsModule != null) 2159 bool cachedbaked = false;
1803 friendsModule.SendFriendsOnlineIfNeeded(ControllingClient); 2160
2161 if (IsNPC)
2162 cachedbaked = true;
2163 else
2164 {
2165 if (m_scene.AvatarFactory != null && !isHGTP)
2166 cachedbaked = m_scene.AvatarFactory.ValidateBakedTextureCache(this);
2167
2168 // not sure we need this
2169 if (!cachedbaked)
2170 {
2171 if (m_scene.AvatarFactory != null)
2172 m_scene.AvatarFactory.QueueAppearanceSave(UUID);
2173 }
2174 }
2175 //m_log.DebugFormat("[CompleteMovement] Baked check: {0}ms", Util.EnvironmentTickCountSubtract(ts));
2176 }
2177
2178 if(m_teleportFlags > 0)
2179 {
2180 gotCrossUpdate = false; // sanity check
2181 if(Util.EnvironmentTickCountSubtract(delayctnr)< 500)
2182 Thread.Sleep(500); // let viewers catch us
2183 }
2184
2185 if(!gotCrossUpdate)
2186 RotateToLookAt(look);
2187
2188 // HG
2189 if(isHGTP)
2190 {
2191// ControllingClient.SendNameReply(m_uuid, Firstname, Lastname);
2192 m_log.DebugFormat("[CompleteMovement] HG");
2193 }
2194
2195 m_previusParcelHide = false;
2196 m_previusParcelUUID = UUID.Zero;
2197 m_currentParcelHide = false;
2198 m_currentParcelUUID = UUID.Zero;
2199 ParcelDwellTickMS = Util.GetTimeStampMS();
2200
2201 if(!IsNPC)
2202 {
2203 GodController.SyncViewerState();
2204
2205 // start sending terrain patchs
2206 if (!gotCrossUpdate)
2207 Scene.SendLayerData(ControllingClient);
2208 }
2209 // send initial land overlay and parcel
2210 ILandChannel landch = m_scene.LandChannel;
2211 if (landch != null)
2212 landch.sendClientInitialLandInfo(client);
2213
2214 if (!IsChildAgent)
2215 {
2216 List<ScenePresence> allpresences = m_scene.GetScenePresences();
2217
2218 // send avatar object to all presences including us, so they cross it into region
2219 // then hide if necessary
2220
2221 SendInitialAvatarDataToAllAgents(allpresences);
2222
2223 // send this look
2224 SendAppearanceToAgent(this);
2225
2226 // send this animations
2227
2228 UUID[] animIDs = null;
2229 int[] animseqs = null;
2230 UUID[] animsobjs = null;
2231
2232 if (Animator != null)
2233 Animator.GetArrays(out animIDs, out animseqs, out animsobjs);
2234
2235 bool haveAnims = (animIDs != null && animseqs != null && animsobjs != null);
2236
2237 if (haveAnims)
2238 SendAnimPackToAgent(this, animIDs, animseqs, animsobjs);
2239
2240 // we should be able to receive updates, etc
2241 // so release them
2242 m_inTransit = false;
2243
2244 // send look and animations to others
2245 // if not cached we send greys
2246 // uncomented if will wait till avatar does baking
2247 //if (cachedbaked)
2248 {
2249 foreach (ScenePresence p in allpresences)
2250 {
2251 if (p == this)
2252 continue;
2253
2254 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod)
2255 continue;
2256
2257 SendAppearanceToAgentNF(p);
2258 if (haveAnims)
2259 SendAnimPackToAgentNF(p, animIDs, animseqs, animsobjs);
2260 }
2261 } // greys if
2262
2263 //m_log.DebugFormat("[CompleteMovement] ValidateAndSendAppearanceAndAgentData: {0}ms", Util.EnvironmentTickCountSubtract(ts));
2264
2265 // attachments
2266 if (IsNPC || IsRealLogin(m_teleportFlags))
2267 {
2268 if (Scene.AttachmentsModule != null)
2269 // Util.FireAndForget(
2270 // o =>
2271 // {
2272
2273 if (!IsNPC)
2274 Scene.AttachmentsModule.RezAttachments(this);
2275 else
2276 Util.FireAndForget(x =>
2277 {
2278 Scene.AttachmentsModule.RezAttachments(this);
2279 });
2280
2281 // });
2282 }
2283 else
2284 {
2285 if (m_attachments.Count > 0)
2286 {
2287 m_log.DebugFormat(
2288 "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name);
1804 2289
2290 foreach (SceneObjectGroup sog in m_attachments)
2291 {
2292 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
2293 sog.ResumeScripts();
2294 }
2295
2296 foreach (ScenePresence p in allpresences)
2297 {
2298 if (p == this)
2299 {
2300 SendAttachmentsToAgentNF(this);
2301 continue;
2302 }
2303
2304 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod)
2305 continue;
2306
2307 SendAttachmentsToAgentNF(p);
2308 }
2309 }
2310 }
2311
2312 //m_log.DebugFormat("[CompleteMovement] attachments: {0}ms", Util.EnvironmentTickCountSubtract(ts));
2313 if (openChildAgents)
2314 {
2315 // Create child agents in neighbouring regions
2316 IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>();
2317 if (m_agentTransfer != null)
2318 {
2319 m_agentTransfer.EnableChildAgents(this);
2320 }
2321 }
2322 // let updates be sent, with some delay
2323 m_lastChildUpdatesTime = Util.EnvironmentTickCount() + 10000;
2324 m_lastChildAgentUpdateGodLevel = GodController.ViwerUIGodLevel;
2325 m_lastChildAgentUpdateDrawDistance = DrawDistance;
2326 m_lastChildAgentUpdatePosition = AbsolutePosition;
2327 m_childUpdatesBusy = false; // allow them
1805 } 2328 }
1806 2329
1807 // XXX: If we force an update after activity has completed, then multiple attachments do appear correctly on a destination region 2330 //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. 2331
1809 // This may be due to viewer code or it may be something we're not doing properly simulator side. 2332 // send the rest of the world
1810 WorkManager.RunJob( 2333 if (m_teleportFlags > 0 && !IsNPC || m_currentParcelHide)
1811 "ScheduleAttachmentsForFullUpdate", 2334 SendInitialDataToMe();
1812 o => ScheduleAttachmentsForFullUpdate(), 2335
1813 null, 2336 // priority uses avatar position only
1814 string.Format("Schedule attachments for full update for {0} in {1}", Name, Scene.Name), 2337// m_reprioritizationLastPosition = AbsolutePosition;
1815 true); 2338// m_reprioritizationLastDrawDistance = DrawDistance;
2339// m_reprioritizationLastTime = Util.EnvironmentTickCount() + 15000; // delay it
2340// m_reprioritizationBusy = false;
1816 2341
1817 // m_log.DebugFormat( 2342 //m_log.DebugFormat("[CompleteMovement] SendInitialDataToMe: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1818 // "[SCENE PRESENCE]: Completing movement of {0} into region {1} took {2}ms", 2343
1819 // client.Name, Scene.RegionInfo.RegionName, (DateTime.Now - startTime).Milliseconds); 2344 if (!IsChildAgent && openChildAgents)
2345 {
2346 IFriendsModule friendsModule = m_scene.RequestModuleInterface<IFriendsModule>();
2347 if (friendsModule != null)
2348 {
2349 if(gotCrossUpdate)
2350 friendsModule.IsNowRoot(this);
2351 else
2352 friendsModule.SendFriendsOnlineIfNeeded(ControllingClient);
2353 }
2354 //m_log.DebugFormat("[CompleteMovement] friendsModule: {0}ms", Util.EnvironmentTickCountSubtract(ts));
2355
2356 }
1820 } 2357 }
1821 finally 2358 finally
1822 { 2359 {
1823 IsInTransit = false; 2360 haveGroupInformation = false;
2361 gotCrossUpdate = false;
2362 crossingFlags = 0;
2363 m_inTransit = false;
1824 } 2364 }
1825 } 2365
2366 m_scene.EventManager.OnRegionHeartbeatEnd += RegionHeartbeatEnd;
1826 2367
1827 private void ScheduleAttachmentsForFullUpdate() 2368 m_log.DebugFormat("[CompleteMovement] end: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1828 {
1829 lock (m_attachments)
1830 {
1831 foreach (SceneObjectGroup sog in m_attachments)
1832 sog.ScheduleGroupForFullUpdate();
1833 }
1834 } 2369 }
1835 2370
1836 /// <summary> 2371 /// <summary>
@@ -1841,7 +2376,54 @@ namespace OpenSim.Region.Framework.Scenes
1841 /// <param name="collisionPoint"></param> 2376 /// <param name="collisionPoint"></param>
1842 /// <param name="localid"></param> 2377 /// <param name="localid"></param>
1843 /// <param name="distance"></param> 2378 /// <param name="distance"></param>
1844 /// 2379 ///
2380
2381 private void checkCameraCollision()
2382 {
2383 if(m_doingCamRayCast || !m_scene.PhysicsScene.SupportsRayCast())
2384 return;
2385
2386 if(m_mouseLook || ParentID != 0)
2387 {
2388 if (CameraConstraintActive)
2389 {
2390 Vector4 plane = new Vector4(0.9f, 0.0f, 0.361f, -10000f); // not right...
2391 UpdateCameraCollisionPlane(plane);
2392 CameraConstraintActive = false;
2393 }
2394 return;
2395 }
2396
2397 Vector3 posAdjusted = AbsolutePosition;
2398 posAdjusted.Z += 1.0f; // viewer current camera focus point
2399
2400 if(posAdjusted.ApproxEquals(m_lastCameraRayCastPos, 0.2f) &&
2401 CameraPosition.ApproxEquals(m_lastCameraRayCastCam, 0.2f))
2402 return;
2403
2404 m_lastCameraRayCastCam = CameraPosition;
2405 m_lastCameraRayCastPos = posAdjusted;
2406
2407 Vector3 tocam = CameraPosition - posAdjusted;
2408
2409 float distTocamlen = tocam.LengthSquared();
2410 if (distTocamlen > 0.01f && distTocamlen < 400)
2411 {
2412 distTocamlen = (float)Math.Sqrt(distTocamlen);
2413 tocam *= (1.0f / distTocamlen);
2414
2415 m_doingCamRayCast = true;
2416 m_scene.PhysicsScene.RaycastWorld(posAdjusted, tocam, distTocamlen + 1.0f, RayCastCameraCallback);
2417 return;
2418 }
2419
2420 if (CameraConstraintActive)
2421 {
2422 Vector4 plane = new Vector4(0.9f, 0.0f, 0.361f, -10000f); // not right...
2423 UpdateCameraCollisionPlane(plane);
2424 CameraConstraintActive = false;
2425 }
2426 }
1845 2427
1846 private void UpdateCameraCollisionPlane(Vector4 plane) 2428 private void UpdateCameraCollisionPlane(Vector4 plane)
1847 { 2429 {
@@ -1854,17 +2436,11 @@ namespace OpenSim.Region.Framework.Scenes
1854 2436
1855 public void RayCastCameraCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 pNormal) 2437 public void RayCastCameraCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 pNormal)
1856 { 2438 {
1857 const float POSITION_TOLERANCE = 0.02f;
1858 const float ROTATION_TOLERANCE = 0.02f;
1859
1860 m_doingCamRayCast = false;
1861 if (hitYN && localid != LocalId) 2439 if (hitYN && localid != LocalId)
1862 { 2440 {
1863 SceneObjectGroup group = m_scene.GetGroupByPrim(localid); 2441 if (localid != 0)
1864 bool IsPrim = group != null;
1865 if (IsPrim)
1866 { 2442 {
1867 SceneObjectPart part = group.GetPart(localid); 2443 SceneObjectPart part = m_scene.GetSceneObjectPart(localid);
1868 if (part != null && !part.VolumeDetectActive) 2444 if (part != null && !part.VolumeDetectActive)
1869 { 2445 {
1870 CameraConstraintActive = true; 2446 CameraConstraintActive = true;
@@ -1897,13 +2473,14 @@ namespace OpenSim.Region.Framework.Scenes
1897 UpdateCameraCollisionPlane(plane); 2473 UpdateCameraCollisionPlane(plane);
1898 } 2474 }
1899 } 2475 }
1900 else if (!m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) || 2476 else if(CameraConstraintActive)
1901 !Rotation.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE))
1902 { 2477 {
1903 Vector4 plane = new Vector4(0.9f, 0.0f, 0.361f, -9000f); // not right... 2478 Vector4 plane = new Vector4(0.9f, 0.0f, 0.361f, -9000f); // not right...
1904 UpdateCameraCollisionPlane(plane); 2479 UpdateCameraCollisionPlane(plane);
1905 CameraConstraintActive = false; 2480 CameraConstraintActive = false;
1906 } 2481 }
2482
2483 m_doingCamRayCast = false;
1907 } 2484 }
1908 2485
1909 /// <summary> 2486 /// <summary>
@@ -1921,12 +2498,17 @@ namespace OpenSim.Region.Framework.Scenes
1921 return; 2498 return;
1922 } 2499 }
1923 2500
2501 if (IsInTransit)
2502 return;
2503
1924 #region Sanity Checking 2504 #region Sanity Checking
1925 2505
1926 // This is irritating. Really. 2506 // This is irritating. Really.
1927 if (!AbsolutePosition.IsFinite()) 2507 if (!AbsolutePosition.IsFinite())
1928 { 2508 {
1929 RemoveFromPhysicalScene(); 2509 bool isphysical = PhysicsActor != null;
2510 if(isphysical)
2511 RemoveFromPhysicalScene();
1930 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902"); 2512 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902");
1931 2513
1932 m_pos = m_LastFinitePos; 2514 m_pos = m_LastFinitePos;
@@ -1938,7 +2520,8 @@ namespace OpenSim.Region.Framework.Scenes
1938 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999903"); 2520 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999903");
1939 } 2521 }
1940 2522
1941 AddToPhysicalScene(false); 2523 if(isphysical)
2524 AddToPhysicalScene(false);
1942 } 2525 }
1943 else 2526 else
1944 { 2527 {
@@ -1953,18 +2536,18 @@ namespace OpenSim.Region.Framework.Scenes
1953 2536
1954 // The Agent's Draw distance setting 2537 // The Agent's Draw distance setting
1955 // When we get to the point of re-computing neighbors everytime this 2538 // When we get to the point of re-computing neighbors everytime this
1956 // changes, then start using the agent's drawdistance rather than the 2539 // changes, then start using the agent's drawdistance rather than the
1957 // region's draw distance. 2540 // region's draw distance.
2541
1958 DrawDistance = agentData.Far; 2542 DrawDistance = agentData.Far;
1959 // DrawDistance = Scene.DefaultDrawDistance;
1960 2543
1961 m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0; 2544 m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0;
1962 2545
1963 // FIXME: This does not work as intended because the viewer only sends the lbutton down when the button 2546 // FIXME: This does not work as intended because the viewer only sends the lbutton down when the button
1964 // is first pressed, not whilst it is held down. If this is required in the future then need to look 2547 // 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 2548 // 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). 2549 // received (e.g. on holding LMB down on the avatar in a viewer).
1967// m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0; 2550 m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0;
1968 2551
1969 #endregion Inputs 2552 #endregion Inputs
1970 2553
@@ -1977,6 +2560,7 @@ namespace OpenSim.Region.Framework.Scenes
1977// (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) 2560// (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
1978// m_updateCount = UPDATE_COUNT; 2561// m_updateCount = UPDATE_COUNT;
1979 2562
2563
1980 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0) 2564 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0)
1981 { 2565 {
1982 StandUp(); 2566 StandUp();
@@ -1984,38 +2568,8 @@ namespace OpenSim.Region.Framework.Scenes
1984 2568
1985 // Raycast from the avatar's head to the camera to see if there's anything blocking the view 2569 // Raycast from the avatar's head to the camera to see if there's anything blocking the view
1986 // this exclude checks may not be complete 2570 // this exclude checks may not be complete
1987 2571 if(agentData.NeedsCameraCollision) // condition parentID may be wrong
1988 if (m_movementUpdateCount % NumMovementsBetweenRayCast == 0 && m_scene.PhysicsScene.SupportsRayCast()) 2572 checkCameraCollision();
1989 {
1990 if (!m_doingCamRayCast && !m_mouseLook && ParentID == 0)
1991 {
1992 Vector3 posAdjusted = AbsolutePosition;
1993// posAdjusted.Z += 0.5f * Appearance.AvatarSize.Z - 0.5f;
1994 posAdjusted.Z += 1.0f; // viewer current camera focus point
1995 Vector3 tocam = CameraPosition - posAdjusted;
1996 tocam.X = (float)Math.Round(tocam.X, 1);
1997 tocam.Y = (float)Math.Round(tocam.Y, 1);
1998 tocam.Z = (float)Math.Round(tocam.Z, 1);
1999
2000 float distTocamlen = tocam.Length();
2001 if (distTocamlen > 0.3f)
2002 {
2003 tocam *= (1.0f / distTocamlen);
2004 posAdjusted.X = (float)Math.Round(posAdjusted.X, 1);
2005 posAdjusted.Y = (float)Math.Round(posAdjusted.Y, 1);
2006 posAdjusted.Z = (float)Math.Round(posAdjusted.Z, 1);
2007
2008 m_doingCamRayCast = true;
2009 m_scene.PhysicsScene.RaycastWorld(posAdjusted, tocam, distTocamlen + 1.0f, RayCastCameraCallback);
2010 }
2011 }
2012 else if (CameraConstraintActive && (m_mouseLook || ParentID != 0))
2013 {
2014 Vector4 plane = new Vector4(0.9f, 0.0f, 0.361f, -10000f); // not right...
2015 UpdateCameraCollisionPlane(plane);
2016 CameraConstraintActive = false;
2017 }
2018 }
2019 2573
2020 uint flagsForScripts = (uint)flags; 2574 uint flagsForScripts = (uint)flags;
2021 flags = RemoveIgnoredControls(flags, IgnoredControls); 2575 flags = RemoveIgnoredControls(flags, IgnoredControls);
@@ -2032,7 +2586,7 @@ namespace OpenSim.Region.Framework.Scenes
2032 2586
2033 // We need to send this back to the client in order to stop the edit beams 2587 // 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) 2588 if ((oldState & (uint)AgentState.Editing) != 0 && State == (uint)AgentState.None)
2035 ControllingClient.SendAgentTerseUpdate(this); 2589 SendAgentTerseUpdate(this);
2036 2590
2037 PhysicsActor actor = PhysicsActor; 2591 PhysicsActor actor = PhysicsActor;
2038 2592
@@ -2046,9 +2600,7 @@ namespace OpenSim.Region.Framework.Scenes
2046 if (AllowMovement && !SitGround) 2600 if (AllowMovement && !SitGround)
2047 { 2601 {
2048// m_log.DebugFormat("[SCENE PRESENCE]: Initial body rotation {0} for {1}", agentData.BodyRotation, Name); 2602// m_log.DebugFormat("[SCENE PRESENCE]: Initial body rotation {0} for {1}", agentData.BodyRotation, Name);
2049
2050 bool update_rotation = false; 2603 bool update_rotation = false;
2051
2052 if (agentData.BodyRotation != Rotation) 2604 if (agentData.BodyRotation != Rotation)
2053 { 2605 {
2054 Rotation = agentData.BodyRotation; 2606 Rotation = agentData.BodyRotation;
@@ -2056,31 +2608,26 @@ namespace OpenSim.Region.Framework.Scenes
2056 } 2608 }
2057 2609
2058 bool update_movementflag = false; 2610 bool update_movementflag = false;
2059 2611 bool mvToTarget = m_movingToTarget;
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) 2612 if (agentData.UseClientAgentPosition)
2069 { 2613 {
2070 MovingToTarget = (agentData.ClientAgentPosition - AbsolutePosition).Length() > 0.2f; 2614 m_movingToTarget = (agentData.ClientAgentPosition - AbsolutePosition).LengthSquared() > 0.04f;
2071 MoveToPositionTarget = agentData.ClientAgentPosition; 2615 m_moveToPositionTarget = agentData.ClientAgentPosition;
2616 m_moveToSpeed = -1f;
2072 } 2617 }
2073 2618
2074 int i = 0; 2619 int i = 0;
2075 bool DCFlagKeyPressed = false; 2620 bool DCFlagKeyPressed = false;
2076 Vector3 agent_control_v3 = Vector3.Zero; 2621 Vector3 agent_control_v3 = Vector3.Zero;
2077 2622
2078 bool newFlying = actor.Flying; 2623 bool newFlying = false;
2079 2624
2080 if (ForceFly) 2625 if (ForceFly)
2081 newFlying = true; 2626 newFlying = true;
2082 else if (FlyDisabled) 2627 else if (FlyDisabled)
2083 newFlying = false; 2628 newFlying = false;
2629 else if(mvToTarget)
2630 newFlying = actor.Flying;
2084 else 2631 else
2085 newFlying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); 2632 newFlying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
2086 2633
@@ -2096,6 +2643,15 @@ namespace OpenSim.Region.Framework.Scenes
2096 { 2643 {
2097 bool bAllowUpdateMoveToPosition = false; 2644 bool bAllowUpdateMoveToPosition = false;
2098 2645
2646 Vector3[] dirVectors;
2647
2648 // use camera up angle when in mouselook and not flying or when holding the left mouse button down and not flying
2649 // this prevents 'jumping' in inappropriate situations.
2650// if (!Flying && (m_mouseLook || m_leftButtonDown))
2651// dirVectors = GetWalkDirectionVectors();
2652// else
2653 dirVectors = Dir_Vectors;
2654
2099 // A DIR_CONTROL_FLAG occurs when the user is trying to move in a particular direction. 2655 // 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) 2656 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
2101 { 2657 {
@@ -2105,9 +2661,7 @@ namespace OpenSim.Region.Framework.Scenes
2105 2661
2106 try 2662 try
2107 { 2663 {
2108 // Don't slide against ground when crouching if camera is panned around avatar 2664 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]); 2665 //m_log.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]);
2112 } 2666 }
2113 catch (IndexOutOfRangeException) 2667 catch (IndexOutOfRangeException)
@@ -2115,10 +2669,10 @@ namespace OpenSim.Region.Framework.Scenes
2115 // Why did I get this? 2669 // Why did I get this?
2116 } 2670 }
2117 2671
2118 if (((MovementFlag & (uint)DCF) == 0) & !AgentControlStopActive) 2672 if (((MovementFlag & (uint)DCF) == 0))
2119 { 2673 {
2120 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF); 2674 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF);
2121 MovementFlag += (uint)DCF; 2675 MovementFlag |= (uint)DCF;
2122 update_movementflag = true; 2676 update_movementflag = true;
2123 } 2677 }
2124 } 2678 }
@@ -2127,7 +2681,7 @@ namespace OpenSim.Region.Framework.Scenes
2127 if ((MovementFlag & (uint)DCF) != 0) 2681 if ((MovementFlag & (uint)DCF) != 0)
2128 { 2682 {
2129 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF); 2683 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF);
2130 MovementFlag -= (uint)DCF; 2684 MovementFlag &= (uint)~DCF;
2131 update_movementflag = true; 2685 update_movementflag = true;
2132 2686
2133 /* 2687 /*
@@ -2154,7 +2708,7 @@ namespace OpenSim.Region.Framework.Scenes
2154 update_movementflag = true; 2708 update_movementflag = true;
2155 } 2709 }
2156 2710
2157 if (MovingToTarget) 2711 if (m_movingToTarget)
2158 { 2712 {
2159 // If the user has pressed a key then we want to cancel any move to target. 2713 // If the user has pressed a key then we want to cancel any move to target.
2160 if (DCFlagKeyPressed) 2714 if (DCFlagKeyPressed)
@@ -2167,7 +2721,7 @@ namespace OpenSim.Region.Framework.Scenes
2167 // The UseClientAgentPosition is set if parcel ban is forcing the avatar to move to a 2721 // The UseClientAgentPosition is set if parcel ban is forcing the avatar to move to a
2168 // certain position. It's only check for tolerance on returning to that position is 0.2 2722 // certain position. It's only check for tolerance on returning to that position is 0.2
2169 // rather than 1, at which point it removes its force target. 2723 // rather than 1, at which point it removes its force target.
2170 if (HandleMoveToTargetUpdate(agentData.UseClientAgentPosition ? 0.2 : 1, ref agent_control_v3)) 2724 if (HandleMoveToTargetUpdate(agentData.UseClientAgentPosition ? 0.2f : 1f, ref agent_control_v3))
2171 update_movementflag = true; 2725 update_movementflag = true;
2172 } 2726 }
2173 } 2727 }
@@ -2180,11 +2734,11 @@ namespace OpenSim.Region.Framework.Scenes
2180 if (Flying && !ForceFly) 2734 if (Flying && !ForceFly)
2181 { 2735 {
2182 // Need to stop in mid air if user holds down AGENT_CONTROL_STOP 2736 // Need to stop in mid air if user holds down AGENT_CONTROL_STOP
2183 if (AgentControlStopActive) 2737 // if (AgentControlStopActive)
2184 { 2738 // {
2185 agent_control_v3 = Vector3.Zero; 2739 // agent_control_v3 = Vector3.Zero;
2186 } 2740 // }
2187 else 2741 // else
2188 { 2742 {
2189 // Landing detection code 2743 // Landing detection code
2190 2744
@@ -2192,38 +2746,43 @@ namespace OpenSim.Region.Framework.Scenes
2192 bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || 2746 bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) ||
2193 ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); 2747 ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
2194 2748
2195 //m_log.Debug("[CONTROL]: " +flags); 2749 //m_log.Debug("[CONTROL]: " +flags);
2196 // Applies a satisfying roll effect to the avatar when flying. 2750 // 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) 2751 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0 && (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0)
2198 { 2752 {
2199 ApplyFlyingRoll( 2753 ApplyFlyingRoll(
2200 FLY_ROLL_RADIANS_PER_UPDATE, 2754 FLY_ROLL_RADIANS_PER_UPDATE,
2201 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0, 2755 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
2202 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0); 2756 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
2203 } 2757 }
2204 else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0 && 2758 else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0 &&
2205 (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) 2759 (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
2206 { 2760 {
2207 ApplyFlyingRoll( 2761 ApplyFlyingRoll(
2208 -FLY_ROLL_RADIANS_PER_UPDATE, 2762 -FLY_ROLL_RADIANS_PER_UPDATE,
2209 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0, 2763 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
2210 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0); 2764 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
2211 } 2765 }
2212 else 2766 else
2213 { 2767 {
2214 if (m_AngularVelocity.Z != 0) 2768 if (m_AngularVelocity.Z != 0)
2215 m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE); 2769 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 } 2770 }
2771
2772 /*
2773 if (Flying && IsColliding && controlland)
2774 {
2775 // nesting this check because LengthSquared() is expensive and we don't
2776 // want to do it every step when flying.
2777 if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX))
2778 StopFlying();
2779 }
2780 */
2225 } 2781 }
2226 } 2782 }
2783 else if (IsColliding && agent_control_v3.Z < 0f)
2784 agent_control_v3.Z = 0;
2785// else if(AgentControlStopActive %% Velocity.Z <0.01f)
2227 2786
2228// m_log.DebugFormat("[SCENE PRESENCE]: MovementFlag {0} for {1}", MovementFlag, Name); 2787// m_log.DebugFormat("[SCENE PRESENCE]: MovementFlag {0} for {1}", MovementFlag, Name);
2229 2788
@@ -2231,54 +2790,60 @@ namespace OpenSim.Region.Framework.Scenes
2231 // which occurs later in the main scene loop 2790 // which occurs later in the main scene loop
2232 // We also need to update if the user rotates their avatar whilst it is slow walking/running (if they 2791 // We also need to update if the user rotates their avatar whilst it is slow walking/running (if they
2233 // held down AGENT_CONTROL_STOP whilst normal walking/running). However, we do not want to update 2792 // held down AGENT_CONTROL_STOP whilst normal walking/running). However, we do not want to update
2234 // if the user rotated whilst holding down AGENT_CONTROL_STOP when already still (which locks the 2793 // if the user rotated whilst holding down AGENT_CONTROL_STOP when already still (which locks the
2235 // avatar location in place). 2794 // avatar location in place).
2236 if (update_movementflag 2795
2796 if (update_movementflag
2237 || (update_rotation && DCFlagKeyPressed && (!AgentControlStopActive || MovementFlag != 0))) 2797 || (update_rotation && DCFlagKeyPressed && (!AgentControlStopActive || MovementFlag != 0)))
2238 { 2798 {
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 2799
2246 float speedModifier; 2800 if (AgentControlStopActive)
2247 2801 {
2248 if (AgentControlStopActive) 2802 // if (MovementFlag == 0 && Animator.Falling)
2249 speedModifier = AgentControlStopSlowWhilstMoving; 2803 if (MovementFlag == 0 && Animator.currentControlState == ScenePresenceAnimator.motionControlStates.falling)
2804 {
2805 AddNewMovement(agent_control_v3, AgentControlStopSlowVel, true);
2806 }
2250 else 2807 else
2251 speedModifier = 1; 2808 AddNewMovement(agent_control_v3, AgentControlStopSlowVel);
2252 2809 }
2253 AddNewMovement(agent_control_v3, speedModifier); 2810 else
2254// } 2811 {
2812 if(m_movingToTarget ||
2813 (Animator.currentControlState != ScenePresenceAnimator.motionControlStates.flying &&
2814 Animator.currentControlState != ScenePresenceAnimator.motionControlStates.onsurface)
2815 )
2816 AddNewMovement(agent_control_v3);
2817 else
2818 {
2819 if (MovementFlag != 0)
2820 AddNewMovement(agent_control_v3);
2821 else
2822 m_delayedStop = Util.GetTimeStampMS() + 200.0;
2823 }
2824 }
2255 } 2825 }
2256// else 2826/*
2257// { 2827 if (update_movementflag && ParentID == 0 && m_delayedStop < 0)
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
2266 if (update_movementflag && ParentID == 0)
2267 { 2828 {
2268// m_log.DebugFormat("[SCENE PRESENCE]: Updating movement animations for {0}", Name); 2829// m_log.DebugFormat("[SCENE PRESENCE]: Updating movement animations for {0}", Name);
2269 Animator.UpdateMovementAnimations(); 2830 Animator.UpdateMovementAnimations();
2270 } 2831 }
2271 2832*/
2272 SendControlsToScripts(flagsForScripts); 2833 SendControlsToScripts(flagsForScripts);
2273 } 2834 }
2274 2835
2275 // We need to send this back to the client in order to see the edit beams 2836 // We need to send this back to the client in order to see the edit beams
2276 if ((State & (uint)AgentState.Editing) != 0) 2837 if ((State & (uint)AgentState.Editing) != 0)
2277 ControllingClient.SendAgentTerseUpdate(this); 2838 SendAgentTerseUpdate(this);
2278 2839
2279 m_scene.EventManager.TriggerOnClientMovement(this); 2840// m_scene.EventManager.TriggerOnClientMovement(this);
2280 } 2841 }
2281 2842
2843 private void HandleAgentFOV(IClientAPI remoteClient, float _fov)
2844 {
2845 m_FOV = _fov;
2846 }
2282 2847
2283 /// <summary> 2848 /// <summary>
2284 /// This is the event handler for client cameras. If a client is moving, or moving the camera, this event is triggering. 2849 /// This is the event handler for client cameras. If a client is moving, or moving the camera, this event is triggering.
@@ -2290,60 +2855,37 @@ namespace OpenSim.Region.Framework.Scenes
2290 // Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags); 2855 // Scene.RegionInfo.RegionName, remoteClient.Name, (AgentManager.ControlFlags)agentData.ControlFlags);
2291 2856
2292 if (IsChildAgent) 2857 if (IsChildAgent)
2293 {
2294 // // m_log.Debug("DEBUG: HandleAgentUpdate: child agent");
2295 return; 2858 return;
2296 }
2297 2859
2298 ++m_movementUpdateCount; 2860 if(IsInTransit)
2299 if (m_movementUpdateCount < 1) 2861 return;
2300 m_movementUpdateCount = 1;
2301 2862
2302// AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags; 2863// AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags;
2303 2864
2304 // Camera location in world. We'll need to raytrace 2865 // Camera location in world. We'll need to raytrace
2305 // from this location from time to time. 2866 // from this location from time to time.
2306 CameraPosition = agentData.CameraCenter; 2867 CameraPosition = agentData.CameraCenter;
2307 if (Vector3.Distance(m_lastCameraPosition, CameraPosition) >= Scene.RootReprioritizationDistance)
2308 {
2309 ReprioritizeUpdates();
2310 m_lastCameraPosition = CameraPosition;
2311 }
2312
2313 // Use these three vectors to figure out what the agent is looking at 2868 // Use these three vectors to figure out what the agent is looking at
2314 // Convert it to a Matrix and/or Quaternion 2869 // Convert it to a Matrix and/or Quaternion
2870
2871 // this may need lock
2315 CameraAtAxis = agentData.CameraAtAxis; 2872 CameraAtAxis = agentData.CameraAtAxis;
2316 CameraLeftAxis = agentData.CameraLeftAxis; 2873 CameraLeftAxis = agentData.CameraLeftAxis;
2317 CameraUpAxis = agentData.CameraUpAxis; 2874 CameraUpAxis = agentData.CameraUpAxis;
2318
2319 // The Agent's Draw distance setting
2320 // When we get to the point of re-computing neighbors everytime this
2321 // changes, then start using the agent's drawdistance rather than the
2322 // region's draw distance.
2323 DrawDistance = agentData.Far; 2875 DrawDistance = agentData.Far;
2324 // DrawDistance = Scene.DefaultDrawDistance;
2325
2326 // Check if Client has camera in 'follow cam' or 'build' mode.
2327 Vector3 camdif = (Vector3.One * Rotation - Vector3.One * CameraRotation);
2328 2876
2329 m_followCamAuto = ((CameraUpAxis.Z > 0.959f && CameraUpAxis.Z < 0.98f) 2877 CameraAtAxis.Normalize();
2330 && (Math.Abs(camdif.X) < 0.4f && Math.Abs(camdif.Y) < 0.4f)) ? true : false; 2878 CameraLeftAxis.Normalize();
2879 CameraUpAxis.Normalize();
2880 Quaternion camRot = Util.Axes2Rot(CameraAtAxis, CameraLeftAxis, CameraUpAxis);
2881 CameraRotation = camRot;
2331 2882
2332 2883 if(agentData.NeedsCameraCollision)
2333 //m_log.DebugFormat("[FollowCam]: {0}", m_followCamAuto); 2884 checkCameraCollision();
2334 // Raycast from the avatar's head to the camera to see if there's anything blocking the view
2335 if ((m_movementUpdateCount % NumMovementsBetweenRayCast) == 0 && m_scene.PhysicsScene.SupportsRayCast())
2336 {
2337 if (m_followCamAuto)
2338 {
2339 Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT;
2340 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(CameraPosition - posAdjusted), Vector3.Distance(CameraPosition, posAdjusted) + 0.3f, RayCastCameraCallback);
2341 }
2342 }
2343 2885
2344 TriggerScenePresenceUpdated(); 2886 TriggerScenePresenceUpdated();
2345 } 2887 }
2346 2888
2347 /// <summary> 2889 /// <summary>
2348 /// Calculate an update to move the presence to the set target. 2890 /// Calculate an update to move the presence to the set target.
2349 /// </summary> 2891 /// </summary>
@@ -2352,125 +2894,158 @@ namespace OpenSim.Region.Framework.Scenes
2352 /// </remarks> 2894 /// </remarks>
2353 /// <param value="agent_control_v3">Cumulative agent movement that this method will update.</param> 2895 /// <param value="agent_control_v3">Cumulative agent movement that this method will update.</param>
2354 /// <returns>True if movement has been updated in some way. False otherwise.</returns> 2896 /// <returns>True if movement has been updated in some way. False otherwise.</returns>
2355 public bool HandleMoveToTargetUpdate(double tolerance, ref Vector3 agent_control_v3) 2897 public bool HandleMoveToTargetUpdate(float tolerance, ref Vector3 agent_control_v3)
2356 { 2898 {
2357// m_log.DebugFormat("[SCENE PRESENCE]: Called HandleMoveToTargetUpdate() for {0}", Name); 2899// m_log.DebugFormat("[SCENE PRESENCE]: Called HandleMoveToTargetUpdate() for {0}", Name);
2358 2900
2359 bool updated = false; 2901 bool updated = false;
2360 2902
2903 Vector3 LocalVectorToTarget3D = m_moveToPositionTarget - AbsolutePosition;
2904
2361// m_log.DebugFormat( 2905// m_log.DebugFormat(
2362// "[SCENE PRESENCE]: bAllowUpdateMoveToPosition {0}, m_moveToPositionInProgress {1}, m_autopilotMoving {2}", 2906// "[SCENE PRESENCE]: bAllowUpdateMoveToPosition {0}, m_moveToPositionInProgress {1}, m_autopilotMoving {2}",
2363// allowUpdate, m_moveToPositionInProgress, m_autopilotMoving); 2907// allowUpdate, m_moveToPositionInProgress, m_autopilotMoving);
2364 2908
2365 double distanceToTarget = Util.GetDistanceTo(AbsolutePosition, MoveToPositionTarget); 2909 float distanceToTarget;
2910 if(Flying && !LandAtTarget)
2911 {
2912 distanceToTarget = LocalVectorToTarget3D.Length();
2913 }
2914 else
2915 {
2916 distanceToTarget = (float)Math.Sqrt(LocalVectorToTarget3D.X * LocalVectorToTarget3D.X +
2917 LocalVectorToTarget3D.Y * LocalVectorToTarget3D.Y);
2918 }
2366 2919
2367// m_log.DebugFormat( 2920 // m_log.DebugFormat(
2368// "[SCENE PRESENCE]: Abs pos of {0} is {1}, target {2}, distance {3}", 2921 // "[SCENE PRESENCE]: Abs pos of {0} is {1}, target {2}, distance {3}",
2369// Name, AbsolutePosition, MoveToPositionTarget, distanceToTarget); 2922 // Name, AbsolutePosition, MoveToPositionTarget, distanceToTarget);
2370 2923
2371 // Check the error term of the current position in relation to the target position 2924 // Check the error term of the current position in relation to the target position
2372 if (distanceToTarget <= tolerance) 2925 if (distanceToTarget <= tolerance)
2373 { 2926 {
2374 // We are close enough to the target 2927 // We are close enough to the target
2375 AbsolutePosition = MoveToPositionTarget; 2928 Velocity = Vector3.Zero;
2929 AbsolutePosition = m_moveToPositionTarget;
2930 if (Flying)
2931 {
2932 if (LandAtTarget)
2933 Flying = false;
2934
2935 // A horrible hack to stop the avatar dead in its tracks rather than having them overshoot
2936 // the target if flying.
2937 // We really need to be more subtle (slow the avatar as it approaches the target) or at
2938 // least be able to set collision status once, rather than 5 times to give it enough
2939 // weighting so that that PhysicsActor thinks it really is colliding.
2940 for (int i = 0; i < 5; i++)
2941 IsColliding = true;
2942 }
2376 ResetMoveToTarget(); 2943 ResetMoveToTarget();
2377 updated = true; 2944 return false;
2378 } 2945 }
2379 else 2946
2947 if(m_moveToSpeed > 0 && distanceToTarget <= m_moveToSpeed * Scene.FrameTime)
2948 m_moveToSpeed = distanceToTarget / Scene.FrameTime;
2949
2950 try
2380 { 2951 {
2381 try 2952 // move avatar in 3D towards target, in avatar coordinate frame.
2382 { 2953 // This movement vector gets added to the velocity through AddNewMovement().
2383 // move avatar in 3D at one meter/second towards target, in avatar coordinate frame. 2954 // Theoretically we might need a more complex PID approach here if other
2384 // This movement vector gets added to the velocity through AddNewMovement(). 2955 // unknown forces are acting on the avatar and we need to adaptively respond
2385 // Theoretically we might need a more complex PID approach here if other 2956 // to such forces, but the following simple approach seems to works fine.
2386 // 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.
2388 Vector3 LocalVectorToTarget3D =
2389 (MoveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords
2390 * Matrix4.CreateFromQuaternion(Quaternion.Inverse(Rotation)); // change to avatar coords
2391 // Ignore z component of vector
2392// Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f);
2393 LocalVectorToTarget3D.Normalize();
2394
2395 // update avatar movement flags. the avatar coordinate system is as follows:
2396 //
2397 // +X (forward)
2398 //
2399 // ^
2400 // |
2401 // |
2402 // |
2403 // |
2404 // (left) +Y <--------o--------> -Y
2405 // avatar
2406 // |
2407 // |
2408 // |
2409 // |
2410 // v
2411 // -X
2412 //
2413 2957
2414 // based on the above avatar coordinate system, classify the movement into 2958 float angle = 0.5f * (float)Math.Atan2(LocalVectorToTarget3D.Y, LocalVectorToTarget3D.X);
2415 // one of left/right/back/forward. 2959 Quaternion rot = new Quaternion(0,0, (float)Math.Sin(angle),(float)Math.Cos(angle));
2416 if (LocalVectorToTarget3D.X < 0) //MoveBack 2960 Rotation = rot;
2417 { 2961 LocalVectorToTarget3D = LocalVectorToTarget3D * Quaternion.Inverse(rot); // change to avatar coords
2418 MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK; 2962 LocalVectorToTarget3D.Normalize();
2419 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK;
2420 updated = true;
2421 }
2422 else if (LocalVectorToTarget3D.X > 0) //Move Forward
2423 {
2424 MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD;
2425 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD;
2426 updated = true;
2427 }
2428 2963
2429 if (LocalVectorToTarget3D.Y > 0) //MoveLeft 2964 // update avatar movement flags. the avatar coordinate system is as follows:
2430 { 2965 //
2431 MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; 2966 // +X (forward)
2432 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; 2967 //
2433 updated = true; 2968 // ^
2434 } 2969 // |
2435 else if (LocalVectorToTarget3D.Y < 0) //MoveRight 2970 // |
2436 { 2971 // |
2437 MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; 2972 // |
2438 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; 2973 // (left) +Y <--------o--------> -Y
2439 updated = true; 2974 // avatar
2440 } 2975 // |
2976 // |
2977 // |
2978 // |
2979 // v
2980 // -X
2981 //
2441 2982
2442 if (LocalVectorToTarget3D.Z > 0) //Up 2983 // based on the above avatar coordinate system, classify the movement into
2443 { 2984 // one of left/right/back/forward.
2444 // Don't set these flags for up or down - doing so will make the avatar crouch or 2985
2445 // keep trying to jump even if walking along level ground 2986 const uint noMovFlagsMask = (uint)(~(Dir_ControlFlags.DIR_CONTROL_FLAG_BACK |
2446 //MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_UP; 2987 Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD | Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT |
2447 //AgentControlFlags 2988 Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT | Dir_ControlFlags.DIR_CONTROL_FLAG_UP |
2448 //AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_UP; 2989 Dir_ControlFlags.DIR_CONTROL_FLAG_DOWN));
2449 updated = true; 2990
2450 } 2991 MovementFlag &= noMovFlagsMask;
2451 else if (LocalVectorToTarget3D.Z < 0) //Down 2992 uint tmpAgentControlFlags = (uint)m_AgentControlFlags;
2452 { 2993 tmpAgentControlFlags &= noMovFlagsMask;
2453 //MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_DOWN;
2454 //AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_DOWN;
2455 updated = true;
2456 }
2457 2994
2995 if (LocalVectorToTarget3D.X < 0) //MoveBack
2996 {
2997 MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK;
2998 tmpAgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK;
2999 updated = true;
3000 }
3001 else if (LocalVectorToTarget3D.X > 0) //Move Forward
3002 {
3003 MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD;
3004 tmpAgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD;
3005 updated = true;
3006 }
3007
3008 if (LocalVectorToTarget3D.Y > 0) //MoveLeft
3009 {
3010 MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT;
3011 tmpAgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT;
3012 updated = true;
3013 }
3014 else if (LocalVectorToTarget3D.Y < 0) //MoveRight
3015 {
3016 MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT;
3017 tmpAgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT;
3018 updated = true;
3019 }
3020
3021 if (LocalVectorToTarget3D.Z > 0) //Up
3022 updated = true;
3023
3024 else if (LocalVectorToTarget3D.Z < 0) //Down
3025 updated = true;
3026
2458// m_log.DebugFormat( 3027// m_log.DebugFormat(
2459// "[SCENE PRESENCE]: HandleMoveToTargetUpdate adding {0} to move vector {1} for {2}", 3028// "[SCENE PRESENCE]: HandleMoveToTargetUpdate adding {0} to move vector {1} for {2}",
2460// LocalVectorToTarget3D, agent_control_v3, Name); 3029// LocalVectorToTarget3D, agent_control_v3, Name);
2461 3030
3031 m_AgentControlFlags = (AgentManager.ControlFlags) tmpAgentControlFlags;
3032 if(updated)
2462 agent_control_v3 += LocalVectorToTarget3D; 3033 agent_control_v3 += LocalVectorToTarget3D;
2463 } 3034 }
2464 catch (Exception e) 3035 catch (Exception e)
2465 { 3036 {
2466 //Avoid system crash, can be slower but... 3037 //Avoid system crash, can be slower but...
2467 m_log.DebugFormat("Crash! {0}", e.ToString()); 3038 m_log.DebugFormat("Crash! {0}", e.ToString());
2468 }
2469 } 3039 }
2470 3040
2471 return updated; 3041 return updated;
3042// AddNewMovement(agent_control_v3);
2472 } 3043 }
2473 3044
3045 public void MoveToTargetHandle(Vector3 pos, bool noFly, bool landAtTarget)
3046 {
3047 MoveToTarget(pos, noFly, landAtTarget);
3048 }
2474 /// <summary> 3049 /// <summary>
2475 /// Move to the given target over time. 3050 /// Move to the given target over time.
2476 /// </summary> 3051 /// </summary>
@@ -2483,8 +3058,10 @@ namespace OpenSim.Region.Framework.Scenes
2483 /// <param name="landAtTarget"> 3058 /// <param name="landAtTarget">
2484 /// If true and the avatar starts flying during the move then land at the target. 3059 /// If true and the avatar starts flying during the move then land at the target.
2485 /// </param> 3060 /// </param>
2486 public void MoveToTarget(Vector3 pos, bool noFly, bool landAtTarget) 3061 public void MoveToTarget(Vector3 pos, bool noFly, bool landAtTarget, float tau = -1f)
2487 { 3062 {
3063 m_delayedStop = -1;
3064
2488 if (SitGround) 3065 if (SitGround)
2489 StandUp(); 3066 StandUp();
2490 3067
@@ -2494,89 +3071,61 @@ namespace OpenSim.Region.Framework.Scenes
2494 3071
2495 // Allow move to another sub-region within a megaregion 3072 // Allow move to another sub-region within a megaregion
2496 Vector2 regionSize; 3073 Vector2 regionSize;
2497 IRegionCombinerModule regionCombinerModule = m_scene.RequestModuleInterface<IRegionCombinerModule>(); 3074 regionSize = new Vector2(m_scene.RegionInfo.RegionSizeX, m_scene.RegionInfo.RegionSizeY);
2498 if (regionCombinerModule != null)
2499 regionSize = regionCombinerModule.GetSizeOfMegaregion(m_scene.RegionInfo.RegionID);
2500 else
2501 regionSize = new Vector2(m_scene.RegionInfo.RegionSizeX, m_scene.RegionInfo.RegionSizeY);
2502 3075
2503 if (pos.X < 0 || pos.X >= regionSize.X 3076 if (pos.X < 0 || pos.X >= regionSize.X
2504 || pos.Y < 0 || pos.Y >= regionSize.Y 3077 || pos.Y < 0 || pos.Y >= regionSize.Y
2505 || pos.Z < 0) 3078 || pos.Z < 0)
2506 return; 3079 return;
2507 3080
3081 float terrainHeight;
2508 Scene targetScene = m_scene; 3082 Scene targetScene = m_scene;
3083 terrainHeight = m_scene.GetGroundHeight(pos.X, pos.Y);
2509 3084
2510// Vector3 heightAdjust = new Vector3(0, 0, Appearance.AvatarHeight / 2); 3085 // dont try to land underground
2511// pos += heightAdjust; 3086 terrainHeight += Appearance.AvatarHeight * 0.5f + 0.2f;
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 3087
2520 // Get terrain height for sub-region in a megaregion if necessary 3088 if(terrainHeight > pos.Z)
2521
2522 //COMMENT: If its only nessesary in a megaregion, why do it on normal region's too?
2523
2524 if (regionCombinerModule != null)
2525 {
2526 int x = (int)((m_scene.RegionInfo.WorldLocX) + pos.X);
2527 int y = (int)((m_scene.RegionInfo.WorldLocY) + pos.Y);
2528 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
2531 if (target_region == null)
2532 return;
2533
2534 SceneManager.Instance.TryGetScene(target_region.RegionID, out targetScene);
2535 }
2536
2537 float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % regionSize.X), (int)(pos.Y % regionSize.Y)];
2538 pos.Z = Math.Max(terrainHeight, pos.Z);
2539
2540 // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is
2541 // always slightly higher than the actual terrain height.
2542 // FIXME: This constrains NPC movements as well, so should be somewhere else.
2543 if (pos.Z - terrainHeight < 0.2)
2544 pos.Z = terrainHeight; 3089 pos.Z = terrainHeight;
2545 3090
2546 if (noFly)
2547 Flying = false;
2548 else if (pos.Z > terrainHeight)
2549 Flying = true;
2550
2551// m_log.DebugFormat( 3091// m_log.DebugFormat(
2552// "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}", 3092// "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}",
2553// Name, pos, terrainHeight, m_scene.RegionInfo.RegionName); 3093// Name, pos, terrainHeight, m_scene.RegionInfo.RegionName);
2554 3094
2555 if (noFly) 3095 terrainHeight += Appearance.AvatarHeight; // so 1.5 * AvatarHeight above ground at target
2556 Flying = false; 3096 bool shouldfly = Flying;
2557 3097 if (noFly)
2558 LandAtTarget = landAtTarget; 3098 shouldfly = false;
2559 MovingToTarget = true; 3099 else if (pos.Z > terrainHeight || Flying)
2560 MoveToPositionTarget = pos; 3100 shouldfly = true;
2561 3101
2562 // Rotate presence around the z-axis to point in same direction as movement.
2563 // Ignore z component of vector
2564 Vector3 localVectorToTarget3D = pos - AbsolutePosition; 3102 Vector3 localVectorToTarget3D = pos - AbsolutePosition;
2565 Vector3 localVectorToTarget2D = new Vector3((float)(localVectorToTarget3D.X), (float)(localVectorToTarget3D.Y), 0f);
2566 3103
2567// m_log.DebugFormat("[SCENE PRESENCE]: Local vector to target is {0}", localVectorToTarget2D); 3104// m_log.DebugFormat("[SCENE PRESENCE]: Local vector to target is {0},[1}", localVectorToTarget3D.X,localVectorToTarget3D.Y);
3105
3106 m_movingToTarget = true;
3107 LandAtTarget = landAtTarget;
3108 m_moveToPositionTarget = pos;
3109 if(tau > 0)
3110 {
3111 if(tau < Scene.FrameTime)
3112 tau = Scene.FrameTime;
3113 m_moveToSpeed = localVectorToTarget3D.Length() / tau;
3114 if(m_moveToSpeed < 0.5f) //to tune
3115 m_moveToSpeed = 0.5f;
3116 else if(m_moveToSpeed > 50f)
3117 m_moveToSpeed = 50f;
2568 3118
2569 // Calculate the yaw. 3119 SetAlwaysRun = false;
2570 Vector3 angle = new Vector3(0, 0, (float)(Math.Atan2(localVectorToTarget2D.Y, localVectorToTarget2D.X))); 3120 }
3121 else
3122 m_moveToSpeed = 4.096f * m_speedModifier;
2571 3123
2572// m_log.DebugFormat("[SCENE PRESENCE]: Angle is {0}", angle); 3124 Flying = shouldfly;
2573 3125
2574 Rotation = Quaternion.CreateFromEulers(angle); 3126 Vector3 control = Vector3.Zero;
2575// m_log.DebugFormat("[SCENE PRESENCE]: Body rot for {0} set to {1}", Name, Rotation); 3127 if(HandleMoveToTargetUpdate(1f, ref control))
2576 3128 AddNewMovement(control);
2577 Vector3 agent_control_v3 = new Vector3();
2578 HandleMoveToTargetUpdate(1, ref agent_control_v3);
2579 AddNewMovement(agent_control_v3);
2580 } 3129 }
2581 3130
2582 /// <summary> 3131 /// <summary>
@@ -2586,9 +3135,11 @@ namespace OpenSim.Region.Framework.Scenes
2586 { 3135 {
2587// m_log.DebugFormat("[SCENE PRESENCE]: Resetting move to target for {0}", Name); 3136// m_log.DebugFormat("[SCENE PRESENCE]: Resetting move to target for {0}", Name);
2588 3137
2589 MovingToTarget = false; 3138 m_movingToTarget = false;
3139 m_moveToSpeed = -1f;
2590// MoveToPositionTarget = Vector3.Zero; 3140// MoveToPositionTarget = Vector3.Zero;
2591 m_forceToApply = null; // cancel possible last action 3141// lock(m_forceToApplyLock)
3142// m_forceToApplyValid = false; // cancel possible last action
2592 3143
2593 // We need to reset the control flag as the ScenePresenceAnimator uses this to determine the correct 3144 // We need to reset the control flag as the ScenePresenceAnimator uses this to determine the correct
2594 // resting animation (e.g. hover or stand). NPCs don't have a client that will quickly reset this flag. 3145 // resting animation (e.g. hover or stand). NPCs don't have a client that will quickly reset this flag.
@@ -2629,69 +3180,65 @@ namespace OpenSim.Region.Framework.Scenes
2629 } 3180 }
2630 } 3181 }
2631 3182
3183// part.ParentGroup.DeleteAvatar(UUID);
3184
3185 Quaternion standRotation = part.ParentGroup.RootPart.RotationOffset;
3186 Vector3 sitPartWorldPosition = part.ParentGroup.AbsolutePosition + m_pos * standRotation;
2632 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 3187 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
2633 3188
2634 ParentID = 0; 3189 ParentID = 0;
2635 ParentPart = null; 3190 ParentPart = null;
2636 3191
2637 Quaternion standRotation;
2638
2639 if (part.SitTargetAvatar == UUID) 3192 if (part.SitTargetAvatar == UUID)
2640 { 3193 standRotation = standRotation * part.SitTargetOrientation;
2641 standRotation = part.GetWorldRotation(); 3194 else
3195 standRotation = standRotation * m_bodyRot;
2642 3196
2643 if (!part.IsRoot) 3197 m_bodyRot = standRotation;
2644 standRotation = standRotation * part.SitTargetOrientation; 3198
2645// standRotation = part.RotationOffset * part.SitTargetOrientation; 3199 Quaternion standRotationZ = new Quaternion(0,0,standRotation.Z,standRotation.W);
2646// else
2647// standRotation = part.SitTargetOrientation;
2648 3200
3201 float t = standRotationZ.W * standRotationZ.W + standRotationZ.Z * standRotationZ.Z;
3202 if (t > 0)
3203 {
3204 t = 1.0f / (float)Math.Sqrt(t);
3205 standRotationZ.W *= t;
3206 standRotationZ.Z *= t;
2649 } 3207 }
2650 else 3208 else
2651 { 3209 {
2652 standRotation = Rotation; 3210 standRotationZ.W = 1.0f;
3211 standRotationZ.Z = 0f;
2653 } 3212 }
2654 3213
2655 //Vector3 standPos = ParentPosition + new Vector3(0.0f, 0.0f, 2.0f * m_sitAvatarHeight); 3214 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 3215
2662 // XXX: This is based on the physics capsule sizes. Need to find a better way to read this rather than 3216 Vector3 standPos = sitPartWorldPosition + adjustmentForSitPose;
2663 // hardcoding here. 3217 m_pos = standPos;
2664 Vector3 adjustmentForSitPose = new Vector3(0.74f, 0f, 0f) * standRotation;
2665 3218
2666 Vector3 standPos = part.ParentGroup.AbsolutePosition + adjustmentForSitPosition + adjustmentForSitPose;
2667
2668// m_log.DebugFormat(
2669// "[SCENE PRESENCE]: Setting stand to pos {0}, (adjustmentForSitPosition {1}, adjustmentForSitPose {2}) rotation {3} for {4} in {5}",
2670// standPos, adjustmentForSitPosition, adjustmentForSitPose, standRotation, Name, Scene.Name);
2671
2672 Rotation = standRotation;
2673 AbsolutePosition = standPos;
2674 } 3219 }
2675 3220
2676 // We need to wait until we have calculated proper stand positions before sitting up the physical 3221 // We need to wait until we have calculated proper stand positions before sitting up the physical
2677 // avatar to avoid race conditions. 3222 // avatar to avoid race conditions.
2678 if (PhysicsActor == null) 3223 if (PhysicsActor == null)
2679 AddToPhysicalScene(false); 3224 AddToPhysicalScene(false);
2680 3225
2681 if (satOnObject) 3226 if (satOnObject)
2682 { 3227 {
2683 SendAvatarDataToAllClients();
2684 m_requestedSitTargetID = 0; 3228 m_requestedSitTargetID = 0;
2685
2686 part.RemoveSittingAvatar(this); 3229 part.RemoveSittingAvatar(this);
2687
2688 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); 3230 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
3231
3232 SendAvatarDataToAllAgents();
3233 m_scene.EventManager.TriggerParcelPrimCountTainted(); // update select/ sat on
2689 } 3234 }
2690 3235
2691 else if (PhysicsActor == null) 3236 // reset to default sitAnimation
2692 AddToPhysicalScene(false); 3237 sitAnimation = "SIT";
3238
3239// Animator.TrySetMovementAnimation("STAND");
3240 Animator.SetMovementAnimations("STAND");
2693 3241
2694 Animator.TrySetMovementAnimation("STAND");
2695 TriggerScenePresenceUpdated(); 3242 TriggerScenePresenceUpdated();
2696 } 3243 }
2697 3244
@@ -2746,28 +3293,14 @@ namespace OpenSim.Region.Framework.Scenes
2746 3293
2747 if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero) 3294 if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero)
2748 { 3295 {
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; 3296 offset = part.SitTargetPosition;
2754 sitOrientation = part.SitTargetOrientation; 3297 sitOrientation = part.SitTargetOrientation;
2755 3298
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; 3299 canSit = true;
2767 } 3300 }
2768 else 3301 else
2769 { 3302 {
2770 if (PhysicsSit(part,offset)) // physics engine 3303 if (PhysicsSit(part,offset)) // physics engine
2771 return; 3304 return;
2772 3305
2773 Vector3 pos = part.AbsolutePosition + offset; 3306 Vector3 pos = part.AbsolutePosition + offset;
@@ -2781,55 +3314,45 @@ namespace OpenSim.Region.Framework.Scenes
2781 3314
2782 if (canSit) 3315 if (canSit)
2783 { 3316 {
2784
2785 if (PhysicsActor != null) 3317 if (PhysicsActor != null)
2786 { 3318 {
2787 // We can remove the physicsActor until they stand up. 3319 // We can remove the physicsActor until they stand up.
2788 RemoveFromPhysicalScene(); 3320 RemoveFromPhysicalScene();
2789 } 3321 }
2790 3322
2791 if (MovingToTarget) 3323 if (m_movingToTarget)
2792 ResetMoveToTarget(); 3324 ResetMoveToTarget();
2793 3325
2794 Velocity = Vector3.Zero; 3326 Velocity = Vector3.Zero;
3327 m_AngularVelocity = Vector3.Zero;
2795 3328
2796 part.AddSittingAvatar(this); 3329 part.AddSittingAvatar(this);
2797 3330
2798 cameraAtOffset = part.GetCameraAtOffset(); 3331 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(); 3332 cameraEyeOffset = part.GetCameraEyeOffset();
2805 3333
2806 if (!part.IsRoot && cameraEyeOffset == Vector3.Zero) 3334 forceMouselook = part.GetForceMouselook();
2807 {
2808 cameraEyeOffset = part.ParentGroup.RootPart.GetCameraEyeOffset();
2809 cameraEyeOffsetFromRootForChild = true;
2810 }
2811 3335
2812 if ((cameraEyeOffset != Vector3.Zero && !cameraEyeOffsetFromRootForChild) || cameraAtOffset != Vector3.Zero) 3336 if (!part.IsRoot)
2813 { 3337 {
2814 if (!part.IsRoot) 3338 sitOrientation = part.RotationOffset * sitOrientation;
3339 offset = offset * part.RotationOffset;
3340 offset += part.OffsetPosition;
3341
3342 if (cameraAtOffset == Vector3.Zero && cameraEyeOffset == Vector3.Zero)
2815 { 3343 {
2816 cameraEyeOffset = cameraEyeOffset * part.RotationOffset; 3344 cameraAtOffset = part.ParentGroup.RootPart.GetCameraAtOffset();
3345 cameraEyeOffset = part.ParentGroup.RootPart.GetCameraEyeOffset();
3346 }
3347 else
3348 {
3349 cameraAtOffset = cameraAtOffset * part.RotationOffset;
2817 cameraAtOffset += part.OffsetPosition; 3350 cameraAtOffset += part.OffsetPosition;
3351 cameraEyeOffset = cameraEyeOffset * part.RotationOffset;
3352 cameraEyeOffset += part.OffsetPosition;
2818 } 3353 }
2819
2820 cameraEyeOffset += part.OffsetPosition;
2821 } 3354 }
2822 3355
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
2833 ControllingClient.SendSitResponse( 3356 ControllingClient.SendSitResponse(
2834 part.ParentGroup.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); 3357 part.ParentGroup.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook);
2835 3358
@@ -2840,6 +3363,7 @@ namespace OpenSim.Region.Framework.Scenes
2840 // Moved here to avoid a race with default sit anim 3363 // Moved here to avoid a race with default sit anim
2841 // The script event needs to be raised after the default sit anim is set. 3364 // The script event needs to be raised after the default sit anim is set.
2842 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); 3365 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
3366 m_scene.EventManager.TriggerParcelPrimCountTainted(); // update select/ sat on
2843 } 3367 }
2844 } 3368 }
2845 3369
@@ -2862,7 +3386,6 @@ namespace OpenSim.Region.Framework.Scenes
2862 { 3386 {
2863 m_requestedSitTargetID = part.LocalId; 3387 m_requestedSitTargetID = part.LocalId;
2864 m_requestedSitTargetUUID = part.UUID; 3388 m_requestedSitTargetUUID = part.UUID;
2865
2866 } 3389 }
2867 else 3390 else
2868 { 3391 {
@@ -2875,13 +3398,8 @@ namespace OpenSim.Region.Framework.Scenes
2875 // returns false if does not suport so older sit can be tried 3398 // returns false if does not suport so older sit can be tried
2876 public bool PhysicsSit(SceneObjectPart part, Vector3 offset) 3399 public bool PhysicsSit(SceneObjectPart part, Vector3 offset)
2877 { 3400 {
2878// TODO: Pull in these bits
2879 return false;
2880/*
2881 if (part == null || part.ParentGroup.IsAttachment) 3401 if (part == null || part.ParentGroup.IsAttachment)
2882 {
2883 return true; 3402 return true;
2884 }
2885 3403
2886 if ( m_scene.PhysicsScene == null) 3404 if ( m_scene.PhysicsScene == null)
2887 return false; 3405 return false;
@@ -2893,24 +3411,20 @@ namespace OpenSim.Region.Framework.Scenes
2893 ControllingClient.SendAlertMessage(" There is no suitable surface to sit on, try another spot."); 3411 ControllingClient.SendAlertMessage(" There is no suitable surface to sit on, try another spot.");
2894 else 3412 else
2895 { // non physical phantom TODO 3413 { // non physical phantom TODO
2896 ControllingClient.SendAlertMessage(" There is no suitable surface to sit on, try another spot."); 3414// ControllingClient.SendAlertMessage(" There is no suitable surface to sit on, try another spot.");
2897 return false; 3415 return false;
2898 } 3416 }
2899 return true; 3417 return true;
2900 } 3418 }
2901 3419
2902
2903 // not doing autopilot
2904 m_requestedSitTargetID = 0;
2905
2906 if (m_scene.PhysicsScene.SitAvatar(part.PhysActor, AbsolutePosition, CameraPosition, offset, new Vector3(0.35f, 0, 0.65f), PhysicsSitResponse) != 0) 3420 if (m_scene.PhysicsScene.SitAvatar(part.PhysActor, AbsolutePosition, CameraPosition, offset, new Vector3(0.35f, 0, 0.65f), PhysicsSitResponse) != 0)
3421 {
2907 return true; 3422 return true;
3423 }
2908 3424
2909 return false; 3425 return false;
2910*/
2911 } 3426 }
2912 3427
2913
2914 private bool CanEnterLandPosition(Vector3 testPos) 3428 private bool CanEnterLandPosition(Vector3 testPos)
2915 { 3429 {
2916 ILandObject land = m_scene.LandChannel.GetLandObject(testPos.X, testPos.Y); 3430 ILandObject land = m_scene.LandChannel.GetLandObject(testPos.X, testPos.Y);
@@ -2939,7 +3453,7 @@ namespace OpenSim.Region.Framework.Scenes
2939 if (part == null) 3453 if (part == null)
2940 return; 3454 return;
2941 3455
2942 Vector3 targetPos = part.GetWorldPosition() + offset * part.GetWorldRotation(); 3456 Vector3 targetPos = part.GetWorldPosition() + offset * part.GetWorldRotation();
2943 if(!CanEnterLandPosition(targetPos)) 3457 if(!CanEnterLandPosition(targetPos))
2944 { 3458 {
2945 ControllingClient.SendAlertMessage(" Sit position on restricted land, try another spot"); 3459 ControllingClient.SendAlertMessage(" Sit position on restricted land, try another spot");
@@ -2948,36 +3462,58 @@ namespace OpenSim.Region.Framework.Scenes
2948 3462
2949 RemoveFromPhysicalScene(); 3463 RemoveFromPhysicalScene();
2950 3464
2951 if (MovingToTarget) 3465 if (m_movingToTarget)
2952 ResetMoveToTarget(); 3466 ResetMoveToTarget();
2953 3467
2954 Velocity = Vector3.Zero; 3468 Velocity = Vector3.Zero;
3469 m_AngularVelocity = Vector3.Zero;
2955 3470
3471 m_requestedSitTargetID = 0;
2956 part.AddSittingAvatar(this); 3472 part.AddSittingAvatar(this);
2957 3473
3474 ParentPart = part;
3475 ParentID = part.LocalId;
3476
2958 Vector3 cameraAtOffset = part.GetCameraAtOffset(); 3477 Vector3 cameraAtOffset = part.GetCameraAtOffset();
2959 Vector3 cameraEyeOffset = part.GetCameraEyeOffset(); 3478 Vector3 cameraEyeOffset = part.GetCameraEyeOffset();
2960 bool forceMouselook = part.GetForceMouselook(); 3479 bool forceMouselook = part.GetForceMouselook();
2961 3480
2962 ControllingClient.SendSitResponse( 3481 if (!part.IsRoot)
2963 part.UUID, offset, Orientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); 3482 {
3483 Orientation = part.RotationOffset * Orientation;
3484 offset = offset * part.RotationOffset;
3485 offset += part.OffsetPosition;
2964 3486
2965 // not using autopilot 3487 if (cameraAtOffset == Vector3.Zero && cameraEyeOffset == Vector3.Zero)
3488 {
3489 cameraAtOffset = part.ParentGroup.RootPart.GetCameraAtOffset();
3490 cameraEyeOffset = part.ParentGroup.RootPart.GetCameraEyeOffset();
3491 }
3492 else
3493 {
3494 cameraAtOffset = cameraAtOffset * part.RotationOffset;
3495 cameraAtOffset += part.OffsetPosition;
3496 cameraEyeOffset = cameraEyeOffset * part.RotationOffset;
3497 cameraEyeOffset += part.OffsetPosition;
3498 }
3499 }
2966 3500
2967 Rotation = Orientation; 3501 m_bodyRot = Orientation;
2968 m_pos = offset; 3502 m_pos = offset;
2969 3503
2970 m_requestedSitTargetID = 0; 3504 ControllingClient.SendSitResponse(
3505 part.ParentGroup.UUID, offset, Orientation, true, cameraAtOffset, cameraEyeOffset, forceMouselook);
2971 3506
2972 ParentPart = part; 3507 SendAvatarDataToAllAgents();
2973 ParentID = part.LocalId; 3508
2974 if(status == 3) 3509 if (status == 3)
2975 Animator.TrySetMovementAnimation("SIT_GROUND"); 3510 sitAnimation = "SIT_GROUND";
2976 else 3511 else
2977 Animator.TrySetMovementAnimation("SIT"); 3512 sitAnimation = "SIT";
2978 SendAvatarDataToAllClients();
2979 3513
3514 Animator.SetMovementAnimations("SIT");
2980 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); 3515 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
3516 m_scene.EventManager.TriggerParcelPrimCountTainted(); // update select/ sat on
2981 } 3517 }
2982 3518
2983 public void HandleAgentSit(IClientAPI remoteClient, UUID agentID) 3519 public void HandleAgentSit(IClientAPI remoteClient, UUID agentID)
@@ -2985,7 +3521,7 @@ namespace OpenSim.Region.Framework.Scenes
2985 if (IsChildAgent) 3521 if (IsChildAgent)
2986 return; 3522 return;
2987 3523
2988 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID); 3524 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
2989 3525
2990 if (part != null) 3526 if (part != null)
2991 { 3527 {
@@ -3007,45 +3543,77 @@ namespace OpenSim.Region.Framework.Scenes
3007// "[SCENE PRESENCE]: Sitting {0} at sit target {1}, {2} on {3} {4}", 3543// "[SCENE PRESENCE]: Sitting {0} at sit target {1}, {2} on {3} {4}",
3008// Name, sitTargetPos, sitTargetOrient, part.Name, part.LocalId); 3544// Name, sitTargetPos, sitTargetOrient, part.Name, part.LocalId);
3009 3545
3010 //Quaternion vq = new Quaternion(sitTargetPos.X, sitTargetPos.Y+0.2f, sitTargetPos.Z+0.2f, 0); 3546 double x, y, z, m;
3011 //Quaternion nq = new Quaternion(-sitTargetOrient.X, -sitTargetOrient.Y, -sitTargetOrient.Z, sitTargetOrient.w); 3547 Vector3 sitOffset;
3012 3548 Quaternion r = sitTargetOrient;
3013 //Quaternion result = (sitTargetOrient * vq) * nq;
3014 3549
3015 double x, y, z, m1, m2; 3550 Vector3 newPos;
3016 3551
3017 Quaternion r = sitTargetOrient; 3552 if (LegacySitOffsets)
3018 m1 = r.X * r.X + r.Y * r.Y;
3019 m2 = r.Z * r.Z + r.W * r.W;
3020
3021 // Rotate the vector <0, 0, 1>
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 { 3553 {
3040 offset /= m; 3554 double m1,m2;
3555
3556 m1 = r.X * r.X + r.Y * r.Y;
3557 m2 = r.Z * r.Z + r.W * r.W;
3558
3559 // Rotate the vector <0, 0, 1>
3560 x = 2 * (r.X * r.Z + r.Y * r.W);
3561 y = 2 * (-r.X * r.W + r.Y * r.Z);
3562 z = m2 - m1;
3563
3564 // Set m to be the square of the norm of r.
3565 m = m1 + m2;
3566
3567 // This constant is emperically determined to be what is used in SL.
3568 // See also http://opensimulator.org/mantis/view.php?id=7096
3569 double offset = 0.05;
3570
3571 // Normally m will be ~ 1, but if someone passed a handcrafted quaternion
3572 // to llSitTarget with values so small that squaring them is rounded off
3573 // to zero, then m could be zero. The result of this floating point
3574 // round off error (causing us to skip this impossible normalization)
3575 // is only 5 cm.
3576 if (m > 0.000001)
3577 {
3578 offset /= m;
3579 }
3580
3581 Vector3 up = new Vector3((float)x, (float)y, (float)z);
3582 sitOffset = up * (float)offset;
3583 newPos = sitTargetPos - sitOffset + SIT_TARGET_ADJUSTMENT;
3041 } 3584 }
3585 else
3586 {
3587 m = r.X * r.X + r.Y * r.Y + r.Z * r.Z + r.W * r.W;
3588
3589 if (Math.Abs(1.0 - m) > 0.000001)
3590 {
3591 if(m != 0)
3592 {
3593 m = 1.0 / Math.Sqrt(m);
3594 r.X *= (float)m;
3595 r.Y *= (float)m;
3596 r.Z *= (float)m;
3597 r.W *= (float)m;
3598 }
3599 else
3600 {
3601 r.X = 0.0f;
3602 r.Y = 0.0f;
3603 r.Z = 0.0f;
3604 r.W = 1.0f;
3605 m = 1.0f;
3606 }
3607 }
3042 3608
3043 Vector3 up = new Vector3((float)x, (float)y, (float)z); 3609 x = 2 * (r.X * r.Z + r.Y * r.W);
3044 Vector3 sitOffset = up * (float)offset; 3610 y = 2 * (-r.X * r.W + r.Y * r.Z);
3611 z = -r.X * r.X - r.Y * r.Y + r.Z * r.Z + r.W * r.W;
3612 Vector3 up = new Vector3((float)x, (float)y, (float)z);
3613 sitOffset = up * Appearance.AvatarHeight * 0.02638f;
3614 newPos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT;
3615 }
3045 3616
3046 // sitOffset is in Avatar Center coordinates: from origin to 'sitTargetPos + 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; 3617 Quaternion newRot;
3050 3618
3051 if (part.IsRoot) 3619 if (part.IsRoot)
@@ -3078,19 +3646,25 @@ namespace OpenSim.Region.Framework.Scenes
3078// Name, part.AbsolutePosition, m_pos, ParentPosition, part.Name, part.LocalId); 3646// Name, part.AbsolutePosition, m_pos, ParentPosition, part.Name, part.LocalId);
3079 } 3647 }
3080 3648
3649 part.AddSittingAvatar(this);
3081 ParentPart = part; 3650 ParentPart = part;
3082 ParentID = m_requestedSitTargetID; 3651 ParentID = m_requestedSitTargetID;
3652
3653 RemoveFromPhysicalScene();
3083 m_AngularVelocity = Vector3.Zero; 3654 m_AngularVelocity = Vector3.Zero;
3084 Velocity = Vector3.Zero; 3655 Velocity = Vector3.Zero;
3085 RemoveFromPhysicalScene();
3086 3656
3087 String sitAnimation = "SIT"; 3657 m_requestedSitTargetID = 0;
3658
3659 SendAvatarDataToAllAgents();
3660
3661 sitAnimation = "SIT";
3088 if (!String.IsNullOrEmpty(part.SitAnimation)) 3662 if (!String.IsNullOrEmpty(part.SitAnimation))
3089 { 3663 {
3090 sitAnimation = part.SitAnimation; 3664 sitAnimation = part.SitAnimation;
3091 } 3665 }
3092 Animator.TrySetMovementAnimation(sitAnimation); 3666// Animator.TrySetMovementAnimation(sitAnimation);
3093 SendAvatarDataToAllClients(); 3667 Animator.SetMovementAnimations("SIT");
3094 TriggerScenePresenceUpdated(); 3668 TriggerScenePresenceUpdated();
3095 } 3669 }
3096 } 3670 }
@@ -3101,11 +3675,17 @@ namespace OpenSim.Region.Framework.Scenes
3101 return; 3675 return;
3102 3676
3103// m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.. 3677// m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick..
3104 m_AngularVelocity = Vector3.Zero; 3678 sitAnimation = "SIT_GROUND_CONSTRAINED";
3105 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); 3679// Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
3106 TriggerScenePresenceUpdated(); 3680// TriggerScenePresenceUpdated();
3107 SitGround = true; 3681 SitGround = true;
3108 RemoveFromPhysicalScene(); 3682 RemoveFromPhysicalScene();
3683
3684 m_AngularVelocity = Vector3.Zero;
3685 Velocity = Vector3.Zero;
3686
3687 Animator.SetMovementAnimations("SITGROUND");
3688 TriggerScenePresenceUpdated();
3109 } 3689 }
3110 3690
3111 /// <summary> 3691 /// <summary>
@@ -3129,86 +3709,84 @@ namespace OpenSim.Region.Framework.Scenes
3129 TriggerScenePresenceUpdated(); 3709 TriggerScenePresenceUpdated();
3130 } 3710 }
3131 3711
3712 public void avnHandleChangeAnim(UUID animID, bool addRemove,bool sendPack)
3713 {
3714 Animator.avnChangeAnim(animID, addRemove, sendPack);
3715 }
3716
3132 /// <summary> 3717 /// <summary>
3133 /// Rotate the avatar to the given rotation and apply a movement in the given relative vector 3718 /// Rotate the avatar to the given rotation and apply a movement in the given relative vector
3134 /// </summary> 3719 /// </summary>
3135 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> 3720 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param>
3136 /// <param name="thisAddSpeedModifier"> 3721 /// <param name="thisAddSpeedModifier">
3137 /// Optional additional speed modifier for this particular add. Default is 1</param> 3722 /// Optional additional speed modifier for this particular add. Default is 1</param>
3138 public void AddNewMovement(Vector3 vec, float thisAddSpeedModifier = 1) 3723 public void AddNewMovement(Vector3 vec, float thisAddSpeedModifier = 1, bool breaking = false)
3139 { 3724 {
3140// m_log.DebugFormat( 3725 // m_log.DebugFormat(
3141// "[SCENE PRESENCE]: Adding new movement {0} with rotation {1}, thisAddSpeedModifier {2} for {3}", 3726 // "[SCENE PRESENCE]: Adding new movement {0} with rotation {1}, thisAddSpeedModifier {2} for {3}",
3142// vec, Rotation, thisAddSpeedModifier, Name); 3727 // vec, Rotation, thisAddSpeedModifier, Name);
3143 3728 m_delayedStop = -1;
3729 // rotate from avatar coord space to world
3144 Quaternion rot = Rotation; 3730 Quaternion rot = Rotation;
3145 if (!Flying && PresenceType != PresenceType.Npc) 3731 if (!Flying && PresenceType != PresenceType.Npc)
3146 { 3732 {
3147 // The only situation in which we care about X and Y is avatar flying. The rest of the time 3733 // force rotation to be around Z only, if not flying
3148 // these parameters are not relevant for determining avatar movement direction and cause issues such 3734 // needed for mouselook
3149 // as wrong walk speed if the camera is rotated.
3150 rot.X = 0; 3735 rot.X = 0;
3151 rot.Y = 0; 3736 rot.Y = 0;
3152 rot.Normalize();
3153 } 3737 }
3154 3738
3155 Vector3 direc = vec * rot; 3739 Vector3 direc = vec * rot;
3156 direc.Normalize(); 3740 direc.Normalize();
3157 3741
3158 if (Flying != FlyingOld) // add for fly velocity control
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) 3742 if ((vec.Z == 0f) && !Flying)
3169 direc.Z = 0f; // Prevent camera WASD up. 3743 direc.Z = 0f; // Prevent camera WASD up.
3170 3744
3171 direc *= 0.03f * 128f * SpeedModifier * thisAddSpeedModifier; 3745 bool notmvtrgt = !m_movingToTarget || m_moveToSpeed <= 0;
3746 // odd rescalings
3747 if(notmvtrgt)
3748 direc *= 4.096f * SpeedModifier * thisAddSpeedModifier;
3749 else
3750 direc *= m_moveToSpeed;
3172 3751
3173// m_log.DebugFormat("[SCENE PRESENCE]: Force to apply before modification was {0} for {1}", direc, Name); 3752 // m_log.DebugFormat("[SCENE PRESENCE]: Force to apply before modification was {0} for {1}", direc, Name);
3174 3753
3175 if (PhysicsActor != null) 3754 if (Animator.currentControlState == ScenePresenceAnimator.motionControlStates.falling
3755 && (PhysicsActor == null || !PhysicsActor.PIDHoverActive))
3176 { 3756 {
3177 if (Flying) 3757 if (breaking)
3178 { 3758 direc.Z = -9999f; //hack to tell physics to stop on Z
3759 else
3760 direc = Vector3.Zero;
3761 }
3762 else if (Flying)
3763 {
3764 if (IsColliding && direc.Z < 0)
3765 // landing situation, prevent avatar moving or it may fail to land
3766 // animator will handle this condition and do the land
3767 direc = Vector3.Zero;
3768 else if(notmvtrgt)
3179 direc *= 4.0f; 3769 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)); 3770 }
3181 //if (controlland) 3771 else if (IsColliding)
3182 // m_log.Info("[AGENT]: landCommand"); 3772 {
3183 //if (IsColliding) 3773 if (direc.Z > 2.0f && notmvtrgt) // 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 {
3193 direc *= 0.0f;
3194 }
3195 else if (!Flying && IsColliding)
3196 { 3774 {
3197 if (direc.Z > 2.0f) 3775 direc.Z *= 2.6f;
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 } 3776 }
3777 else if (direc.Z < 0) // on a surface moving down (pg down) only changes animation
3778 direc.Z = 0;
3206 } 3779 }
3207 3780
3208// m_log.DebugFormat("[SCENE PRESENCE]: Setting force to apply to {0} for {1}", direc, Name); 3781 // m_log.DebugFormat("[SCENE PRESENCE]: Setting force to apply to {0} for {1}", direc, Name);
3209 3782/*
3210 // TODO: Add the force instead of only setting it to support multiple forces per frame? 3783 lock(m_forceToApplyLock)
3211 m_forceToApply = direc; 3784 {
3785 m_forceToApply = direc;
3786 m_forceToApplyValid = true;
3787 }
3788*/
3789 TargetVelocity = direc;
3212 Animator.UpdateMovementAnimations(); 3790 Animator.UpdateMovementAnimations();
3213 } 3791 }
3214 3792
@@ -3216,51 +3794,116 @@ namespace OpenSim.Region.Framework.Scenes
3216 3794
3217 #region Overridden Methods 3795 #region Overridden Methods
3218 3796
3797 const float ROTATION_TOLERANCE = 0.01f;
3798 const float VELOCITY_TOLERANCE = 0.1f;
3799 const float LOWVELOCITYSQ = 0.1f;
3800 const float POSITION_LARGETOLERANCE = 5f;
3801 const float POSITION_SMALLTOLERANCE = 0.05f;
3802
3219 public override void Update() 3803 public override void Update()
3220 { 3804 {
3221 if (IsChildAgent == false) 3805 if(IsChildAgent || IsDeleted)
3222 { 3806 return;
3223 // NOTE: Velocity is not the same as m_velocity. Velocity will attempt to 3807
3224 // grab the latest PhysicsActor velocity, whereas m_velocity is often 3808 CheckForBorderCrossing();
3225 // storing a requested force instead of an actual traveling velocity
3226 if (Appearance.AvatarSize != m_lastSize && !IsLoggingIn)
3227 SendAvatarDataToAllClients();
3228 3809
3229 // Allow any updates for sitting avatars to that llSetPrimitiveLinkParams() can work for very 3810 if (IsInTransit || IsLoggingIn)
3230 // small increments (e.g. sit position adjusters). An alternative may be to eliminate the tolerance 3811 return;
3231 // checks on all updates but the ramifications of this would need careful consideration.
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 3812
3241 if (updateClients) 3813 if(m_movingToTarget)
3814 {
3815 m_delayedStop = -1;
3816 Vector3 control = Vector3.Zero;
3817 if(HandleMoveToTargetUpdate(1f, ref control))
3818 AddNewMovement(control);
3819 }
3820 else if(m_delayedStop > 0)
3821 {
3822 if(IsSatOnObject)
3823 m_delayedStop = -1;
3824 else
3825 if(Util.GetTimeStampMS() > m_delayedStop)
3826 AddNewMovement(Vector3.Zero);
3827 }
3828
3829 if (Appearance.AvatarSize != m_lastSize)
3830 SendAvatarDataToAllAgents();
3831
3832 // Send terse position update if not sitting and position, velocity, or rotation
3833 // has changed significantly from last sent update
3834 if (!IsSatOnObject)
3835 {
3836 // this does need to be more complex later
3837 Vector3 vel = Velocity;
3838 Vector3 dpos = m_pos - m_lastPosition;
3839 if( State != m_lastState ||
3840 Math.Abs(vel.X - m_lastVelocity.X) > VELOCITY_TOLERANCE ||
3841 Math.Abs(vel.Y - m_lastVelocity.Y) > VELOCITY_TOLERANCE ||
3842 Math.Abs(vel.Z - m_lastVelocity.Z) > VELOCITY_TOLERANCE ||
3843
3844 Math.Abs(m_bodyRot.X - m_lastRotation.X) > ROTATION_TOLERANCE ||
3845 Math.Abs(m_bodyRot.Y - m_lastRotation.Y) > ROTATION_TOLERANCE ||
3846 Math.Abs(m_bodyRot.Z - m_lastRotation.Z) > ROTATION_TOLERANCE ||
3847
3848 (vel == Vector3.Zero && m_lastVelocity != Vector3.Zero) ||
3849
3850 Math.Abs(dpos.X) > POSITION_LARGETOLERANCE ||
3851 Math.Abs(dpos.Y) > POSITION_LARGETOLERANCE ||
3852 Math.Abs(dpos.Z) > POSITION_LARGETOLERANCE ||
3853
3854 ( (Math.Abs(dpos.X) > POSITION_SMALLTOLERANCE ||
3855 Math.Abs(dpos.Y) > POSITION_SMALLTOLERANCE ||
3856 Math.Abs(dpos.Z) > POSITION_SMALLTOLERANCE)
3857 && vel.LengthSquared() < LOWVELOCITYSQ
3858 ) ||
3859
3860 Math.Abs(CollisionPlane.X - m_lastCollisionPlane.X) > POSITION_SMALLTOLERANCE ||
3861 Math.Abs(CollisionPlane.Y - m_lastCollisionPlane.Y) > POSITION_SMALLTOLERANCE ||
3862 Math.Abs(CollisionPlane.W - m_lastCollisionPlane.W) > POSITION_SMALLTOLERANCE
3863 )
3242 { 3864 {
3243 SendTerseUpdateToAllClients(); 3865 SendTerseUpdateToAllClients();
3244
3245 // Update the "last" values
3246 m_lastPosition = m_pos;
3247 m_lastRotation = Rotation;
3248 m_lastVelocity = Velocity;
3249 } 3866 }
3250
3251 if (Scene.AllowAvatarCrossing)
3252 CheckForBorderCrossing();
3253
3254 CheckForSignificantMovement(); // sends update to the modules.
3255 } 3867 }
3868 CheckForSignificantMovement();
3256 } 3869 }
3257 3870
3258 #endregion 3871 #endregion
3259 3872
3260 #region Update Client(s) 3873 #region Update Client(s)
3261 3874
3875 public void SendUpdateToAgent(ScenePresence p)
3876 {
3877 IClientAPI remoteClient = p.ControllingClient;
3878
3879 if (remoteClient.IsActive)
3880 {
3881 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
3882 remoteClient.SendEntityUpdate(this, PrimUpdateFlags.FullUpdate);
3883 m_scene.StatsReporter.AddAgentUpdates(1);
3884 }
3885 }
3886
3887 public void SendFullUpdateToClient(IClientAPI remoteClient)
3888 {
3889 if (remoteClient.IsActive)
3890 {
3891 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
3892 remoteClient.SendEntityUpdate(this, PrimUpdateFlags.FullUpdate);
3893 m_scene.StatsReporter.AddAgentUpdates(1);
3894 }
3895 }
3896
3897 // this is diferente from SendTerseUpdateToClient
3898 // this sends bypassing entities updates
3899 public void SendAgentTerseUpdate(ISceneEntity p)
3900 {
3901 ControllingClient.SendAgentTerseUpdate(p);
3902 }
3903
3262 /// <summary> 3904 /// <summary>
3263 /// Sends a location update to the client connected to this scenePresence 3905 /// Sends a location update to the client connected to this scenePresence
3906 /// via entity updates
3264 /// </summary> 3907 /// </summary>
3265 /// <param name="remoteClient"></param> 3908 /// <param name="remoteClient"></param>
3266 public void SendTerseUpdateToClient(IClientAPI remoteClient) 3909 public void SendTerseUpdateToClient(IClientAPI remoteClient)
@@ -3269,31 +3912,7 @@ namespace OpenSim.Region.Framework.Scenes
3269 // server. 3912 // server.
3270 if (remoteClient.IsActive) 3913 if (remoteClient.IsActive)
3271 { 3914 {
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); 3915 //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( 3916 remoteClient.SendEntityUpdate(
3298 this, 3917 this,
3299 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity 3918 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
@@ -3303,59 +3922,51 @@ namespace OpenSim.Region.Framework.Scenes
3303 } 3922 }
3304 } 3923 }
3305 3924
3306 3925 public void SendTerseUpdateToAgent(ScenePresence p)
3307 // vars to support reduced update frequency when velocity is unchanged
3308 private Vector3 lastVelocitySentToAllClients = Vector3.Zero;
3309 private Vector3 lastPositionSentToAllClients = Vector3.Zero;
3310 private int lastTerseUpdateToAllClientsTick = Util.EnvironmentTickCount();
3311
3312 /// <summary>
3313 /// Send a location/velocity/accelleration update to all agents in scene
3314 /// </summary>
3315 public void SendTerseUpdateToAllClients()
3316 { 3926 {
3317 int currentTick = Util.EnvironmentTickCount(); 3927 IClientAPI remoteClient = p.ControllingClient;
3318
3319 // Decrease update frequency when avatar is moving but velocity is
3320 // not changing.
3321 // If there is a mismatch between distance travelled and expected
3322 // distance based on last velocity sent and velocity hasnt changed,
3323 // then send a new terse update
3324
3325 float timeSinceLastUpdate = (currentTick - lastTerseUpdateToAllClientsTick) * 0.001f;
3326
3327 Vector3 expectedPosition = lastPositionSentToAllClients + lastVelocitySentToAllClients * timeSinceLastUpdate;
3328 3928
3329 float distanceError = Vector3.Distance(OffsetPosition, expectedPosition); 3929 if (!remoteClient.IsActive)
3930 return;
3330 3931
3331 float speed = Velocity.Length(); 3932 if (ParcelHideThisAvatar && p.currentParcelUUID != currentParcelUUID && !p.IsViewerUIGod)
3332 float velocityDiff = Vector3.Distance(lastVelocitySentToAllClients, Velocity); 3933 return;
3333 3934
3334// m_log.DebugFormat( 3935 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
3335// "[SCENE PRESENCE]: Delta-v {0}, lastVelocity {1}, Velocity {2} for {3} in {4}", 3936 remoteClient.SendEntityUpdate(
3336// velocidyDiff, lastVelocitySentToAllClients, Velocity, Name, Scene.Name); 3937 this,
3938 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
3939 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
3337 3940
3338 // assuming 5 ms. worst case precision for timer, use 2x that 3941 m_scene.StatsReporter.AddAgentUpdates(1);
3339 // for distance error threshold 3942 }
3340 float distanceErrorThreshold = speed * 0.01f;
3341 3943
3342 if (speed < 0.01f // allow rotation updates if avatar position is unchanged 3944 public void SendTerseUpdateToAgentNF(ScenePresence p)
3343 || Math.Abs(distanceError) > distanceErrorThreshold 3945 {
3344 || velocityDiff > 0.01f) // did velocity change from last update? 3946 IClientAPI remoteClient = p.ControllingClient;
3947 if (remoteClient.IsActive)
3345 { 3948 {
3346// m_log.DebugFormat( 3949 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
3347// "[SCENE PRESENCE]: Update triggered with speed {0}, distanceError {1}, distanceThreshold {2}, delta-v {3} for {4} in {5}", 3950 remoteClient.SendEntityUpdate(this,
3348// speed, distanceError, distanceErrorThreshold, velocidyDiff, Name, Scene.Name); 3951 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
3349 3952 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
3350 lastVelocitySentToAllClients = Velocity; 3953 m_scene.StatsReporter.AddAgentUpdates(1);
3351 lastTerseUpdateToAllClientsTick = currentTick; 3954 }
3352 lastPositionSentToAllClients = OffsetPosition; 3955 }
3353 3956
3354 m_terseUpdateCount++; 3957 /// <summary>
3958 /// Send a location/velocity/accelleration update to all agents in scene
3959 /// </summary>
3960 public void SendTerseUpdateToAllClients()
3961 {
3962 m_lastState = State;
3963 m_lastPosition = m_pos;
3964 m_lastRotation = m_bodyRot;
3965 m_lastVelocity = Velocity;
3966 m_lastCollisionPlane = CollisionPlane;
3355 3967
3356// Console.WriteLine("Scheduled update for {0} in {1}", Name, Scene.Name); 3968 m_scene.ForEachScenePresence(SendTerseUpdateToAgent);
3357 m_scene.ForEachClient(SendTerseUpdateToClient); 3969 // Update the "last" values
3358 }
3359 TriggerScenePresenceUpdated(); 3970 TriggerScenePresenceUpdated();
3360 } 3971 }
3361 3972
@@ -3379,89 +3990,75 @@ namespace OpenSim.Region.Framework.Scenes
3379 ControllingClient.SendCoarseLocationUpdate(avatarUUIDs, coarseLocations); 3990 ControllingClient.SendCoarseLocationUpdate(avatarUUIDs, coarseLocations);
3380 } 3991 }
3381 3992
3382 public void SendInitialDataToClient() 3993 public void SendInitialDataToMe()
3383 { 3994 {
3384 SentInitialDataToClient = true;
3385
3386 // Send all scene object to the new client 3995 // Send all scene object to the new client
3387 WorkManager.RunJob("SendInitialDataToClient", delegate 3996 SentInitialData = true;
3997 Util.FireAndForget(delegate
3388 { 3998 {
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. 3999 // we created a new ScenePresence (a new child agent) in a fresh region.
3394 // Request info about all the (root) agents in this region 4000 // 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) 4001 // Note: This won't send data *to* other clients in that region (children don't send)
3396 SendOtherAgentsAvatarDataToClient(); 4002 if (m_teleportFlags <= 0)
3397 SendOtherAgentsAppearanceToClient(); 4003 {
4004 Scene.SendLayerData(ControllingClient);
3398 4005
4006 ILandChannel landch = m_scene.LandChannel;
4007 if (landch != null)
4008 {
4009 landch.sendClientInitialLandInfo(ControllingClient);
4010 }
4011 }
4012
4013 SendOtherAgentsAvatarFullToMe();
3399 EntityBase[] entities = Scene.Entities.GetEntities(); 4014 EntityBase[] entities = Scene.Entities.GetEntities();
3400 foreach (EntityBase e in entities) 4015 foreach (EntityBase e in entities)
3401 { 4016 {
3402 if (e != null && e is SceneObjectGroup) 4017 if (e != null && e is SceneObjectGroup && !((SceneObjectGroup)e).IsAttachment)
3403 ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient); 4018 ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient);
3404 } 4019 }
3405 }, null, string.Format("SendInitialDataToClient ({0} in {1})", Name, Scene.Name), false, true); 4020
4021 m_reprioritizationLastPosition = AbsolutePosition;
4022 m_reprioritizationLastDrawDistance = DrawDistance;
4023 m_reprioritizationLastTime = Util.EnvironmentTickCount() + 15000; // delay it
4024 m_reprioritizationBusy = false;
4025
4026 });
3406 } 4027 }
3407 4028
3408 /// <summary> 4029 /// <summary>
3409 /// Do everything required once a client completes its movement into a region and becomes 4030 /// Send avatar full data appearance and animations for all other root agents to this agent, this agent
3410 /// a root agent. 4031 /// can be either a child or root
3411 /// </summary> 4032 /// </summary>
3412 private void ValidateAndSendAppearanceAndAgentData() 4033 public void SendOtherAgentsAvatarFullToMe()
3413 { 4034 {
3414 //m_log.DebugFormat("[SCENE PRESENCE] SendInitialData: {0} ({1})", Name, UUID); 4035 int count = 0;
3415 // Moved this into CompleteMovement to ensure that Appearance is initialized before 4036 m_scene.ForEachRootScenePresence(delegate(ScenePresence p)
3416 // the inventory arrives
3417 // m_scene.GetAvatarAppearance(ControllingClient, out Appearance);
3418
3419 bool cachedappearance = false;
3420
3421 // We have an appearance but we may not have the baked textures. Check the asset cache
3422 // to see if all the baked textures are already here.
3423 if (m_scene.AvatarFactory != null)
3424 cachedappearance = m_scene.AvatarFactory.ValidateBakedTextureCache(this);
3425
3426 // If we aren't using a cached appearance, then clear out the baked textures
3427 if (!cachedappearance)
3428 { 4037 {
3429 Appearance.ResetAppearance(); 4038 // only send information about other root agents
3430 if (m_scene.AvatarFactory != null) 4039 if (p.UUID == UUID)
3431 m_scene.AvatarFactory.QueueAppearanceSave(UUID); 4040 return;
3432 }
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 4041
3440 // This invocation always shows up in the viewer logs as an error. Is it needed? 4042 // get the avatar, then a kill if can't see it
3441 SendAppearanceToClient(this); 4043 p.SendInitialAvatarDataToAgent(this);
3442 4044
3443 // If we are using the the cached appearance then send it out to everyone 4045 if (p.ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !IsViewerUIGod)
3444 if (cachedappearance) 4046 return;
3445 {
3446 m_log.DebugFormat("[SCENE PRESENCE]: Baked textures are in the cache for {0} in {1}", Name, m_scene.Name);
3447 4047
3448 // If the avatars baked textures are all in the cache, then we have a 4048 p.SendAppearanceToAgentNF(this);
3449 // complete appearance... send it out, if not, then we'll send it when 4049 p.SendAnimPackToAgentNF(this);
3450 // the avatar finishes updating its appearance 4050 p.SendAttachmentsToAgentNF(this);
3451 SendAppearanceToAllOtherClients(); 4051 count++;
3452 } 4052 });
3453 }
3454 4053
3455 public void SendAvatarDataToAllClients() 4054 m_scene.StatsReporter.AddAgentUpdates(count);
3456 {
3457 SendAvatarDataToAllClients(true);
3458 } 4055 }
3459 4056
3460 /// <summary> 4057 /// <summary>
3461 /// Send this agent's avatar data to all other root and child agents in the scene 4058 /// 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. 4059 /// This agent must be root. This avatar will receive its own update.
3463 /// </summary> 4060 /// </summary>
3464 public void SendAvatarDataToAllClients(bool full) 4061 public void SendAvatarDataToAllAgents()
3465 { 4062 {
3466 //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAllAgents: {0} ({1})", Name, UUID); 4063 //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" 4064 // only send update from root agents to other clients; children are only "listening posts"
@@ -3470,64 +4067,73 @@ namespace OpenSim.Region.Framework.Scenes
3470 m_log.WarnFormat( 4067 m_log.WarnFormat(
3471 "[SCENE PRESENCE]: Attempt to send avatar data from a child agent for {0} in {1}", 4068 "[SCENE PRESENCE]: Attempt to send avatar data from a child agent for {0} in {1}",
3472 Name, Scene.RegionInfo.RegionName); 4069 Name, Scene.RegionInfo.RegionName);
3473
3474 return; 4070 return;
3475 } 4071 }
3476 4072
3477 m_lastSize = Appearance.AvatarSize; 4073 m_lastSize = Appearance.AvatarSize;
3478
3479 int count = 0; 4074 int count = 0;
4075
3480 m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) 4076 m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence)
3481 { 4077 {
3482 if (full) 4078 SendAvatarDataToAgent(scenePresence);
3483 SendAvatarDataToClient(scenePresence);
3484 else
3485 scenePresence.ControllingClient.SendAvatarDataImmediate(this);
3486 count++; 4079 count++;
3487 }); 4080 });
3488 4081
3489 m_scene.StatsReporter.AddAgentUpdates(count); 4082 m_scene.StatsReporter.AddAgentUpdates(count);
3490 } 4083 }
3491 4084 // sends avatar object to all clients so they cross it into region
3492 /// <summary> 4085 // then sends kills to hide
3493 /// Send avatar data for all other root agents to this agent, this agent 4086 public void SendInitialAvatarDataToAllAgents(List<ScenePresence> presences)
3494 /// can be either a child or root
3495 /// </summary>
3496 public void SendOtherAgentsAvatarDataToClient()
3497 { 4087 {
4088 m_lastSize = Appearance.AvatarSize;
3498 int count = 0; 4089 int count = 0;
3499 m_scene.ForEachRootScenePresence(delegate(ScenePresence scenePresence) 4090 foreach (ScenePresence p in presences)
3500 { 4091 {
3501 // only send information about other root agents 4092 p.ControllingClient.SendEntityFullUpdateImmediate(this);
3502 if (scenePresence.UUID == UUID) 4093 if (p != this && ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod)
3503 return; 4094 // either just kill the object
3504 4095 // p.ControllingClient.SendKillObject(new List<uint> {LocalId});
3505 scenePresence.SendAvatarDataToClient(this); 4096 // or also attachments viewer may still know about
3506 count++; 4097 SendKillTo(p);
3507 }); 4098 count++;
3508 4099 }
3509 m_scene.StatsReporter.AddAgentUpdates(count); 4100 m_scene.StatsReporter.AddAgentUpdates(count);
3510 } 4101 }
3511 4102
4103 public void SendInitialAvatarDataToAgent(ScenePresence p)
4104 {
4105 p.ControllingClient.SendEntityFullUpdateImmediate(this);
4106 if (p != this && ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod)
4107 // either just kill the object
4108 // p.ControllingClient.SendKillObject(new List<uint> {LocalId});
4109 // or also attachments viewer may still know about
4110 SendKillTo(p);
4111 }
4112
3512 /// <summary> 4113 /// <summary>
3513 /// Send avatar data to an agent. 4114 /// Send avatar data to an agent.
3514 /// </summary> 4115 /// </summary>
3515 /// <param name="avatar"></param> 4116 /// <param name="avatar"></param>
3516 public void SendAvatarDataToClient(ScenePresence avatar) 4117 public void SendAvatarDataToAgent(ScenePresence avatar)
3517 { 4118 {
3518 //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToClient from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID); 4119 //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAgent from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID);
4120 if (ParcelHideThisAvatar && currentParcelUUID != avatar.currentParcelUUID && !avatar.IsViewerUIGod)
4121 return;
4122 avatar.ControllingClient.SendEntityFullUpdateImmediate(this);
4123 }
3519 4124
3520 avatar.ControllingClient.SendAvatarDataImmediate(this); 4125 public void SendAvatarDataToAgentNF(ScenePresence avatar)
3521 Animator.SendAnimPackToClient(avatar.ControllingClient); 4126 {
4127 avatar.ControllingClient.SendEntityFullUpdateImmediate(this);
3522 } 4128 }
3523 4129
3524 /// <summary> 4130 /// <summary>
3525 /// Send this agent's appearance to all other root and child agents in the scene 4131 /// Send this agent's appearance to all other root and child agents in the scene
3526 /// This agent must be root. 4132 /// This agent must be root.
3527 /// </summary> 4133 /// </summary>
3528 public void SendAppearanceToAllOtherClients() 4134 public void SendAppearanceToAllOtherAgents()
3529 { 4135 {
3530// m_log.DebugFormat("[SCENE PRESENCE] SendAppearanceToAllOtherClients: {0} {1}", Name, UUID); 4136 // m_log.DebugFormat("[SCENE PRESENCE] SendAppearanceToAllOtherAgents: {0} {1}", Name, UUID);
3531 4137
3532 // only send update from root agents to other clients; children are only "listening posts" 4138 // only send update from root agents to other clients; children are only "listening posts"
3533 if (IsChildAgent) 4139 if (IsChildAgent)
@@ -3538,109 +4144,217 @@ namespace OpenSim.Region.Framework.Scenes
3538 4144
3539 return; 4145 return;
3540 } 4146 }
3541 4147
3542 int count = 0; 4148 int count = 0;
3543 m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) 4149 m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence)
3544 { 4150 {
3545 // only send information to other root agents 4151 // only send information to other root agents
3546 if (scenePresence.UUID == UUID) 4152 if (scenePresence.UUID == UUID)
3547 return; 4153 return;
3548
3549 SendAppearanceToClient(scenePresence);
3550 count++;
3551 });
3552 4154
4155 SendAppearanceToAgent(scenePresence);
4156 count++;
4157 });
3553 m_scene.StatsReporter.AddAgentUpdates(count); 4158 m_scene.StatsReporter.AddAgentUpdates(count);
3554 } 4159 }
3555 4160
3556 /// <summary> 4161 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 { 4162 {
3562// m_log.DebugFormat("[SCENE PRESENCE] SendOtherAgentsAppearanceToClient {0} {1}", Name, UUID); 4163 // m_log.DebugFormat(
4164 // "[SCENE PRESENCE]: Sending appearance data from {0} {1} to {2} {3}", Name, m_uuid, avatar.Name, avatar.UUID);
4165 if (ParcelHideThisAvatar && currentParcelUUID != avatar.currentParcelUUID && !avatar.IsViewerUIGod)
4166 return;
4167 SendAppearanceToAgentNF(avatar);
4168 }
3563 4169
3564 int count = 0; 4170 public void SendAppearanceToAgentNF(ScenePresence avatar)
3565 m_scene.ForEachRootScenePresence(delegate(ScenePresence scenePresence) 4171 {
3566 { 4172 avatar.ControllingClient.SendAppearance(
3567 // only send information about other root agents 4173 UUID, Appearance.VisualParams, Appearance.Texture.GetBytes());
3568 if (scenePresence.UUID == UUID) 4174 }
3569 return;
3570
3571 scenePresence.SendAppearanceToClient(this);
3572 count++;
3573 });
3574 4175
3575 m_scene.StatsReporter.AddAgentUpdates(count); 4176 public void SendAnimPackToAgent(ScenePresence p)
4177 {
4178 if (IsChildAgent || Animator == null)
4179 return;
4180
4181 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod)
4182 return;
4183
4184 Animator.SendAnimPackToClient(p.ControllingClient);
3576 } 4185 }
3577 4186
3578 /// <summary> 4187 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 { 4188 {
3584// m_log.DebugFormat( 4189 if (IsChildAgent)
3585// "[SCENE PRESENCE]: Sending appearance data from {0} {1} to {2} {3}", Name, m_uuid, avatar.Name, avatar.UUID); 4190 return;
3586 4191
3587 avatar.ControllingClient.SendAppearance( 4192 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod)
3588 UUID, Appearance.VisualParams, Appearance.Texture.GetBytes()); 4193 return;
4194
4195 p.ControllingClient.SendAnimations(animations, seqs, ControllingClient.AgentId, objectIDs);
4196 }
4197
4198 public void SendAnimPackToAgentNF(ScenePresence p)
4199 {
4200 if (IsChildAgent || Animator == null)
4201 return;
4202 Animator.SendAnimPackToClient(p.ControllingClient);
4203 }
4204
4205 public void SendAnimPackToAgentNF(ScenePresence p, UUID[] animations, int[] seqs, UUID[] objectIDs)
4206 {
4207 p.ControllingClient.SendAnimations(animations, seqs, ControllingClient.AgentId, objectIDs);
4208 }
4209
4210 public void SendAnimPack(UUID[] animations, int[] seqs, UUID[] objectIDs)
4211 {
4212 if (IsChildAgent)
4213 return;
3589 4214
3590 4215 m_scene.ForEachScenePresence(delegate(ScenePresence p)
4216 {
4217 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod)
4218 return;
4219 p.ControllingClient.SendAnimations(animations, seqs, ControllingClient.AgentId, objectIDs);
4220 });
3591 } 4221 }
3592 4222
3593 #endregion 4223 #endregion
3594 4224
3595 #region Significant Movement Method 4225 #region Significant Movement Method
3596 4226
4227 private void checkRePrioritization()
4228 {
4229 if(IsDeleted || !ControllingClient.IsActive)
4230 return;
4231
4232 if(!SentInitialData)
4233 {
4234 SendInitialDataToMe();
4235 return;
4236 }
4237
4238 if(m_reprioritizationBusy)
4239 return;
4240
4241 float limit = Scene.ReprioritizationDistance;
4242 bool byDrawdistance = Scene.ObjectsCullingByDistance;
4243 if(byDrawdistance)
4244 {
4245 float minregionSize = (float)Scene.RegionInfo.RegionSizeX;
4246 if(minregionSize > (float)Scene.RegionInfo.RegionSizeY)
4247 minregionSize = (float)Scene.RegionInfo.RegionSizeY;
4248 minregionSize *= 0.5f;
4249 if(DrawDistance > minregionSize && m_reprioritizationLastDrawDistance > minregionSize)
4250 byDrawdistance = false;
4251 else
4252 byDrawdistance = (Math.Abs(DrawDistance - m_reprioritizationLastDrawDistance) > 0.5f * limit);
4253 }
4254
4255 int tdiff = Util.EnvironmentTickCountSubtract(m_reprioritizationLastTime);
4256 if(!byDrawdistance && tdiff < Scene.ReprioritizationInterval)
4257 return;
4258 // priority uses avatar position
4259 Vector3 pos = AbsolutePosition;
4260 Vector3 diff = pos - m_reprioritizationLastPosition;
4261 limit *= limit;
4262 if (!byDrawdistance && diff.LengthSquared() < limit)
4263 return;
4264
4265 m_reprioritizationBusy = true;
4266 m_reprioritizationLastPosition = pos;
4267 m_reprioritizationLastDrawDistance = DrawDistance;
4268
4269 Util.FireAndForget(
4270 o =>
4271 {
4272 ControllingClient.ReprioritizeUpdates();
4273 m_reprioritizationLastTime = Util.EnvironmentTickCount();
4274 m_reprioritizationBusy = false;
4275 }, null, "ScenePresence.Reprioritization");
4276 }
3597 /// <summary> 4277 /// <summary>
3598 /// This checks for a significant movement and sends a coarselocationchange update 4278 /// This checks for a significant movement and sends a coarselocationchange update
3599 /// </summary> 4279 /// </summary>
3600 protected void CheckForSignificantMovement() 4280 protected void CheckForSignificantMovement()
3601 { 4281 {
3602 if (Util.GetDistanceTo(AbsolutePosition, posLastSignificantMove) > SIGNIFICANT_MOVEMENT) 4282 Vector3 pos = AbsolutePosition;
4283
4284 Vector3 diff = pos - posLastMove;
4285 if (diff.LengthSquared() > MOVEMENT)
3603 { 4286 {
3604 posLastSignificantMove = AbsolutePosition; 4287 posLastMove = pos;
3605 m_scene.EventManager.TriggerSignificantClientMovement(this); 4288 m_scene.EventManager.TriggerOnClientMovement(this);
3606 } 4289 }
3607 4290
3608 // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m 4291 diff = pos - posLastSignificantMove;
3609 if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance) 4292 if (diff.LengthSquared() > SIGNIFICANT_MOVEMENT)
3610 { 4293 {
3611 m_lastChildAgentUpdatePosition = AbsolutePosition; 4294 posLastSignificantMove = pos;
3612// m_lastChildAgentUpdateCamPosition = CameraPosition; 4295 m_scene.EventManager.TriggerSignificantClientMovement(this);
4296 }
3613 4297
3614 ChildAgentDataUpdate cadu = new ChildAgentDataUpdate(); 4298 // updates priority recalc
3615 cadu.ActiveGroupID = UUID.Zero.Guid; 4299 checkRePrioritization();
3616 cadu.AgentID = UUID.Guid;
3617 cadu.alwaysrun = SetAlwaysRun;
3618 cadu.AVHeight = Appearance.AvatarHeight;
3619 cadu.cameraPosition = CameraPosition;
3620 cadu.drawdistance = DrawDistance;
3621 cadu.GroupAccess = 0;
3622 cadu.Position = AbsolutePosition;
3623 cadu.regionHandle = RegionHandle;
3624 4300
3625 // Throttles 4301 if(m_childUpdatesBusy)
3626 float multiplier = 1; 4302 return;
3627 int childRegions = KnownRegionCount;
3628 if (childRegions != 0)
3629 multiplier = 1f / childRegions;
3630 4303
3631 // Minimum throttle for a child region is 1/4 of the root region throttle 4304 //possible KnownRegionHandles always contains current region and this check is not needed
3632 if (multiplier <= 0.25f) 4305 int minhandles = 0;
3633 multiplier = 0.25f; 4306 if(KnownRegionHandles.Contains(RegionHandle))
4307 minhandles++;
3634 4308
3635 cadu.throttles = ControllingClient.GetThrottlesPacked(multiplier); 4309 if(KnownRegionHandles.Count > minhandles)
3636 cadu.Velocity = Velocity; 4310 {
4311 int tdiff = Util.EnvironmentTickCountSubtract(m_lastChildUpdatesTime);
4312 if(tdiff < CHILDUPDATES_TIME)
4313 return;
3637 4314
3638 AgentPosition agentpos = new AgentPosition(); 4315 bool doUpdate = false;
3639 agentpos.CopyFrom(cadu, ControllingClient.SessionId); 4316 if(m_lastChildAgentUpdateGodLevel != GodController.ViwerUIGodLevel)
4317 doUpdate = true;
4318
4319 if(!doUpdate && Math.Abs(DrawDistance - m_lastChildAgentUpdateDrawDistance) > 32.0f)
4320 doUpdate = true;
4321
4322 if(!doUpdate)
4323 {
4324 diff = pos - m_lastChildAgentUpdatePosition;
4325 if (diff.LengthSquared() > CHILDUPDATES_MOVEMENT)
4326 doUpdate = true;
4327 }
3640 4328
3641 // Let's get this out of the update loop 4329 if(doUpdate)
3642 Util.FireAndForget( 4330 {
3643 o => m_scene.SendOutChildAgentUpdates(agentpos, this), null, "ScenePresence.SendOutChildAgentUpdates"); 4331 m_childUpdatesBusy = true;
4332 m_lastChildAgentUpdatePosition = pos;
4333 m_lastChildAgentUpdateGodLevel = GodController.ViwerUIGodLevel;
4334 m_lastChildAgentUpdateDrawDistance = DrawDistance;
4335// m_lastChildAgentUpdateCamPosition = CameraPosition;
4336
4337 AgentPosition agentpos = new AgentPosition();
4338 agentpos.AgentID = new UUID(UUID.Guid);
4339 agentpos.SessionID = ControllingClient.SessionId;
4340 agentpos.Size = Appearance.AvatarSize;
4341 agentpos.Center = CameraPosition;
4342 agentpos.Far = DrawDistance;
4343 agentpos.Position = AbsolutePosition;
4344 agentpos.Velocity = Velocity;
4345 agentpos.RegionHandle = RegionHandle;
4346 agentpos.GodData = GodController.State();
4347 agentpos.Throttles = ControllingClient.GetThrottlesPacked(1);
4348
4349 // Let's get this out of the update loop
4350 Util.FireAndForget(
4351 o =>
4352 {
4353 m_scene.SendOutChildAgentUpdates(agentpos, this);
4354 m_lastChildUpdatesTime = Util.EnvironmentTickCount();
4355 m_childUpdatesBusy = false;
4356 }, null, "ScenePresence.SendOutChildAgentUpdates");
4357 }
3644 } 4358 }
3645 } 4359 }
3646 4360
@@ -3657,7 +4371,7 @@ namespace OpenSim.Region.Framework.Scenes
3657 protected void CheckForBorderCrossing() 4371 protected void CheckForBorderCrossing()
3658 { 4372 {
3659 // Check that we we are not a child 4373 // Check that we we are not a child
3660 if (IsChildAgent) 4374 if (IsChildAgent || IsInTransit)
3661 return; 4375 return;
3662 4376
3663 // If we don't have a PhysActor, we can't cross anyway 4377 // If we don't have a PhysActor, we can't cross anyway
@@ -3667,79 +4381,71 @@ namespace OpenSim.Region.Framework.Scenes
3667 if (ParentID != 0 || PhysicsActor == null || ParentUUID != UUID.Zero) 4381 if (ParentID != 0 || PhysicsActor == null || ParentUUID != UUID.Zero)
3668 return; 4382 return;
3669 4383
3670 if (IsInTransit)
3671 return;
3672
3673 Vector3 pos2 = AbsolutePosition; 4384 Vector3 pos2 = AbsolutePosition;
3674 Vector3 origPosition = pos2;
3675 Vector3 vel = Velocity; 4385 Vector3 vel = Velocity;
3676 4386
3677 // Compute the future avatar position. 4387 float timeStep = 0.1f;
3678 // If the avatar will be crossing, we force the crossing to happen now 4388 pos2.X += vel.X * timeStep;
3679 // in the hope that this will make the avatar movement smoother when crossing. 4389 pos2.Y += vel.Y * timeStep;
3680 pos2 += vel * 0.05f; 4390 pos2.Z += vel.Z * timeStep;
3681
3682 if (m_scene.PositionIsInCurrentRegion(pos2))
3683 return;
3684
3685 m_log.DebugFormat("{0} CheckForBorderCrossing: position outside region. {1} in {2} at pos {3}",
3686 LogHeader, Name, Scene.Name, pos2);
3687 4391
3688 // Disconnect from the current region 4392// m_log.DebugFormat(
3689 bool isFlying = Flying; 4393// "[SCENE PRESENCE]: Testing border check for projected position {0} of {1} in {2}",
3690 RemoveFromPhysicalScene(); 4394// pos2, Name, Scene.Name);
3691 4395
3692 // pos2 is the forcasted position so make that the 'current' position so the crossing 4396 if (Scene.PositionIsInCurrentRegion(pos2))
3693 // code will move us into the newly addressed region. 4397 return;
3694 m_pos = pos2;
3695 4398
3696 if (CrossToNewRegion()) 4399 if (!CrossToNewRegion() && m_requestedSitTargetUUID == UUID.Zero)
3697 {
3698 AddToPhysicalScene(isFlying);
3699 }
3700 else
3701 { 4400 {
3702 // Tried to make crossing happen but it failed. 4401 // we don't have entity transfer module
3703 if (m_requestedSitTargetUUID == UUID.Zero) 4402 Vector3 pos = AbsolutePosition;
3704 { 4403 vel = Velocity;
3705 m_log.DebugFormat("{0} CheckForBorderCrossing: Crossing failed. Restoring old position.", LogHeader); 4404 float px = pos.X;
3706 4405 if (px < 0)
3707 Velocity = Vector3.Zero; 4406 pos.X += vel.X * 2;
3708 AbsolutePosition = EnforceSanityOnPosition(origPosition); 4407 else if (px > m_scene.RegionInfo.RegionSizeX)
4408 pos.X -= vel.X * 2;
4409
4410 float py = pos.Y;
4411 if (py < 0)
4412 pos.Y += vel.Y * 2;
4413 else if (py > m_scene.RegionInfo.RegionSizeY)
4414 pos.Y -= vel.Y * 2;
3709 4415
3710 AddToPhysicalScene(isFlying); 4416 Velocity = Vector3.Zero;
3711 } 4417 m_AngularVelocity = Vector3.Zero;
4418 AbsolutePosition = pos;
3712 } 4419 }
3713 } 4420 }
3714 4421
3715 // Given a position, make sure it is within the current region. 4422 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 { 4423 {
3719 const float borderFudge = 0.1f; 4424 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 { 4425 {
3728 // If a mega-region, the size could be much bigger 4426 bool isFlying = Flying;
3729 Vector2 megaExtent = combiner.GetSizeOfMegaregion(m_scene.RegionInfo.RegionID); 4427 RemoveFromPhysicalScene();
3730 extentX = megaExtent.X; 4428
3731 extentY = megaExtent.Y; 4429 Vector3 pos = AbsolutePosition;
3732 } 4430 Vector3 vel = Velocity;
3733 if (ret.X < 0) 4431 float px = pos.X;
3734 ret.X = borderFudge; 4432 if (px < 0)
3735 else if (ret.X >= extentX) 4433 pos.X += vel.X * 2;
3736 ret.X = extentX - borderFudge; 4434 else if (px > m_scene.RegionInfo.RegionSizeX)
3737 if (ret.Y < 0) 4435 pos.X -= vel.X * 2;
3738 ret.Y = borderFudge; 4436
3739 else if (ret.Y >= extentY) 4437 float py = pos.Y;
3740 ret.Y = extentY - borderFudge; 4438 if (py < 0)
4439 pos.Y += vel.Y * 2;
4440 else if (py > m_scene.RegionInfo.RegionSizeY)
4441 pos.Y -= vel.Y * 2;
4442
4443 Velocity = Vector3.Zero;
4444 m_AngularVelocity = Vector3.Zero;
4445 AbsolutePosition = pos;
3741 4446
3742 return ret; 4447 AddToPhysicalScene(isFlying);
4448 }
3743 } 4449 }
3744 4450
3745 /// <summary> 4451 /// <summary>
@@ -3750,62 +4456,93 @@ namespace OpenSim.Region.Framework.Scenes
3750 /// </summary> 4456 /// </summary>
3751 protected bool CrossToNewRegion() 4457 protected bool CrossToNewRegion()
3752 { 4458 {
4459 bool result = false;
4460// parcelRegionCross(false);
3753 try 4461 try
3754 { 4462 {
3755 return m_scene.CrossAgentToNewRegion(this, Flying); 4463 result = m_scene.CrossAgentToNewRegion(this, Flying);
3756 } 4464 }
3757 catch 4465 catch
3758 { 4466 {
3759 return m_scene.CrossAgentToNewRegion(this, false); 4467// result = m_scene.CrossAgentToNewRegion(this, false);
4468 return false;
3760 } 4469 }
3761 } 4470 // if(!result)
4471 // parcelRegionCross(true);
3762 4472
3763 public void Reset() 4473 return result;
3764 {
3765// m_log.DebugFormat("[SCENE PRESENCE]: Resetting {0} in {1}", Name, Scene.RegionInfo.RegionName);
3766
3767 // Put the child agent back at the center
3768 AbsolutePosition
3769 = new Vector3(((float)m_scene.RegionInfo.RegionSizeX * 0.5f), ((float)m_scene.RegionInfo.RegionSizeY * 0.5f), 70);
3770 4474
3771 Animator.ResetAnimations();
3772 } 4475 }
3773 4476
3774 /// <summary> 4477 /// <summary>
3775 /// Computes which child agents to close when the scene presence moves to another region. 4478 /// Computes which child agents to close when the scene presence moves to another region.
3776 /// Removes those regions from m_knownRegions. 4479 /// Removes those regions from m_knownRegions.
3777 /// </summary> 4480 /// </summary>
3778 /// <param name="newRegionX">The new region's x on the map</param> 4481 /// <param name="newRegionHandle">The new region's handle</param>
3779 /// <param name="newRegionY">The new region's y on the map</param> 4482 /// <param name="newRegionSizeX">The new region's size x</param>
4483 /// <param name="newRegionSizeY">The new region's size y</param>
3780 /// <returns></returns> 4484 /// <returns></returns>
3781 public void CloseChildAgents(uint newRegionX, uint newRegionY) 4485 public List<ulong> GetChildAgentsToClose(ulong newRegionHandle, int newRegionSizeX, int newRegionSizeY)
3782 { 4486 {
4487 ulong curRegionHandle = m_scene.RegionInfo.RegionHandle;
3783 List<ulong> byebyeRegions = new List<ulong>(); 4488 List<ulong> byebyeRegions = new List<ulong>();
4489
4490 if(newRegionHandle == curRegionHandle) //??
4491 return byebyeRegions;
4492
4493 uint newRegionX, newRegionY;
3784 List<ulong> knownRegions = KnownRegionHandles; 4494 List<ulong> knownRegions = KnownRegionHandles;
3785 m_log.DebugFormat( 4495 m_log.DebugFormat(
3786 "[SCENE PRESENCE]: Closing child agents. Checking {0} regions in {1}", 4496 "[SCENE PRESENCE]: Closing child agents. Checking {0} regions in {1}",
3787 knownRegions.Count, Scene.RegionInfo.RegionName); 4497 knownRegions.Count, Scene.RegionInfo.RegionName);
3788 //DumpKnownRegions(); 4498
4499 Util.RegionHandleToRegionLoc(newRegionHandle, out newRegionX, out newRegionY);
4500 uint x, y;
4501 spRegionSizeInfo regInfo;
3789 4502
3790 foreach (ulong handle in knownRegions) 4503 foreach (ulong handle in knownRegions)
3791 { 4504 {
3792 // Don't close the agent on this region yet 4505 if(newRegionY == 0) // HG
3793 if (handle != Scene.RegionInfo.RegionHandle) 4506 byebyeRegions.Add(handle);
4507 else if(handle == curRegionHandle)
3794 { 4508 {
3795 uint x, y; 4509 RegionInfo curreg = m_scene.RegionInfo;
3796 Util.RegionHandleToRegionLoc(handle, out x, out y); 4510 if (Util.IsOutsideView(255, curreg.RegionLocX, newRegionX, curreg.RegionLocY, newRegionY,
3797 4511 (int)curreg.RegionSizeX, (int)curreg.RegionSizeX, newRegionSizeX, newRegionSizeY))
3798// 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)));
3800 float dist = (float)Math.Max(Scene.DefaultDrawDistance,
3801 (float)Math.Max(Scene.RegionInfo.RegionSizeX, Scene.RegionInfo.RegionSizeY));
3802 if (Util.IsOutsideView(dist, x, newRegionX, y, newRegionY))
3803 { 4512 {
3804 byebyeRegions.Add(handle); 4513 byebyeRegions.Add(handle);
3805 } 4514 }
3806 } 4515 }
4516 else
4517 {
4518 Util.RegionHandleToRegionLoc(handle, out x, out y);
4519 if (m_knownChildRegionsSizeInfo.TryGetValue(handle, out regInfo))
4520 {
4521// if (Util.IsOutsideView(RegionViewDistance, x, newRegionX, y, newRegionY,
4522 // for now need to close all but first order bc RegionViewDistance it the target value not ours
4523 if (Util.IsOutsideView(255, x, newRegionX, y, newRegionY,
4524 regInfo.sizeX, regInfo.sizeY, newRegionSizeX, newRegionSizeY))
4525 {
4526 byebyeRegions.Add(handle);
4527 }
4528 }
4529 else
4530 {
4531// if (Util.IsOutsideView(RegionViewDistance, x, newRegionX, y, newRegionY,
4532 if (Util.IsOutsideView(255, x, newRegionX, y, newRegionY,
4533 (int)Constants.RegionSize, (int)Constants.RegionSize, newRegionSizeX, newRegionSizeY))
4534 {
4535 byebyeRegions.Add(handle);
4536 }
4537 }
4538 }
3807 } 4539 }
3808 4540 return byebyeRegions;
4541 }
4542
4543 public void CloseChildAgents(List<ulong> byebyeRegions)
4544 {
4545 byebyeRegions.Remove(Scene.RegionInfo.RegionHandle);
3809 if (byebyeRegions.Count > 0) 4546 if (byebyeRegions.Count > 0)
3810 { 4547 {
3811 m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents"); 4548 m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents");
@@ -3814,43 +4551,56 @@ namespace OpenSim.Region.Framework.Scenes
3814 string auth = string.Empty; 4551 string auth = string.Empty;
3815 if (acd != null) 4552 if (acd != null)
3816 auth = acd.SessionID.ToString(); 4553 auth = acd.SessionID.ToString();
3817 m_scene.SceneGridService.SendCloseChildAgentConnections(ControllingClient.AgentId, auth, byebyeRegions); 4554 m_scene.SceneGridService.SendCloseChildAgentConnections(ControllingClient.AgentId, auth, byebyeRegions);
3818 } 4555 }
3819 4556
3820 foreach (ulong handle in byebyeRegions) 4557 foreach (ulong handle in byebyeRegions)
3821 { 4558 {
3822 RemoveNeighbourRegion(handle); 4559 RemoveNeighbourRegion(handle);
4560 Scene.CapsModule.DropChildSeed(UUID, handle);
3823 } 4561 }
3824 } 4562 }
3825 4563
3826 #endregion 4564 public void closeAllChildAgents()
3827
3828 /// <summary>
3829 /// This allows the Sim owner the abiility to kick users from their sim currently.
3830 /// It tells the client that the agent has permission to do so.
3831 /// </summary>
3832 public void GrantGodlikePowers(UUID agentID, UUID sessionID, UUID token, bool godStatus)
3833 { 4565 {
3834 if (godStatus) 4566 List<ulong> byebyeRegions = new List<ulong>();
4567 List<ulong> knownRegions = KnownRegionHandles;
4568 foreach (ulong handle in knownRegions)
3835 { 4569 {
3836 // For now, assign god level 200 to anyone 4570 if (handle != Scene.RegionInfo.RegionHandle)
3837 // who is granted god powers, but has no god level set.
3838 //
3839 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, agentID);
3840 if (account != null)
3841 { 4571 {
3842 if (account.UserLevel > 0) 4572 byebyeRegions.Add(handle);
3843 GodLevel = account.UserLevel; 4573 RemoveNeighbourRegion(handle);
3844 else 4574 Scene.CapsModule.DropChildSeed(UUID, handle);
3845 GodLevel = 200;
3846 } 4575 }
3847 } 4576 }
3848 else 4577
4578 if (byebyeRegions.Count > 0)
3849 { 4579 {
3850 GodLevel = 0; 4580 m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents");
4581
4582 AgentCircuitData acd = Scene.AuthenticateHandler.GetAgentCircuitData(UUID);
4583 string auth = string.Empty;
4584 if (acd != null)
4585 auth = acd.SessionID.ToString();
4586 m_scene.SceneGridService.SendCloseChildAgentConnections(ControllingClient.AgentId, auth, byebyeRegions);
3851 } 4587 }
4588 }
4589
4590 #endregion
3852 4591
3853 ControllingClient.SendAdminResponse(token, (uint)GodLevel); 4592 /// <summary>
4593 /// handle god level requests.
4594 /// </summary>
4595 public void GrantGodlikePowers(UUID token, bool godStatus)
4596 {
4597 if (IsNPC)
4598 return;
4599
4600 bool wasgod = IsViewerUIGod;
4601 GodController.RequestGodMode(godStatus);
4602 if (wasgod != IsViewerUIGod)
4603 parcelGodCheck(m_currentParcelUUID);
3854 } 4604 }
3855 4605
3856 #region Child Agent Updates 4606 #region Child Agent Updates
@@ -3862,12 +4612,16 @@ namespace OpenSim.Region.Framework.Scenes
3862 return; 4612 return;
3863 4613
3864 CopyFrom(cAgentData); 4614 CopyFrom(cAgentData);
3865
3866 m_updateAgentReceivedAfterTransferEvent.Set(); 4615 m_updateAgentReceivedAfterTransferEvent.Set();
3867 } 4616 }
3868 4617
3869 private static Vector3 marker = new Vector3(-1f, -1f, -1f); 4618 private static Vector3 marker = new Vector3(-1f, -1f, -1f);
3870 4619
4620 private void RaiseUpdateThrottles()
4621 {
4622 m_scene.EventManager.TriggerThrottleUpdate(this);
4623 }
4624
3871 /// <summary> 4625 /// <summary>
3872 /// This updates important decision making data about a child agent 4626 /// 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 4627 /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region
@@ -3877,44 +4631,59 @@ namespace OpenSim.Region.Framework.Scenes
3877 if (!IsChildAgent) 4631 if (!IsChildAgent)
3878 return; 4632 return;
3879 4633
3880// m_log.DebugFormat( 4634 GodController.SetState(cAgentData.GodData);
3881// "[SCENE PRESENCE]: ChildAgentPositionUpdate for {0} in {1}, tRegion {2},{3}, rRegion {4},{5}, pos {6}", 4635
3882// Name, Scene.Name, tRegionX, tRegionY, rRegionX, rRegionY, cAgentData.Position); 4636 RegionHandle = cAgentData.RegionHandle;
3883 4637
3884 // Find the distance (in meters) between the two regions 4638 //m_log.Debug(" >>> ChildAgentPositionUpdate <<< " + rRegionX + "-" + rRegionY);
3885 // XXX: We cannot use Util.RegionLocToHandle() here because a negative value will silently overflow the 4639 int shiftx = ((int)rRegionX - (int)tRegionX) * (int)Constants.RegionSize;
3886 // uint 4640 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 4641
3890 Vector3 offset = new Vector3(shiftx, shifty, 0f); 4642 Vector3 offset = new Vector3(shiftx, shifty, 0f);
3891 4643
3892 // When we get to the point of re-computing neighbors everytime this
3893 // changes, then start using the agent's drawdistance rather than the
3894 // region's draw distance.
3895 DrawDistance = cAgentData.Far; 4644 DrawDistance = cAgentData.Far;
3896 // DrawDistance = Scene.DefaultDrawDistance;
3897 4645
3898 if (cAgentData.Position != marker) // UGH!! 4646 if (cAgentData.Position != marker) // UGH!!
3899 m_pos = cAgentData.Position + offset; 4647 m_pos = cAgentData.Position + offset;
3900 4648
3901 if (Vector3.Distance(AbsolutePosition, posLastSignificantMove) >= Scene.ChildReprioritizationDistance) 4649 CameraPosition = cAgentData.Center + offset;
4650
4651 if ((cAgentData.Throttles != null) && cAgentData.Throttles.Length > 0)
3902 { 4652 {
3903 posLastSignificantMove = AbsolutePosition; 4653 // some scaling factor
3904 ReprioritizeUpdates(); 4654 float x = m_pos.X;
4655 if (x > m_scene.RegionInfo.RegionSizeX)
4656 x -= m_scene.RegionInfo.RegionSizeX;
4657 float y = m_pos.Y;
4658 if (y > m_scene.RegionInfo.RegionSizeY)
4659 y -= m_scene.RegionInfo.RegionSizeY;
4660
4661 x = x * x + y * y;
4662
4663 const float distScale = 0.4f / Constants.RegionSize / Constants.RegionSize;
4664 float factor = 1.0f - distScale * x;
4665 if (factor < 0.2f)
4666 factor = 0.2f;
4667
4668 ControllingClient.SetChildAgentThrottle(cAgentData.Throttles,factor);
3905 } 4669 }
3906 4670
3907 CameraPosition = cAgentData.Center + offset; 4671 if(cAgentData.ChildrenCapSeeds != null && cAgentData.ChildrenCapSeeds.Count >0)
4672 {
4673 if (Scene.CapsModule != null)
4674 {
4675 Scene.CapsModule.SetChildrenSeed(UUID, cAgentData.ChildrenCapSeeds);
4676 }
3908 4677
3909 if ((cAgentData.Throttles != null) && cAgentData.Throttles.Length > 0) 4678 KnownRegions = cAgentData.ChildrenCapSeeds;
3910 ControllingClient.SetChildAgentThrottle(cAgentData.Throttles); 4679 }
3911 4680
3912 //cAgentData.AVHeight; 4681 //cAgentData.AVHeight;
3913 RegionHandle = cAgentData.RegionHandle;
3914 //m_velocity = cAgentData.Velocity; 4682 //m_velocity = cAgentData.Velocity;
4683 checkRePrioritization();
3915 } 4684 }
3916 4685
3917 public void CopyTo(AgentData cAgent) 4686 public void CopyTo(AgentData cAgent, bool isCrossUpdate)
3918 { 4687 {
3919 cAgent.CallbackURI = m_callbackURI; 4688 cAgent.CallbackURI = m_callbackURI;
3920 4689
@@ -3930,35 +4699,23 @@ namespace OpenSim.Region.Framework.Scenes
3930 cAgent.UpAxis = CameraUpAxis; 4699 cAgent.UpAxis = CameraUpAxis;
3931 4700
3932 cAgent.Far = DrawDistance; 4701 cAgent.Far = DrawDistance;
4702 cAgent.GodData = GodController.State();
3933 4703
3934 // Throttles 4704 // Throttles
3935 float multiplier = 1; 4705 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 4706
3946 cAgent.HeadRotation = m_headrotation; 4707 cAgent.HeadRotation = m_headrotation;
3947 cAgent.BodyRotation = Rotation; 4708 cAgent.BodyRotation = Rotation;
3948 cAgent.ControlFlags = (uint)m_AgentControlFlags; 4709 cAgent.ControlFlags = (uint)m_AgentControlFlags;
3949 4710
3950 if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID)))
3951 cAgent.GodLevel = (byte)GodLevel;
3952 else
3953 cAgent.GodLevel = (byte) 0;
3954
3955 cAgent.AlwaysRun = SetAlwaysRun; 4711 cAgent.AlwaysRun = SetAlwaysRun;
3956 4712
3957 cAgent.Appearance = new AvatarAppearance(Appearance); 4713 // make clear we want the all thing
4714 cAgent.Appearance = new AvatarAppearance(Appearance,true,true);
3958 4715
3959 cAgent.ParentPart = ParentUUID; 4716 cAgent.ParentPart = ParentUUID;
3960 cAgent.SitOffset = PrevSitOffset; 4717 cAgent.SitOffset = PrevSitOffset;
3961 4718
3962 lock (scriptedcontrols) 4719 lock (scriptedcontrols)
3963 { 4720 {
3964 ControllerData[] controls = new ControllerData[scriptedcontrols.Count]; 4721 ControllerData[] controls = new ControllerData[scriptedcontrols.Count];
@@ -3980,8 +4737,36 @@ namespace OpenSim.Region.Framework.Scenes
3980 cAgent.DefaultAnim = Animator.Animations.DefaultAnimation; 4737 cAgent.DefaultAnim = Animator.Animations.DefaultAnimation;
3981 cAgent.AnimState = Animator.Animations.ImplicitDefaultAnimation; 4738 cAgent.AnimState = Animator.Animations.ImplicitDefaultAnimation;
3982 4739
4740 cAgent.MovementAnimationOverRides = Overrides.CloneAOPairs();
4741
4742 cAgent.MotionState = (byte)Animator.currentControlState;
4743
3983 if (Scene.AttachmentsModule != null) 4744 if (Scene.AttachmentsModule != null)
3984 Scene.AttachmentsModule.CopyAttachments(this, cAgent); 4745 Scene.AttachmentsModule.CopyAttachments(this, cAgent);
4746
4747 if(isCrossUpdate)
4748 {
4749 cAgent.CrossingFlags = crossingFlags;
4750 cAgent.CrossingFlags |= 1;
4751 cAgent.CrossExtraFlags = 0;
4752 if((LastCommands & ScriptControlled.CONTROL_LBUTTON) != 0)
4753 cAgent.CrossExtraFlags |= 1;
4754 if((LastCommands & ScriptControlled.CONTROL_ML_LBUTTON) != 0)
4755 cAgent.CrossExtraFlags |= 2;
4756 }
4757 else
4758 cAgent.CrossingFlags = 0;
4759
4760 if(isCrossUpdate)
4761 {
4762 cAgent.agentCOF = COF;
4763 cAgent.ActiveGroupID = ControllingClient.ActiveGroupId;
4764 cAgent.ActiveGroupName = ControllingClient.ActiveGroupName;
4765 if(Grouptitle == null)
4766 cAgent.ActiveGroupTitle = String.Empty;
4767 else
4768 cAgent.ActiveGroupTitle = Grouptitle;
4769 }
3985 } 4770 }
3986 4771
3987 private void CopyFrom(AgentData cAgent) 4772 private void CopyFrom(AgentData cAgent)
@@ -3991,40 +4776,59 @@ namespace OpenSim.Region.Framework.Scenes
3991// "[SCENE PRESENCE]: Set callback for {0} in {1} to {2} in CopyFrom()", 4776// "[SCENE PRESENCE]: Set callback for {0} in {1} to {2} in CopyFrom()",
3992// Name, m_scene.RegionInfo.RegionName, m_callbackURI); 4777// Name, m_scene.RegionInfo.RegionName, m_callbackURI);
3993 4778
4779 GodController.SetState(cAgent.GodData);
4780
3994 m_pos = cAgent.Position; 4781 m_pos = cAgent.Position;
3995 m_velocity = cAgent.Velocity; 4782 m_velocity = cAgent.Velocity;
3996 CameraPosition = cAgent.Center; 4783 CameraPosition = cAgent.Center;
3997 CameraAtAxis = cAgent.AtAxis; 4784 CameraAtAxis = cAgent.AtAxis;
3998 CameraLeftAxis = cAgent.LeftAxis; 4785 CameraLeftAxis = cAgent.LeftAxis;
3999 CameraUpAxis = cAgent.UpAxis; 4786 CameraUpAxis = cAgent.UpAxis;
4787
4788 Quaternion camRot = Util.Axes2Rot(CameraAtAxis, CameraLeftAxis, CameraUpAxis);
4789 CameraRotation = camRot;
4790
4000 ParentUUID = cAgent.ParentPart; 4791 ParentUUID = cAgent.ParentPart;
4001 PrevSitOffset = cAgent.SitOffset; 4792 PrevSitOffset = cAgent.SitOffset;
4002 4793
4003 // When we get to the point of re-computing neighbors everytime this 4794 // When we get to the point of re-computing neighbors everytime this
4004 // changes, then start using the agent's drawdistance rather than the 4795 // changes, then start using the agent's drawdistance rather than the
4005 // region's draw distance. 4796 // region's draw distance.
4006 DrawDistance = cAgent.Far; 4797 DrawDistance = cAgent.Far;
4007 // DrawDistance = Scene.DefaultDrawDistance; 4798 //DrawDistance = Scene.DefaultDrawDistance;
4799
4800 if (cAgent.ChildrenCapSeeds != null && cAgent.ChildrenCapSeeds.Count > 0)
4801 {
4802 if (Scene.CapsModule != null)
4803 {
4804 Scene.CapsModule.SetChildrenSeed(UUID, cAgent.ChildrenCapSeeds);
4805 }
4806 KnownRegions = cAgent.ChildrenCapSeeds;
4807 }
4008 4808
4009 if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0) 4809 if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0)
4010 ControllingClient.SetChildAgentThrottle(cAgent.Throttles); 4810 ControllingClient.SetChildAgentThrottle(cAgent.Throttles);
4011 4811
4012 m_headrotation = cAgent.HeadRotation; 4812 m_headrotation = cAgent.HeadRotation;
4013 Rotation = cAgent.BodyRotation; 4813 Rotation = cAgent.BodyRotation;
4014 m_AgentControlFlags = (AgentManager.ControlFlags)cAgent.ControlFlags; 4814 m_AgentControlFlags = (AgentManager.ControlFlags)cAgent.ControlFlags;
4015 4815
4016 if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID)))
4017 GodLevel = cAgent.GodLevel;
4018 SetAlwaysRun = cAgent.AlwaysRun; 4816 SetAlwaysRun = cAgent.AlwaysRun;
4019 4817
4020 Appearance = new AvatarAppearance(cAgent.Appearance); 4818 Appearance = new AvatarAppearance(cAgent.Appearance);
4819/*
4820 bool isFlying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
4821
4021 if (PhysicsActor != null) 4822 if (PhysicsActor != null)
4022 { 4823 {
4023 bool isFlying = Flying;
4024 RemoveFromPhysicalScene(); 4824 RemoveFromPhysicalScene();
4025 AddToPhysicalScene(isFlying); 4825 AddToPhysicalScene(isFlying);
4026 } 4826 }
4027 4827*/
4828
4829 if (Scene.AttachmentsModule != null)
4830 Scene.AttachmentsModule.CopyAttachments(cAgent, this);
4831
4028 try 4832 try
4029 { 4833 {
4030 lock (scriptedcontrols) 4834 lock (scriptedcontrols)
@@ -4032,6 +4836,7 @@ namespace OpenSim.Region.Framework.Scenes
4032 if (cAgent.Controllers != null) 4836 if (cAgent.Controllers != null)
4033 { 4837 {
4034 scriptedcontrols.Clear(); 4838 scriptedcontrols.Clear();
4839 IgnoredControls = ScriptControlled.CONTROL_ZERO;
4035 4840
4036 foreach (ControllerData c in cAgent.Controllers) 4841 foreach (ControllerData c in cAgent.Controllers)
4037 { 4842 {
@@ -4042,40 +4847,63 @@ namespace OpenSim.Region.Framework.Scenes
4042 sc.eventControls = (ScriptControlled)c.EventControls; 4847 sc.eventControls = (ScriptControlled)c.EventControls;
4043 4848
4044 scriptedcontrols[sc.itemID] = sc; 4849 scriptedcontrols[sc.itemID] = sc;
4850 IgnoredControls |= sc.ignoreControls; // this is not correct, aparently only last applied should count
4045 } 4851 }
4046 } 4852 }
4047 } 4853 }
4048 } 4854 }
4049 catch { } 4855 catch { }
4050 4856
4857 Animator.ResetAnimations();
4858
4859 Overrides.CopyAOPairsFrom(cAgent.MovementAnimationOverRides);
4860
4051 // FIXME: Why is this null check necessary? Where are the cases where we get a null Anims object? 4861 // 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) 4862 if (cAgent.DefaultAnim != null)
4055 Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero); 4863 Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero);
4056 if (cAgent.AnimState != null) 4864 if (cAgent.AnimState != null)
4057 Animator.Animations.SetImplicitDefaultAnimation(cAgent.AnimState.AnimID, cAgent.AnimState.SequenceNum, UUID.Zero); 4865 Animator.Animations.SetImplicitDefaultAnimation(cAgent.AnimState.AnimID, cAgent.AnimState.SequenceNum, UUID.Zero);
4866 if (cAgent.Anims != null)
4867 Animator.Animations.FromArray(cAgent.Anims);
4868 if (cAgent.MotionState != 0)
4869 Animator.currentControlState = (ScenePresenceAnimator.motionControlStates) cAgent.MotionState;
4058 4870
4059 if (Scene.AttachmentsModule != null) 4871
4872 crossingFlags = cAgent.CrossingFlags;
4873 gotCrossUpdate = (crossingFlags != 0);
4874 if(gotCrossUpdate)
4875 {
4876 LastCommands &= ~(ScriptControlled.CONTROL_LBUTTON | ScriptControlled.CONTROL_ML_LBUTTON);
4877 if((cAgent.CrossExtraFlags & 1) != 0)
4878 LastCommands |= ScriptControlled.CONTROL_LBUTTON;
4879 if((cAgent.CrossExtraFlags & 2) != 0)
4880 LastCommands |= ScriptControlled.CONTROL_ML_LBUTTON;
4881 MouseDown = (cAgent.CrossExtraFlags & 3) != 0;
4882 }
4883
4884 haveGroupInformation = false;
4885 // using this as protocol detection don't want to mess with the numbers for now
4886 if(cAgent.ActiveGroupTitle != null)
4060 { 4887 {
4061 // If the JobEngine is running we can schedule this job now and continue rather than waiting for all 4888 haveGroupInformation = true;
4062 // attachments to copy, which might take a long time in the Hypergrid case as the entire inventory 4889 COF = cAgent.agentCOF;
4063 // graph is inspected for each attachments and assets possibly fetched. 4890 if(ControllingClient.IsGroupMember(cAgent.ActiveGroupID))
4064 // 4891 {
4065 // We don't need to worry about a race condition as the job to later start the scripts is also 4892 ControllingClient.ActiveGroupId = cAgent.ActiveGroupID;
4066 // JobEngine scheduled and so will always occur after this task. 4893 ControllingClient.ActiveGroupName = cAgent.ActiveGroupName;
4067 // XXX: This will not be true if JobEngine ever gets more than one thread. 4894 Grouptitle = cAgent.ActiveGroupTitle;
4068 WorkManager.RunJob( 4895 ControllingClient.ActiveGroupPowers =
4069 "CopyAttachments", 4896 ControllingClient.GetGroupPowers(cAgent.ActiveGroupID);
4070 o => Scene.AttachmentsModule.CopyAttachments(cAgent, this), 4897 }
4071 null, 4898 else
4072 string.Format("Copy attachments for {0} entering {1}", Name, Scene.Name), 4899 {
4073 true); 4900 // we got a unknown active group so get what groups thinks about us
4074 } 4901 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
4075 4902 if (gm != null)
4076 // This must occur after attachments are copied or scheduled to be copied, as it releases the CompleteMovement() calling thread 4903 gm.SendAgentGroupDataUpdate(ControllingClient);
4077 // originating from the client completing a teleport. Otherwise, CompleteMovement() code to restart 4904 }
4078 // script attachments can outrace this thread. 4905 }
4906
4079 lock (m_originRegionIDAccessLock) 4907 lock (m_originRegionIDAccessLock)
4080 m_originRegionID = cAgent.RegionID; 4908 m_originRegionID = cAgent.RegionID;
4081 } 4909 }
@@ -4083,7 +4911,7 @@ namespace OpenSim.Region.Framework.Scenes
4083 public bool CopyAgent(out IAgentData agent) 4911 public bool CopyAgent(out IAgentData agent)
4084 { 4912 {
4085 agent = new CompleteAgentData(); 4913 agent = new CompleteAgentData();
4086 CopyTo((AgentData)agent); 4914 CopyTo((AgentData)agent, false);
4087 return true; 4915 return true;
4088 } 4916 }
4089 4917
@@ -4094,15 +4922,21 @@ namespace OpenSim.Region.Framework.Scenes
4094 /// </summary> 4922 /// </summary>
4095 public void UpdateMovement() 4923 public void UpdateMovement()
4096 { 4924 {
4097 if (m_forceToApply.HasValue) 4925/*
4098 { 4926 if (IsInTransit)
4099 Vector3 force = m_forceToApply.Value; 4927 return;
4100 4928
4101 Velocity = force; 4929 lock(m_forceToApplyLock)
4930 {
4931 if (m_forceToApplyValid)
4932 {
4933 Velocity = m_forceToApply;
4102 4934
4103 m_forceToApply = null; 4935 m_forceToApplyValid = false;
4104 TriggerScenePresenceUpdated(); 4936 TriggerScenePresenceUpdated();
4937 }
4105 } 4938 }
4939*/
4106 } 4940 }
4107 4941
4108 /// <summary> 4942 /// <summary>
@@ -4124,22 +4958,23 @@ namespace OpenSim.Region.Framework.Scenes
4124 if (Appearance.AvatarHeight == 0) 4958 if (Appearance.AvatarHeight == 0)
4125// Appearance.SetHeight(); 4959// Appearance.SetHeight();
4126 Appearance.SetSize(new Vector3(0.45f,0.6f,1.9f)); 4960 Appearance.SetSize(new Vector3(0.45f,0.6f,1.9f));
4127
4128/*
4129 PhysicsActor = scene.AddAvatar(
4130 LocalId, Firstname + "." + Lastname, pVec,
4131 new Vector3(0.45f, 0.6f, Appearance.AvatarHeight), isFlying);
4132*/
4133 4961
4134 PhysicsActor = m_scene.PhysicsScene.AddAvatar( 4962// lock(m_forceToApplyLock)
4135 LocalId, Firstname + "." + Lastname, AbsolutePosition, Velocity, 4963// m_forceToApplyValid = false;
4136 Appearance.AvatarBoxSize, isFlying); 4964
4965 PhysicsScene scene = m_scene.PhysicsScene;
4966 Vector3 pVec = AbsolutePosition;
4137 4967
4968 PhysicsActor = scene.AddAvatar(
4969 LocalId, Firstname + "." + Lastname, pVec,
4970 Appearance.AvatarBoxSize,Appearance.AvatarFeetOffset, isFlying);
4971 PhysicsActor.Orientation = m_bodyRot;
4138 //PhysicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients; 4972 //PhysicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients;
4139 PhysicsActor.OnCollisionUpdate += PhysicsCollisionUpdate; 4973 PhysicsActor.OnCollisionUpdate += PhysicsCollisionUpdate;
4140 PhysicsActor.OnOutOfBounds += OutOfBoundsCall; // Called for PhysicsActors when there's something wrong 4974 PhysicsActor.OnOutOfBounds += OutOfBoundsCall; // Called for PhysicsActors when there's something wrong
4141 PhysicsActor.SubscribeEvents(100); 4975 PhysicsActor.SubscribeEvents(100);
4142 PhysicsActor.LocalID = LocalId; 4976 PhysicsActor.LocalID = LocalId;
4977 PhysicsActor.SetAlwaysRun = m_setAlwaysRun;
4143 } 4978 }
4144 4979
4145 private void OutOfBoundsCall(Vector3 pos) 4980 private void OutOfBoundsCall(Vector3 pos)
@@ -4152,7 +4987,6 @@ namespace OpenSim.Region.Framework.Scenes
4152 ControllingClient.SendAgentAlertMessage("Physics is having a problem with your avatar. You may not be able to move until you relog.", true); 4987 ControllingClient.SendAgentAlertMessage("Physics is having a problem with your avatar. You may not be able to move until you relog.", true);
4153 } 4988 }
4154 4989
4155
4156 /// <summary> 4990 /// <summary>
4157 /// Event called by the physics plugin to tell the avatar about a collision. 4991 /// Event called by the physics plugin to tell the avatar about a collision.
4158 /// </summary> 4992 /// </summary>
@@ -4166,24 +5000,26 @@ namespace OpenSim.Region.Framework.Scenes
4166 /// <param name="e"></param> 5000 /// <param name="e"></param>
4167 public void PhysicsCollisionUpdate(EventArgs e) 5001 public void PhysicsCollisionUpdate(EventArgs e)
4168 { 5002 {
4169 if (IsChildAgent || Animator == null) 5003 if (IsChildAgent)
4170 return; 5004 return;
4171 5005
5006 if(IsInTransit)
5007 return;
5008
4172 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) 5009 //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( 5010 // The Physics Scene will send updates every 500 ms grep: PhysicsActor.SubscribeEvents(
4174 // as of this comment the interval is set in AddToPhysicalScene 5011 // as of this comment the interval is set in AddToPhysicalScene
4175 5012
4176// if (m_updateCount > 0) 5013// if (m_updateCount > 0)
4177// { 5014// {
4178 if (Animator.UpdateMovementAnimations()) 5015// if (Animator != null && Animator.UpdateMovementAnimations())
4179 TriggerScenePresenceUpdated(); 5016// TriggerScenePresenceUpdated();
4180// m_updateCount--; 5017// m_updateCount--;
4181// } 5018// }
4182 5019
4183 CollisionEventUpdate collisionData = (CollisionEventUpdate)e; 5020 CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
4184 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList; 5021 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList;
4185 5022
4186
4187// // No collisions at all means we may be flying. Update always 5023// // No collisions at all means we may be flying. Update always
4188// // to make falling work 5024// // to make falling work
4189// if (m_lastColCount != coldata.Count || coldata.Count == 0) 5025// if (m_lastColCount != coldata.Count || coldata.Count == 0)
@@ -4192,81 +5028,98 @@ namespace OpenSim.Region.Framework.Scenes
4192// m_lastColCount = coldata.Count; 5028// m_lastColCount = coldata.Count;
4193// } 5029// }
4194 5030
4195 CollisionPlane = Vector4.UnitW; 5031 if (coldata.Count != 0)
5032 {
5033 ContactPoint lowest;
5034 lowest.SurfaceNormal = Vector3.Zero;
5035 lowest.Position = Vector3.Zero;
5036 lowest.Position.Z = float.MaxValue;
5037
5038 foreach (ContactPoint contact in coldata.Values)
5039 {
5040 if (contact.CharacterFeet && contact.Position.Z < lowest.Position.Z)
5041 lowest = contact;
5042 }
5043
5044 if (lowest.Position.Z != float.MaxValue)
5045 {
5046 lowest.SurfaceNormal = -lowest.SurfaceNormal;
5047 CollisionPlane = new Vector4(lowest.SurfaceNormal, Vector3.Dot(lowest.Position, lowest.SurfaceNormal));
5048 }
5049 else
5050 CollisionPlane = Vector4.UnitW;
5051 }
5052 else
5053 CollisionPlane = Vector4.UnitW;
5054
5055 RaiseCollisionScriptEvents(coldata);
4196 5056
4197 // Gods do not take damage and Invulnerable is set depending on parcel/region flags 5057 // Gods do not take damage and Invulnerable is set depending on parcel/region flags
4198 if (Invulnerable || GodLevel > 0) 5058 if (Invulnerable || IsViewerUIGod)
4199 return; 5059 return;
4200 5060
4201 // The following may be better in the ICombatModule 5061 // The following may be better in the ICombatModule
4202 // probably tweaking of the values for ground and normal prim collisions will be needed 5062 // probably tweaking of the values for ground and normal prim collisions will be needed
4203 float starthealth = Health; 5063 float startHealth = Health;
4204 uint killerObj = 0; 5064 if(coldata.Count > 0)
4205 SceneObjectPart part = null;
4206 foreach (uint localid in coldata.Keys)
4207 { 5065 {
4208 if (localid == 0) 5066 uint killerObj = 0;
4209 { 5067 SceneObjectPart part = null;
4210 part = null; 5068 float rvel; // relative velocity, negative on approch
4211 } 5069 foreach (uint localid in coldata.Keys)
4212 else
4213 {
4214 part = Scene.GetSceneObjectPart(localid);
4215 }
4216 if (part != null)
4217 { 5070 {
4218 // Ignore if it has been deleted or volume detect 5071 if (localid == 0)
4219 if (!part.ParentGroup.IsDeleted && !part.ParentGroup.IsVolumeDetect) 5072 {
5073 // 0 is the ground
5074 rvel = coldata[0].RelativeSpeed;
5075 if(rvel < -5.0f)
5076 Health -= 0.01f * rvel * rvel;
5077 }
5078 else
4220 { 5079 {
4221 if (part.ParentGroup.Damage > 0.0f) 5080 part = Scene.GetSceneObjectPart(localid);
5081
5082 if(part != null && !part.ParentGroup.IsVolumeDetect)
4222 { 5083 {
4223 // Something with damage... 5084 if (part.ParentGroup.Damage > 0.0f)
4224 Health -= part.ParentGroup.Damage; 5085 {
4225 part.ParentGroup.Scene.DeleteSceneObject(part.ParentGroup, false); 5086 // Something with damage...
5087 Health -= part.ParentGroup.Damage;
5088 part.ParentGroup.Scene.DeleteSceneObject(part.ParentGroup, false);
5089 }
5090 else
5091 {
5092 // An ordinary prim
5093 rvel = coldata[localid].RelativeSpeed;
5094 if(rvel < -5.0f)
5095 {
5096 Health -= 0.005f * rvel * rvel;
5097 }
5098 }
4226 } 5099 }
4227 else 5100 else
4228 { 5101 {
4229 // An ordinary prim 5102
4230 if (coldata[localid].PenetrationDepth >= 0.10f)
4231 Health -= coldata[localid].PenetrationDepth * 5.0f;
4232 } 5103 }
4233 } 5104 }
4234 }
4235 else
4236 {
4237 // 0 is the ground
4238 // what about collisions with other avatars?
4239 if (localid == 0 && coldata[localid].PenetrationDepth >= 0.10f)
4240 Health -= coldata[localid].PenetrationDepth * 5.0f;
4241 }
4242
4243 5105
4244 if (Health <= 0.0f) 5106 if (Health <= 0.0f)
4245 { 5107 {
4246 if (localid != 0) 5108 if (localid != 0)
4247 killerObj = localid; 5109 killerObj = localid;
4248 } 5110 }
4249 //m_log.Debug("[AVATAR]: Collision with localid: " + localid.ToString() + " at depth: " + coldata[localid].ToString());
4250 }
4251 //Health = 100;
4252 if (!Invulnerable)
4253 {
4254 if (starthealth != Health)
4255 {
4256 ControllingClient.SendHealth(Health);
4257 } 5111 }
5112
4258 if (Health <= 0) 5113 if (Health <= 0)
4259 { 5114 {
4260 m_scene.EventManager.TriggerAvatarKill(killerObj, this);
4261 }
4262 if (starthealth == Health && Health < 100.0f)
4263 {
4264 Health += 0.03f;
4265 if (Health > 100.0f)
4266 Health = 100.0f;
4267 ControllingClient.SendHealth(Health); 5115 ControllingClient.SendHealth(Health);
5116 m_scene.EventManager.TriggerAvatarKill(killerObj, this);
5117 return;
4268 } 5118 }
4269 } 5119 }
5120
5121 if(Math.Abs(Health - startHealth) > 1.0)
5122 ControllingClient.SendHealth(Health);
4270 } 5123 }
4271 5124
4272 public void setHealthWithUpdate(float health) 5125 public void setHealthWithUpdate(float health)
@@ -4280,25 +5133,25 @@ namespace OpenSim.Region.Framework.Scenes
4280 // Clear known regions 5133 // Clear known regions
4281 KnownRegions = new Dictionary<ulong, string>(); 5134 KnownRegions = new Dictionary<ulong, string>();
4282 5135
4283 lock (m_reprioritization_timer)
4284 {
4285 m_reprioritization_timer.Enabled = false;
4286 m_reprioritization_timer.Elapsed -= new ElapsedEventHandler(Reprioritize);
4287 }
4288
4289 // I don't get it but mono crashes when you try to dispose of this timer, 5136 // I don't get it but mono crashes when you try to dispose of this timer,
4290 // unsetting the elapsed callback should be enough to allow for cleanup however. 5137 // unsetting the elapsed callback should be enough to allow for cleanup however.
4291 // m_reprioritizationTimer.Dispose(); 5138 // m_reprioritizationTimer.Dispose();
4292 5139
4293 RemoveFromPhysicalScene(); 5140 RemoveFromPhysicalScene();
4294 5141
4295 m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd; 5142 m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd;
5143 RemoveClientEvents();
4296 5144
4297// if (Animator != null) 5145// if (Animator != null)
4298// Animator.Close(); 5146// Animator.Close();
4299 Animator = null; 5147 Animator = null;
4300 5148
5149 scriptedcontrols.Clear();
5150 ControllingClient = null;
4301 LifecycleState = ScenePresenceState.Removed; 5151 LifecycleState = ScenePresenceState.Removed;
5152 IsDeleted = true;
5153 m_updateAgentReceivedAfterTransferEvent.Dispose();
5154 m_updateAgentReceivedAfterTransferEvent = null;
4302 } 5155 }
4303 5156
4304 public void AddAttachment(SceneObjectGroup gobj) 5157 public void AddAttachment(SceneObjectGroup gobj)
@@ -4311,6 +5164,10 @@ namespace OpenSim.Region.Framework.Scenes
4311 5164
4312 m_attachments.Add(gobj); 5165 m_attachments.Add(gobj);
4313 } 5166 }
5167
5168 IBakedTextureModule bakedModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
5169 if (bakedModule != null)
5170 bakedModule.UpdateMeshAvatar(m_uuid);
4314 } 5171 }
4315 5172
4316 /// <summary> 5173 /// <summary>
@@ -4343,7 +5200,7 @@ namespace OpenSim.Region.Framework.Scenes
4343 } 5200 }
4344 } 5201 }
4345 } 5202 }
4346 5203
4347 return attachments; 5204 return attachments;
4348 } 5205 }
4349 5206
@@ -4474,6 +5331,287 @@ namespace OpenSim.Region.Framework.Scenes
4474 return validated; 5331 return validated;
4475 } 5332 }
4476 5333
5334 public void SendAttachmentsToAllAgents()
5335 {
5336 lock (m_attachments)
5337 {
5338 foreach (SceneObjectGroup sog in m_attachments)
5339 {
5340 m_scene.ForEachScenePresence(delegate(ScenePresence p)
5341 {
5342 if (p != this && sog.HasPrivateAttachmentPoint)
5343 return;
5344
5345 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod)
5346 return;
5347
5348 SendTerseUpdateToAgentNF(p);
5349 SendAttachmentFullUpdateToAgentNF(sog, p);
5350 });
5351 }
5352 }
5353 }
5354
5355 // send attachments to a client without filters except for huds
5356 // for now they are checked in several places down the line...
5357 public void SendAttachmentsToAgentNF(ScenePresence p)
5358 {
5359 SendTerseUpdateToAgentNF(p);
5360// SendAvatarDataToAgentNF(this);
5361 lock (m_attachments)
5362 {
5363 foreach (SceneObjectGroup sog in m_attachments)
5364 {
5365 SendAttachmentFullUpdateToAgentNF(sog, p);
5366 }
5367 }
5368 }
5369
5370 public void SendAttachmentFullUpdateToAgentNF(SceneObjectGroup sog, ScenePresence p)
5371 {
5372 if (p != this && sog.HasPrivateAttachmentPoint)
5373 return;
5374
5375 SceneObjectPart[] parts = sog.Parts;
5376 SceneObjectPart rootpart = sog.RootPart;
5377
5378 p.ControllingClient.SendEntityUpdate(rootpart, PrimUpdateFlags.FullUpdate);
5379
5380 for (int i = 0; i < parts.Length; i++)
5381 {
5382 SceneObjectPart part = parts[i];
5383 if (part == rootpart)
5384 continue;
5385 p.ControllingClient.SendEntityUpdate(part, PrimUpdateFlags.FullUpdate);
5386 }
5387 }
5388
5389 public void SendAttachmentScheduleUpdate(SceneObjectGroup sog)
5390 {
5391 if (IsChildAgent || IsInTransit)
5392 return;
5393
5394 SceneObjectPart[] origparts = sog.Parts;
5395 SceneObjectPart[] parts = new SceneObjectPart[origparts.Length];
5396 PrimUpdateFlags[] flags = new PrimUpdateFlags[origparts.Length];
5397
5398 SceneObjectPart rootpart = sog.RootPart;
5399 UpdateRequired rootreq = sog.RootPart.UpdateFlag;
5400
5401 int j = 0;
5402 bool allterse = true;
5403 for (int i = 0; i < origparts.Length; i++)
5404 {
5405 if (origparts[i] != rootpart)
5406 {
5407 switch (origparts[i].UpdateFlag)
5408 {
5409 case UpdateRequired.NONE:
5410 break;
5411
5412 case UpdateRequired.TERSE:
5413 flags[j] = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
5414 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity;
5415 parts[j] = origparts[i];
5416 j++;
5417 break;
5418
5419 case UpdateRequired.FULL:
5420 flags[j] = PrimUpdateFlags.FullUpdate;
5421 allterse = false;
5422 parts[j] = origparts[i];
5423 j++;
5424 break;
5425 }
5426 }
5427 origparts[i].UpdateFlag = 0;
5428 }
5429
5430 if (j == 0 && rootreq == UpdateRequired.NONE)
5431 return;
5432
5433 PrimUpdateFlags rootflag = PrimUpdateFlags.FullUpdate;
5434
5435 if (rootreq != UpdateRequired.FULL && allterse)
5436 {
5437 rootflag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
5438 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity;
5439 }
5440
5441 int nparts = j;
5442
5443 ControllingClient.SendEntityUpdate(rootpart, rootflag);
5444
5445 for (int i = 0; i < nparts; i++)
5446 {
5447 ControllingClient.SendEntityUpdate(parts[i], flags[i]);
5448 }
5449
5450 if (sog.HasPrivateAttachmentPoint)
5451 return;
5452
5453 List<ScenePresence> allPresences = m_scene.GetScenePresences();
5454 foreach (ScenePresence p in allPresences)
5455 {
5456 if (p == this)
5457 continue;
5458
5459 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod)
5460 continue;
5461
5462 p.ControllingClient.SendEntityUpdate(rootpart, rootflag);
5463
5464 for (int i = 0; i < nparts; i++)
5465 {
5466 p.ControllingClient.SendEntityUpdate(parts[i], flags[i]);
5467 }
5468 }
5469 }
5470
5471 public void SendAttachmentUpdate(SceneObjectGroup sog, UpdateRequired UpdateFlag)
5472 {
5473 if (IsChildAgent || IsInTransit)
5474 return;
5475
5476 PrimUpdateFlags flag;
5477 switch (UpdateFlag)
5478 {
5479 case UpdateRequired.TERSE:
5480 flag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
5481 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity;
5482 break;
5483
5484 case UpdateRequired.FULL:
5485 flag = PrimUpdateFlags.FullUpdate;
5486 break;
5487
5488 default:
5489 return;
5490 }
5491
5492 SceneObjectPart[] parts = sog.Parts;
5493 SceneObjectPart rootpart = sog.RootPart;
5494
5495// rootpart.UpdateFlag = 0;
5496
5497 ControllingClient.SendEntityUpdate(rootpart, flag);
5498
5499 for (int i = 0; i < parts.Length; i++)
5500 {
5501 SceneObjectPart part = parts[i];
5502 if (part == rootpart)
5503 continue;
5504 ControllingClient.SendEntityUpdate(part, flag);
5505// part.UpdateFlag = 0;
5506 }
5507
5508 if (sog.HasPrivateAttachmentPoint)
5509 return;
5510
5511 List<ScenePresence> allPresences = m_scene.GetScenePresences();
5512 foreach (ScenePresence p in allPresences)
5513 {
5514 if (p == this)
5515 continue;
5516
5517 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod)
5518 continue;
5519
5520 p.ControllingClient.SendEntityUpdate(rootpart, flag);
5521
5522 for (int i = 0; i < parts.Length; i++)
5523 {
5524 SceneObjectPart part = parts[i];
5525 if (part == rootpart)
5526 continue;
5527 p.ControllingClient.SendEntityUpdate(part, flag);
5528 }
5529 }
5530 }
5531
5532 public void SendAttachmentScheduleUpdate(SceneObjectPart part)
5533 {
5534 if (IsChildAgent || IsInTransit)
5535 return;
5536
5537
5538 PrimUpdateFlags flag;
5539 switch (part.UpdateFlag)
5540 {
5541 case UpdateRequired.TERSE:
5542 flag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
5543 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity;
5544 break;
5545
5546 case UpdateRequired.FULL:
5547 flag = PrimUpdateFlags.FullUpdate;
5548 break;
5549
5550 default:
5551 return;
5552 }
5553
5554 part.UpdateFlag = 0;
5555
5556 ControllingClient.SendEntityUpdate(part, flag);
5557
5558 if (part.ParentGroup.HasPrivateAttachmentPoint)
5559 return;
5560
5561 List<ScenePresence> allPresences = m_scene.GetScenePresences();
5562 foreach (ScenePresence p in allPresences)
5563 {
5564 if (p == this)
5565 continue;
5566
5567 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod)
5568 continue;
5569
5570 p.ControllingClient.SendEntityUpdate(part, flag);
5571 }
5572 }
5573
5574
5575 public void SendAttachmentUpdate(SceneObjectPart part, UpdateRequired UpdateFlag)
5576 {
5577 if (IsChildAgent || IsInTransit)
5578 return;
5579
5580 PrimUpdateFlags flag;
5581 switch (UpdateFlag)
5582 {
5583 case UpdateRequired.TERSE:
5584 flag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
5585 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity;
5586 break;
5587
5588 case UpdateRequired.FULL:
5589 flag = PrimUpdateFlags.FullUpdate;
5590 break;
5591
5592 default:
5593 return;
5594 }
5595
5596// part.UpdateFlag = 0;
5597
5598 ControllingClient.SendEntityUpdate(part, flag);
5599
5600 if (part.ParentGroup.HasPrivateAttachmentPoint)
5601 return;
5602
5603 List<ScenePresence> allPresences = m_scene.GetScenePresences();
5604 foreach (ScenePresence p in allPresences)
5605 {
5606 if (p == this)
5607 continue;
5608 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod)
5609 continue;
5610
5611 p.ControllingClient.SendEntityUpdate(part, flag);
5612 }
5613 }
5614
4477 /// <summary> 5615 /// <summary>
4478 /// Send a script event to this scene presence's attachments 5616 /// Send a script event to this scene presence's attachments
4479 /// </summary> 5617 /// </summary>
@@ -4530,10 +5668,21 @@ namespace OpenSim.Region.Framework.Scenes
4530 } 5668 }
4531 } 5669 }
4532 5670
5671 CameraData physActor_OnPhysicsRequestingCameraData()
5672 {
5673 return new CameraData
5674 {
5675 Valid = true,
5676 MouseLook = this.m_mouseLook,
5677 CameraRotation = this.CameraRotation,
5678 CameraAtAxis = this.CameraAtAxis
5679 };
5680 }
5681
4533 public void RegisterControlEventsToScript(int controls, int accept, int pass_on, uint Obj_localID, UUID Script_item_UUID) 5682 public void RegisterControlEventsToScript(int controls, int accept, int pass_on, uint Obj_localID, UUID Script_item_UUID)
4534 { 5683 {
4535 SceneObjectPart p = m_scene.GetSceneObjectPart(Obj_localID); 5684 SceneObjectPart part = m_scene.GetSceneObjectPart(Obj_localID);
4536 if (p == null) 5685 if (part == null)
4537 return; 5686 return;
4538 5687
4539 ControllingClient.SendTakeControls(controls, false, false); 5688 ControllingClient.SendTakeControls(controls, false, false);
@@ -4543,7 +5692,7 @@ namespace OpenSim.Region.Framework.Scenes
4543 obj.ignoreControls = ScriptControlled.CONTROL_ZERO; 5692 obj.ignoreControls = ScriptControlled.CONTROL_ZERO;
4544 obj.eventControls = ScriptControlled.CONTROL_ZERO; 5693 obj.eventControls = ScriptControlled.CONTROL_ZERO;
4545 5694
4546 obj.objectID = p.ParentGroup.UUID; 5695 obj.objectID = part.ParentGroup.UUID;
4547 obj.itemID = Script_item_UUID; 5696 obj.itemID = Script_item_UUID;
4548 if (pass_on == 0 && accept == 0) 5697 if (pass_on == 0 && accept == 0)
4549 { 5698 {
@@ -4562,7 +5711,6 @@ namespace OpenSim.Region.Framework.Scenes
4562 { 5711 {
4563 IgnoredControls = ScriptControlled.CONTROL_ZERO; 5712 IgnoredControls = ScriptControlled.CONTROL_ZERO;
4564 obj.eventControls = (ScriptControlled)controls; 5713 obj.eventControls = (ScriptControlled)controls;
4565 obj.ignoreControls = ScriptControlled.CONTROL_ZERO;
4566 } 5714 }
4567 5715
4568 lock (scriptedcontrols) 5716 lock (scriptedcontrols)
@@ -4571,19 +5719,52 @@ namespace OpenSim.Region.Framework.Scenes
4571 { 5719 {
4572 IgnoredControls &= ~(ScriptControlled)controls; 5720 IgnoredControls &= ~(ScriptControlled)controls;
4573 if (scriptedcontrols.ContainsKey(Script_item_UUID)) 5721 if (scriptedcontrols.ContainsKey(Script_item_UUID))
4574 scriptedcontrols.Remove(Script_item_UUID); 5722 RemoveScriptFromControlNotifications(Script_item_UUID, part);
4575 } 5723 }
4576 else 5724 else
4577 { 5725 {
4578 scriptedcontrols[Script_item_UUID] = obj; 5726 AddScriptToControlNotifications(Script_item_UUID, part, ref obj);
4579 } 5727 }
4580 } 5728 }
4581 5729
4582 ControllingClient.SendTakeControls(controls, pass_on == 1 ? true : false, true); 5730 ControllingClient.SendTakeControls(controls, pass_on == 1 ? true : false, true);
4583 } 5731 }
4584 5732
5733 private void AddScriptToControlNotifications(OpenMetaverse.UUID Script_item_UUID, SceneObjectPart part, ref ScriptControllers obj)
5734 {
5735 scriptedcontrols[Script_item_UUID] = obj;
5736
5737 PhysicsActor physActor = part.ParentGroup.RootPart.PhysActor;
5738 if (physActor != null)
5739 {
5740 physActor.OnPhysicsRequestingCameraData -= physActor_OnPhysicsRequestingCameraData;
5741 physActor.OnPhysicsRequestingCameraData += physActor_OnPhysicsRequestingCameraData;
5742 }
5743 }
5744
5745 private void RemoveScriptFromControlNotifications(OpenMetaverse.UUID Script_item_UUID, SceneObjectPart part)
5746 {
5747 scriptedcontrols.Remove(Script_item_UUID);
5748
5749 if (part != null)
5750 {
5751 PhysicsActor physActor = part.ParentGroup.RootPart.PhysActor;
5752 if (physActor != null)
5753 {
5754 physActor.OnPhysicsRequestingCameraData -= physActor_OnPhysicsRequestingCameraData;
5755 }
5756 }
5757 }
5758
4585 public void HandleForceReleaseControls(IClientAPI remoteClient, UUID agentID) 5759 public void HandleForceReleaseControls(IClientAPI remoteClient, UUID agentID)
4586 { 5760 {
5761 foreach (ScriptControllers c in scriptedcontrols.Values)
5762 {
5763 SceneObjectGroup sog = m_scene.GetSceneObjectGroup(c.objectID);
5764 if(sog != null && !sog.IsDeleted && sog.RootPart.PhysActor != null)
5765 sog.RootPart.PhysActor.OnPhysicsRequestingCameraData -= physActor_OnPhysicsRequestingCameraData;
5766 }
5767
4587 IgnoredControls = ScriptControlled.CONTROL_ZERO; 5768 IgnoredControls = ScriptControlled.CONTROL_ZERO;
4588 lock (scriptedcontrols) 5769 lock (scriptedcontrols)
4589 { 5770 {
@@ -4592,7 +5773,36 @@ namespace OpenSim.Region.Framework.Scenes
4592 ControllingClient.SendTakeControls(int.MaxValue, false, false); 5773 ControllingClient.SendTakeControls(int.MaxValue, false, false);
4593 } 5774 }
4594 5775
4595 private void UnRegisterSeatControls(UUID obj) 5776 public void HandleRevokePermissions(UUID objectID, uint permissions )
5777 {
5778
5779 // still skeleton code
5780 if((permissions & (16 | 0x8000 )) == 0) //PERMISSION_TRIGGER_ANIMATION | PERMISSION_OVERRIDE_ANIMATIONS
5781 return;
5782 if(objectID == m_scene.RegionInfo.RegionID) // for all objects
5783 {
5784
5785 }
5786 else
5787 {
5788 SceneObjectPart part = m_scene.GetSceneObjectPart(objectID);
5789 if(part != null)
5790 {
5791
5792 }
5793 }
5794 }
5795
5796 public void ClearControls()
5797 {
5798 IgnoredControls = ScriptControlled.CONTROL_ZERO;
5799 lock (scriptedcontrols)
5800 {
5801 scriptedcontrols.Clear();
5802 }
5803 }
5804
5805 public void UnRegisterSeatControls(UUID obj)
4596 { 5806 {
4597 List<UUID> takers = new List<UUID>(); 5807 List<UUID> takers = new List<UUID>();
4598 5808
@@ -4610,17 +5820,18 @@ namespace OpenSim.Region.Framework.Scenes
4610 public void UnRegisterControlEventsToScript(uint Obj_localID, UUID Script_item_UUID) 5820 public void UnRegisterControlEventsToScript(uint Obj_localID, UUID Script_item_UUID)
4611 { 5821 {
4612 ScriptControllers takecontrols; 5822 ScriptControllers takecontrols;
5823 SceneObjectPart part = m_scene.GetSceneObjectPart(Obj_localID);
4613 5824
4614 lock (scriptedcontrols) 5825 lock (scriptedcontrols)
4615 { 5826 {
4616 if (scriptedcontrols.TryGetValue(Script_item_UUID, out takecontrols)) 5827 if (scriptedcontrols.TryGetValue(Script_item_UUID, out takecontrols))
4617 { 5828 {
4618 ScriptControlled sctc = takecontrols.eventControls; 5829 ScriptControlled sctc = takecontrols.eventControls;
4619 5830
4620 ControllingClient.SendTakeControls((int)sctc, false, false); 5831 ControllingClient.SendTakeControls((int)sctc, false, false);
4621 ControllingClient.SendTakeControls((int)sctc, true, false); 5832 ControllingClient.SendTakeControls((int)sctc, true, false);
4622 5833
4623 scriptedcontrols.Remove(Script_item_UUID); 5834 RemoveScriptFromControlNotifications(Script_item_UUID, part);
4624 IgnoredControls = ScriptControlled.CONTROL_ZERO; 5835 IgnoredControls = ScriptControlled.CONTROL_ZERO;
4625 foreach (ScriptControllers scData in scriptedcontrols.Values) 5836 foreach (ScriptControllers scData in scriptedcontrols.Values)
4626 { 5837 {
@@ -4639,46 +5850,38 @@ namespace OpenSim.Region.Framework.Scenes
4639 if (scriptedcontrols.Count <= 0) 5850 if (scriptedcontrols.Count <= 0)
4640 return; 5851 return;
4641 5852
4642 ScriptControlled allflags = ScriptControlled.CONTROL_ZERO; 5853 ScriptControlled allflags;
4643 5854 // convert mouse from edge to level
4644 if (MouseDown) 5855 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_UP) != 0 ||
5856 (flags & unchecked((uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_UP)) != 0)
4645 { 5857 {
4646 allflags = LastCommands & (ScriptControlled.CONTROL_ML_LBUTTON | ScriptControlled.CONTROL_LBUTTON); 5858 allflags = ScriptControlled.CONTROL_ZERO;
4647 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_UP) != 0 || (flags & unchecked((uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_UP)) != 0)
4648 {
4649 allflags = ScriptControlled.CONTROL_ZERO;
4650 MouseDown = true;
4651 }
4652 } 5859 }
4653 5860 else // recover last state of mouse
5861 allflags = LastCommands & (ScriptControlled.CONTROL_ML_LBUTTON | ScriptControlled.CONTROL_LBUTTON);
5862
4654 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_DOWN) != 0) 5863 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_DOWN) != 0)
4655 {
4656 allflags |= ScriptControlled.CONTROL_ML_LBUTTON; 5864 allflags |= ScriptControlled.CONTROL_ML_LBUTTON;
4657 MouseDown = true; 5865
4658 }
4659
4660 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0) 5866 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0)
4661 {
4662 allflags |= ScriptControlled.CONTROL_LBUTTON; 5867 allflags |= ScriptControlled.CONTROL_LBUTTON;
4663 MouseDown = true; 5868
4664 }
4665
4666 // find all activated controls, whether the scripts are interested in them or not 5869 // find all activated controls, whether the scripts are interested in them or not
4667 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) != 0) 5870 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) != 0)
4668 { 5871 {
4669 allflags |= ScriptControlled.CONTROL_FWD; 5872 allflags |= ScriptControlled.CONTROL_FWD;
4670 } 5873 }
4671 5874
4672 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG) != 0) 5875 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG) != 0)
4673 { 5876 {
4674 allflags |= ScriptControlled.CONTROL_BACK; 5877 allflags |= ScriptControlled.CONTROL_BACK;
4675 } 5878 }
4676 5879
4677 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS) != 0) 5880 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS) != 0)
4678 { 5881 {
4679 allflags |= ScriptControlled.CONTROL_UP; 5882 allflags |= ScriptControlled.CONTROL_UP;
4680 } 5883 }
4681 5884
4682 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0) 5885 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)
4683 { 5886 {
4684 allflags |= ScriptControlled.CONTROL_DOWN; 5887 allflags |= ScriptControlled.CONTROL_DOWN;
@@ -4688,17 +5891,17 @@ namespace OpenSim.Region.Framework.Scenes
4688 { 5891 {
4689 allflags |= ScriptControlled.CONTROL_LEFT; 5892 allflags |= ScriptControlled.CONTROL_LEFT;
4690 } 5893 }
4691 5894
4692 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG) != 0) 5895 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG) != 0)
4693 { 5896 {
4694 allflags |= ScriptControlled.CONTROL_RIGHT; 5897 allflags |= ScriptControlled.CONTROL_RIGHT;
4695 } 5898 }
4696 5899
4697 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) 5900 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
4698 { 5901 {
4699 allflags |= ScriptControlled.CONTROL_ROT_RIGHT; 5902 allflags |= ScriptControlled.CONTROL_ROT_RIGHT;
4700 } 5903 }
4701 5904
4702 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0) 5905 if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0)
4703 { 5906 {
4704 allflags |= ScriptControlled.CONTROL_ROT_LEFT; 5907 allflags |= ScriptControlled.CONTROL_ROT_LEFT;
@@ -4711,7 +5914,7 @@ namespace OpenSim.Region.Framework.Scenes
4711 { 5914 {
4712 UUID scriptUUID = kvp.Key; 5915 UUID scriptUUID = kvp.Key;
4713 ScriptControllers scriptControlData = kvp.Value; 5916 ScriptControllers scriptControlData = kvp.Value;
4714 5917
4715 ScriptControlled localHeld = allflags & scriptControlData.eventControls; // the flags interesting for us 5918 ScriptControlled localHeld = allflags & scriptControlData.eventControls; // the flags interesting for us
4716 ScriptControlled localLast = LastCommands & scriptControlData.eventControls; // the activated controls in the last cycle 5919 ScriptControlled localLast = LastCommands & scriptControlData.eventControls; // the activated controls in the last cycle
4717 ScriptControlled localChange = localHeld ^ localLast; // the changed bits 5920 ScriptControlled localChange = localHeld ^ localLast; // the changed bits
@@ -4723,8 +5926,9 @@ namespace OpenSim.Region.Framework.Scenes
4723 } 5926 }
4724 } 5927 }
4725 } 5928 }
4726 5929
4727 LastCommands = allflags; 5930 LastCommands = allflags;
5931 MouseDown = (allflags & (ScriptControlled.CONTROL_ML_LBUTTON | ScriptControlled.CONTROL_LBUTTON)) != 0;
4728 } 5932 }
4729 } 5933 }
4730 5934
@@ -4765,191 +5969,252 @@ namespace OpenSim.Region.Framework.Scenes
4765 return flags; 5969 return flags;
4766 } 5970 }
4767 5971
4768 private void ReprioritizeUpdates() 5972 // returns true it local teleport allowed and sets the destiny position into pos
5973
5974 private bool CheckLocalTPLandingPoint(ref Vector3 pos)
4769 { 5975 {
4770 if (Scene.IsReprioritizationEnabled && Scene.UpdatePrioritizationScheme != UpdatePrioritizationSchemes.Time) 5976 // Never constrain lures
5977 if ((TeleportFlags & TeleportFlags.ViaLure) != 0)
5978 return true;
5979
5980 if (m_scene.RegionInfo.EstateSettings.AllowDirectTeleport)
5981 return true;
5982
5983 // do not constrain gods and estate managers
5984 if(m_scene.Permissions.IsGod(m_uuid) ||
5985 m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_uuid))
5986 return true;
5987
5988 // will teleport to a telehub spawn point or landpoint if that results in getting closer to target
5989 // if not the local teleport fails.
5990
5991 float currDistanceSQ = Vector3.DistanceSquared(AbsolutePosition, pos);
5992
5993 // first check telehub
5994
5995 UUID TelehubObjectID = m_scene.RegionInfo.RegionSettings.TelehubObject;
5996 if ( TelehubObjectID != UUID.Zero)
4771 { 5997 {
4772 lock (m_reprioritization_timer) 5998 SceneObjectGroup telehubSOG = m_scene.GetSceneObjectGroup(TelehubObjectID);
5999 if(telehubSOG != null)
4773 { 6000 {
4774 if (!m_reprioritizing) 6001 Vector3 spawnPos;
4775 m_reprioritization_timer.Enabled = m_reprioritizing = true; 6002 float spawnDistSQ;
6003
6004 SpawnPoint[] spawnPoints = m_scene.RegionInfo.RegionSettings.SpawnPoints().ToArray();
6005 if(spawnPoints.Length == 0)
6006 {
6007 spawnPos = new Vector3(128.0f, 128.0f, pos.Z);
6008 spawnDistSQ = Vector3.DistanceSquared(spawnPos, pos);
6009 }
4776 else 6010 else
4777 m_reprioritization_called = true; 6011 {
4778 } 6012 Vector3 hubPos = telehubSOG.AbsolutePosition;
4779 } 6013 Quaternion hubRot = telehubSOG.GroupRotation;
4780 }
4781 6014
4782 private void Reprioritize(object sender, ElapsedEventArgs e) 6015 spawnPos = spawnPoints[0].GetLocation(hubPos, hubRot);
4783 { 6016 spawnDistSQ = Vector3.DistanceSquared(spawnPos, pos);
4784 ControllingClient.ReprioritizeUpdates();
4785 6017
4786 lock (m_reprioritization_timer) 6018 float testDistSQ;
4787 { 6019 Vector3 testSpawnPos;
4788 m_reprioritization_timer.Enabled = m_reprioritizing = m_reprioritization_called; 6020 for(int i = 1; i< spawnPoints.Length; i++)
4789 m_reprioritization_called = false; 6021 {
6022 testSpawnPos = spawnPoints[i].GetLocation(hubPos, hubRot);
6023 testDistSQ = Vector3.DistanceSquared(testSpawnPos, pos);
6024
6025 if(testDistSQ < spawnDistSQ)
6026 {
6027 spawnPos = testSpawnPos;
6028 spawnDistSQ = testDistSQ;
6029 }
6030 }
6031 }
6032 if (currDistanceSQ < spawnDistSQ)
6033 {
6034 // we are already close
6035 ControllingClient.SendAlertMessage("Can't teleport closer to destination");
6036 return false;
6037 }
6038 else
6039 {
6040 pos = spawnPos;
6041 return true;
6042 }
6043 }
4790 } 6044 }
4791 }
4792 6045
4793 private void CheckLandingPoint(ref Vector3 pos) 6046 ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
4794 {
4795 // Never constrain lures
4796 if ((TeleportFlags & TeleportFlags.ViaLure) != 0)
4797 return;
4798 6047
4799 if (m_scene.RegionInfo.EstateSettings.AllowDirectTeleport) 6048 if (land.LandData.LandingType != (byte)LandingType.LandingPoint
4800 return; 6049 || land.LandData.OwnerID == m_uuid)
6050 return true;
4801 6051
4802 ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y); 6052 Vector3 landLocation = land.LandData.UserLocation;
6053 if(landLocation == Vector3.Zero)
6054 return true;
4803 6055
4804 if (land.LandData.LandingType == (byte)LandingType.LandingPoint && 6056 if (currDistanceSQ < Vector3.DistanceSquared(landLocation, pos))
4805 land.LandData.UserLocation != Vector3.Zero &&
4806 land.LandData.OwnerID != m_uuid &&
4807 (!m_scene.Permissions.IsGod(m_uuid)) &&
4808 (!m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_uuid)))
4809 { 6057 {
4810 float curr = Vector3.Distance(AbsolutePosition, pos); 6058 ControllingClient.SendAlertMessage("Can't teleport closer to destination");
4811 if (Vector3.Distance(land.LandData.UserLocation, pos) < curr) 6059 return false;
4812 pos = land.LandData.UserLocation;
4813 else
4814 ControllingClient.SendAlertMessage("Can't teleport closer to destination");
4815 } 6060 }
6061
6062 pos = land.LandData.UserLocation;
6063 return true;
4816 } 6064 }
4817 6065
4818 private void CheckAndAdjustTelehub(SceneObjectGroup telehub, ref Vector3 pos) 6066 const TeleportFlags TeleHubTPFlags = TeleportFlags.ViaLogin
6067 | TeleportFlags.ViaHGLogin | TeleportFlags.ViaLocation;
6068
6069 private bool CheckAndAdjustTelehub(SceneObjectGroup telehub, ref Vector3 pos, ref bool positionChanged)
4819 { 6070 {
4820 if ((m_teleportFlags & (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID)) == 6071 // forcing telehubs on any tp that reachs this
4821 (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID) || 6072 if ((m_teleportFlags & TeleHubTPFlags) != 0 ||
4822 (m_scene.TelehubAllowLandmarks == true ? false : ((m_teleportFlags & TeleportFlags.ViaLandmark) != 0 )) || 6073 (m_scene.TelehubAllowLandmarks == true ? false : ((m_teleportFlags & TeleportFlags.ViaLandmark) != 0 )))
4823 (m_teleportFlags & TeleportFlags.ViaLocation) != 0 ||
4824 (m_teleportFlags & Constants.TeleportFlags.ViaHGLogin) != 0)
4825 { 6074 {
6075 ILandObject land;
6076 Vector3 teleHubPosition = telehub.AbsolutePosition;
4826 6077
4827 if (GodLevel < 200 && 6078 SpawnPoint[] spawnPoints = m_scene.RegionInfo.RegionSettings.SpawnPoints().ToArray();
4828 ((!m_scene.Permissions.IsGod(m_uuid) && 6079 if(spawnPoints.Length == 0)
4829 !m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_uuid)) ||
4830 (m_teleportFlags & TeleportFlags.ViaLocation) != 0 ||
4831 (m_teleportFlags & Constants.TeleportFlags.ViaHGLogin) != 0))
4832 { 6080 {
4833 SpawnPoint[] spawnPoints = m_scene.RegionInfo.RegionSettings.SpawnPoints().ToArray(); 6081 land = m_scene.LandChannel.GetLandObject(teleHubPosition.X,teleHubPosition.Y);
4834 if (spawnPoints.Length == 0) 6082 if(land != null)
4835 { 6083 {
4836 if(m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_uuid)) 6084 pos = teleHubPosition;
4837 { 6085 if(land.IsEitherBannedOrRestricted(UUID))
4838 pos.X = 128.0f; 6086 return false;
4839 pos.Y = 128.0f; 6087 positionChanged = true;
4840 } 6088 return true;
4841 return;
4842 } 6089 }
6090 else
6091 return false;
6092 }
4843 6093
4844 int index; 6094 int index;
4845 bool selected = false; 6095 int tries;
4846 6096 bool selected = false;
4847 switch (m_scene.SpawnPointRouting) 6097 bool validhub = false;
4848 { 6098 Vector3 spawnPosition;
4849 case "random":
4850 6099
4851 if (spawnPoints.Length == 0) 6100 Quaternion teleHubRotation = telehub.GroupRotation;
4852 return;
4853 do
4854 {
4855 index = Util.RandomClass.Next(spawnPoints.Length - 1);
4856
4857 Vector3 spawnPosition = spawnPoints[index].GetLocation(
4858 telehub.AbsolutePosition,
4859 telehub.GroupRotation
4860 );
4861 // SpawnPoint sp = spawnPoints[index];
4862 6101
4863 ILandObject land = m_scene.LandChannel.GetLandObject(spawnPosition.X, spawnPosition.Y); 6102 switch(m_scene.SpawnPointRouting)
6103 {
6104 case "random":
6105 tries = spawnPoints.Length;
6106 if(tries < 3) // no much sense in random with a few points when there same can have bans
6107 goto case "sequence";
6108 do
6109 {
6110 index = Util.RandomClass.Next(spawnPoints.Length - 1);
4864 6111
4865 if (land == null || land.IsEitherBannedOrRestricted(UUID)) 6112 spawnPosition = spawnPoints[index].GetLocation(teleHubPosition, teleHubRotation);
4866 selected = false; 6113 land = m_scene.LandChannel.GetLandObject(spawnPosition.X,spawnPosition.Y);
4867 else 6114 if(land != null && !land.IsEitherBannedOrRestricted(UUID))
4868 selected = true; 6115 selected = true;
4869 6116
4870 } while ( selected == false); 6117 } while(selected == false && --tries > 0 );
4871 6118
4872 pos = spawnPoints[index].GetLocation( 6119 if(tries <= 0)
4873 telehub.AbsolutePosition, 6120 goto case "sequence";
4874 telehub.GroupRotation
4875 );
4876 return;
4877 6121
4878 case "sequence": 6122 pos = spawnPosition;
6123 return true;
4879 6124
4880 do 6125 case "sequence":
6126 tries = spawnPoints.Length;
6127 selected = false;
6128 validhub = false;
6129 do
6130 {
6131 index = m_scene.SpawnPoint();
6132 spawnPosition = spawnPoints[index].GetLocation(teleHubPosition, teleHubRotation);
6133 land = m_scene.LandChannel.GetLandObject(spawnPosition.X,spawnPosition.Y);
6134 if(land != null)
4881 { 6135 {
4882 index = m_scene.SpawnPoint(); 6136 validhub = true;
4883 6137 if(land.IsEitherBannedOrRestricted(UUID))
4884 Vector3 spawnPosition = spawnPoints[index].GetLocation(
4885 telehub.AbsolutePosition,
4886 telehub.GroupRotation
4887 );
4888 // SpawnPoint sp = spawnPoints[index];
4889
4890 ILandObject land = m_scene.LandChannel.GetLandObject(spawnPosition.X, spawnPosition.Y);
4891 if (land == null || land.IsEitherBannedOrRestricted(UUID))
4892 selected = false; 6138 selected = false;
4893 else 6139 else
4894 selected = true; 6140 selected = true;
6141 }
4895 6142
4896 } while (selected == false); 6143 } while(selected == false && --tries > 0);
4897 6144
4898 pos = spawnPoints[index].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); 6145 if(!validhub)
4899 ; 6146 return false;
4900 return;
4901 6147
4902 default: 6148 pos = spawnPosition;
4903 case "closest":
4904 6149
4905 float distance = 9999; 6150 if(!selected)
4906 int closest = -1; 6151 return false;
4907 6152 positionChanged = true;
4908 for (int i = 0; i < spawnPoints.Length; i++) 6153 return true;
4909 {
4910 Vector3 spawnPosition = spawnPoints[i].GetLocation(
4911 telehub.AbsolutePosition,
4912 telehub.GroupRotation
4913 );
4914 Vector3 offset = spawnPosition - pos;
4915 float d = Vector3.Mag(offset);
4916 if (d >= distance)
4917 continue;
4918 ILandObject land = m_scene.LandChannel.GetLandObject(spawnPosition.X, spawnPosition.Y);
4919 if (land == null)
4920 continue;
4921 if (land.IsEitherBannedOrRestricted(UUID))
4922 continue;
4923 distance = d;
4924 closest = i;
4925 }
4926 if (closest == -1)
4927 return;
4928
4929 pos = spawnPoints[closest].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation);
4930 return;
4931 6154
4932 } 6155 default:
6156 case "closest":
6157 float distancesq = float.MaxValue;
6158 int closest = -1;
6159 validhub = false;
6160
6161 for(int i = 0; i < spawnPoints.Length; i++)
6162 {
6163 spawnPosition = spawnPoints[i].GetLocation(teleHubPosition, teleHubRotation);
6164 Vector3 offset = spawnPosition - pos;
6165 float dsq = offset.LengthSquared();
6166 land = m_scene.LandChannel.GetLandObject(spawnPosition.X,spawnPosition.Y);
6167 if(land == null)
6168 continue;
6169
6170 validhub = true;
6171 if(land.IsEitherBannedOrRestricted(UUID))
6172 continue;
6173
6174 if(dsq >= distancesq)
6175 continue;
6176 distancesq = dsq;
6177 closest = i;
6178 }
6179
6180 if(!validhub)
6181 return false;
6182
6183 if(closest < 0)
6184 {
6185 pos = spawnPoints[0].GetLocation(teleHubPosition, teleHubRotation);
6186 positionChanged = true;
6187 return false;
6188 }
6189
6190 pos = spawnPoints[closest].GetLocation(teleHubPosition, teleHubRotation);
6191 positionChanged = true;
6192 return true;
4933 } 6193 }
4934 } 6194 }
6195 return false;
4935 } 6196 }
4936 6197
6198 const TeleportFlags adicionalLandPointFlags = TeleportFlags.ViaLandmark |
6199 TeleportFlags.ViaLocation | TeleportFlags.ViaHGLogin;
6200
4937 // Modify landing point based on possible banning, telehubs or parcel restrictions. 6201 // Modify landing point based on possible banning, telehubs or parcel restrictions.
4938 private void CheckAndAdjustLandingPoint(ref Vector3 pos) 6202 // This is the behavior in OpenSim for a very long time, different from SL
6203 private bool CheckAndAdjustLandingPoint_OS(ref Vector3 pos, ref Vector3 lookat, ref bool positionChanged)
4939 { 6204 {
4940 string reason; 6205 string reason;
4941 6206
4942 // Honor bans 6207 // Honor bans
4943 if (!m_scene.TestLandRestrictions(UUID, out reason, ref pos.X, ref pos.Y)) 6208 if (!m_scene.TestLandRestrictions(UUID, out reason, ref pos.X, ref pos.Y))
4944 return; 6209 return false;
4945 6210
4946 SceneObjectGroup telehub = null; 6211 SceneObjectGroup telehub = null;
4947 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject)) != null) 6212 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject)) != null)
4948 { 6213 {
4949 if (!m_scene.RegionInfo.EstateSettings.AllowDirectTeleport) 6214 if (!m_scene.RegionInfo.EstateSettings.AllowDirectTeleport)
4950 { 6215 {
4951 CheckAndAdjustTelehub(telehub, ref pos); 6216 CheckAndAdjustTelehub(telehub, ref pos, ref positionChanged);
4952 return; 6217 return true;
4953 } 6218 }
4954 } 6219 }
4955 6220
@@ -4964,27 +6229,84 @@ namespace OpenSim.Region.Framework.Scenes
4964 // to ignore them. 6229 // to ignore them.
4965 if ((m_teleportFlags & (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID)) == 6230 if ((m_teleportFlags & (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID)) ==
4966 (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID) || 6231 (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID) ||
4967 (m_teleportFlags & TeleportFlags.ViaLandmark) != 0 || 6232 (m_teleportFlags & adicionalLandPointFlags) != 0)
4968 (m_teleportFlags & TeleportFlags.ViaLocation) != 0 ||
4969 (m_teleportFlags & Constants.TeleportFlags.ViaHGLogin) != 0)
4970 { 6233 {
4971 // Don't restrict gods, estate managers, or land owners to 6234 // Don't restrict gods, estate managers, or land owners to
4972 // the TP point. This behaviour mimics agni. 6235 // the TP point. This behaviour mimics agni.
4973 if (land.LandData.LandingType == (byte)LandingType.LandingPoint && 6236 if (land.LandData.LandingType == (byte)LandingType.LandingPoint &&
4974 land.LandData.UserLocation != Vector3.Zero && 6237 land.LandData.UserLocation != Vector3.Zero &&
4975 GodLevel < 200 && 6238 !IsViewerUIGod &&
4976 ((land.LandData.OwnerID != m_uuid && 6239 ((land.LandData.OwnerID != m_uuid &&
4977 !m_scene.Permissions.IsGod(m_uuid) && 6240 !m_scene.Permissions.IsGod(m_uuid) &&
4978 !m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_uuid)) || 6241 !m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_uuid)) ||
4979 (m_teleportFlags & TeleportFlags.ViaLocation) != 0 || 6242 (m_teleportFlags & TeleportFlags.ViaLocation) != 0 ||
4980 (m_teleportFlags & Constants.TeleportFlags.ViaHGLogin) != 0)) 6243 (m_teleportFlags & Constants.TeleportFlags.ViaHGLogin) != 0))
4981 { 6244 {
4982 pos = land.LandData.UserLocation; 6245 pos = land.LandData.UserLocation;
6246 positionChanged = true;
4983 } 6247 }
4984 } 6248 }
4985 6249
4986 land.SendLandUpdateToClient(ControllingClient); 6250 land.SendLandUpdateToClient(ControllingClient);
4987 } 6251 }
6252
6253 return true;
6254 }
6255
6256 // Modify landing point based on telehubs or parcel restrictions.
6257 // This is a behavior coming from AVN, somewhat mimicking SL
6258 private bool CheckAndAdjustLandingPoint_SL(ref Vector3 pos, ref Vector3 lookat, ref bool positionChanged)
6259 {
6260 string reason;
6261
6262 // dont mess with gods
6263 if(IsGod)
6264 return true;
6265
6266 // respect region owner and managers
6267// if(m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_uuid))
6268// return true;
6269
6270 if (!m_scene.RegionInfo.EstateSettings.AllowDirectTeleport)
6271 {
6272 SceneObjectGroup telehub = null;
6273 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject)) != null)
6274 {
6275 if(CheckAndAdjustTelehub(telehub, ref pos, ref positionChanged))
6276 return true;
6277 }
6278 }
6279
6280 // Honor bans, actually we don't honour them
6281 if (!m_scene.TestLandRestrictions(UUID, out reason, ref pos.X, ref pos.Y))
6282 return false;
6283
6284 ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
6285 if (land != null)
6286 {
6287 if (Scene.DebugTeleporting)
6288 TeleportFlagsDebug();
6289
6290 // If we come in via login, landmark or map, we want to
6291 // honor landing points. If we come in via Lure, we want
6292 // to ignore them.
6293 if ((m_teleportFlags & (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID)) ==
6294 (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID)
6295 || (m_teleportFlags & adicionalLandPointFlags) != 0)
6296 {
6297 if (land.LandData.LandingType == (byte)LandingType.LandingPoint &&
6298 land.LandData.UserLocation != Vector3.Zero )
6299 // &&
6300 // land.LandData.OwnerID != m_uuid )
6301 {
6302 pos = land.LandData.UserLocation;
6303 if(land.LandData.UserLookAt != Vector3.Zero)
6304 lookat = land.LandData.UserLookAt;
6305 positionChanged = true;
6306 }
6307 }
6308 }
6309 return true;
4988 } 6310 }
4989 6311
4990 private DetectedObject CreateDetObject(SceneObjectPart obj) 6312 private DetectedObject CreateDetObject(SceneObjectPart obj)
@@ -4998,6 +6320,7 @@ namespace OpenSim.Region.Framework.Scenes
4998 detobj.velVector = obj.Velocity; 6320 detobj.velVector = obj.Velocity;
4999 detobj.colliderType = 0; 6321 detobj.colliderType = 0;
5000 detobj.groupUUID = obj.GroupID; 6322 detobj.groupUUID = obj.GroupID;
6323 detobj.linkNumber = 0;
5001 6324
5002 return detobj; 6325 return detobj;
5003 } 6326 }
@@ -5011,8 +6334,13 @@ namespace OpenSim.Region.Framework.Scenes
5011 detobj.posVector = av.AbsolutePosition; 6334 detobj.posVector = av.AbsolutePosition;
5012 detobj.rotQuat = av.Rotation; 6335 detobj.rotQuat = av.Rotation;
5013 detobj.velVector = av.Velocity; 6336 detobj.velVector = av.Velocity;
5014 detobj.colliderType = 0; 6337 detobj.colliderType = av.IsNPC ? 0x20 : 0x1; // OpenSim\Region\ScriptEngine\Shared\Helpers.cs
6338 if(av.IsSatOnObject)
6339 detobj.colliderType |= 0x4; //passive
6340 else if(detobj.velVector != Vector3.Zero)
6341 detobj.colliderType |= 0x2; //active
5015 detobj.groupUUID = av.ControllingClient.ActiveGroupId; 6342 detobj.groupUUID = av.ControllingClient.ActiveGroupId;
6343 detobj.linkNumber = 0;
5016 6344
5017 return detobj; 6345 return detobj;
5018 } 6346 }
@@ -5028,7 +6356,7 @@ namespace OpenSim.Region.Framework.Scenes
5028 detobj.velVector = Vector3.Zero; 6356 detobj.velVector = Vector3.Zero;
5029 detobj.colliderType = 0; 6357 detobj.colliderType = 0;
5030 detobj.groupUUID = UUID.Zero; 6358 detobj.groupUUID = UUID.Zero;
5031 6359 detobj.linkNumber = 0;
5032 return detobj; 6360 return detobj;
5033 } 6361 }
5034 6362
@@ -5095,29 +6423,404 @@ namespace OpenSim.Region.Framework.Scenes
5095 } 6423 }
5096 } 6424 }
5097 6425
6426 private void RaiseCollisionScriptEvents(Dictionary<uint, ContactPoint> coldata)
6427 {
6428 try
6429 {
6430 List<uint> thisHitColliders = new List<uint>();
6431 List<uint> endedColliders = new List<uint>();
6432 List<uint> startedColliders = new List<uint>();
6433
6434 if (coldata.Count == 0)
6435 {
6436 if (m_lastColliders.Count == 0)
6437 return; // nothing to do
6438
6439 foreach (uint localID in m_lastColliders)
6440 {
6441 endedColliders.Add(localID);
6442 }
6443 m_lastColliders.Clear();
6444 }
6445 else
6446 {
6447 List<CollisionForSoundInfo> soundinfolist = new List<CollisionForSoundInfo>();
6448 if(ParcelAllowThisAvatarSounds)
6449 {
6450 CollisionForSoundInfo soundinfo;
6451 ContactPoint curcontact;
6452
6453 foreach (uint id in coldata.Keys)
6454 {
6455 thisHitColliders.Add(id);
6456 if (!m_lastColliders.Contains(id))
6457 {
6458 startedColliders.Add(id);
6459 curcontact = coldata[id];
6460 if (Math.Abs(curcontact.RelativeSpeed) > 0.2)
6461 {
6462 soundinfo = new CollisionForSoundInfo();
6463 soundinfo.colliderID = id;
6464 soundinfo.position = curcontact.Position;
6465 soundinfo.relativeVel = curcontact.RelativeSpeed;
6466 soundinfolist.Add(soundinfo);
6467 }
6468 }
6469 }
6470 }
6471 else
6472 {
6473 foreach (uint id in coldata.Keys)
6474 {
6475 thisHitColliders.Add(id);
6476 if (!m_lastColliders.Contains(id))
6477 startedColliders.Add(id);
6478 }
6479 }
6480 // calculate things that ended colliding
6481 foreach (uint localID in m_lastColliders)
6482 {
6483 if (!thisHitColliders.Contains(localID))
6484 {
6485 endedColliders.Add(localID);
6486 }
6487 }
6488 //add the items that started colliding this time to the last colliders list.
6489 foreach (uint localID in startedColliders)
6490 {
6491 m_lastColliders.Add(localID);
6492 }
6493 // remove things that ended colliding from the last colliders list
6494 foreach (uint localID in endedColliders)
6495 {
6496 m_lastColliders.Remove(localID);
6497 }
6498
6499 if (soundinfolist.Count > 0)
6500 CollisionSounds.AvatarCollisionSound(this, soundinfolist);
6501 }
6502
6503 foreach (SceneObjectGroup att in GetAttachments())
6504 {
6505 SendCollisionEvent(att, scriptEvents.collision_start, startedColliders, m_scene.EventManager.TriggerScriptCollidingStart);
6506 SendCollisionEvent(att, scriptEvents.collision , m_lastColliders , m_scene.EventManager.TriggerScriptColliding);
6507 SendCollisionEvent(att, scriptEvents.collision_end , endedColliders , m_scene.EventManager.TriggerScriptCollidingEnd);
6508
6509 if (startedColliders.Contains(0))
6510 SendLandCollisionEvent(att, scriptEvents.land_collision_start, m_scene.EventManager.TriggerScriptLandCollidingStart);
6511 if (m_lastColliders.Contains(0))
6512 SendLandCollisionEvent(att, scriptEvents.land_collision, m_scene.EventManager.TriggerScriptLandColliding);
6513 if (endedColliders.Contains(0))
6514 SendLandCollisionEvent(att, scriptEvents.land_collision_end, m_scene.EventManager.TriggerScriptLandCollidingEnd);
6515 }
6516 }
6517 catch { }
6518// finally
6519// {
6520// m_collisionEventFlag = false;
6521// }
6522 }
6523
5098 private void TeleportFlagsDebug() { 6524 private void TeleportFlagsDebug() {
5099 6525
5100 // Some temporary debugging help to show all the TeleportFlags we have... 6526 // Some temporary debugging help to show all the TeleportFlags we have...
5101 bool HG = false; 6527 bool HG = false;
5102 if((m_teleportFlags & TeleportFlags.ViaHGLogin) == TeleportFlags.ViaHGLogin) 6528 if((m_teleportFlags & TeleportFlags.ViaHGLogin) == TeleportFlags.ViaHGLogin)
5103 HG = true; 6529 HG = true;
5104 6530
5105 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************"); 6531 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************");
5106 6532
5107 uint i = 0u; 6533 uint i = 0u;
5108 for (int x = 0; x <= 30 ; x++, i = 1u << x) 6534 for (int x = 0; x <= 30 ; x++, i = 1u << x)
5109 { 6535 {
5110 i = 1u << x; 6536 i = 1u << x;
5111 6537
5112 if((m_teleportFlags & (TeleportFlags)i) == (TeleportFlags)i) 6538 if((m_teleportFlags & (TeleportFlags)i) == (TeleportFlags)i)
5113 if (HG == false) 6539 if (HG == false)
5114 m_log.InfoFormat("[SCENE PRESENCE]: Teleport Flags include {0}", ((TeleportFlags) i).ToString()); 6540 m_log.InfoFormat("[SCENE PRESENCE]: Teleport Flags include {0}", ((TeleportFlags) i).ToString());
5115 else 6541 else
5116 m_log.InfoFormat("[SCENE PRESENCE]: HG Teleport Flags include {0}", ((TeleportFlags)i).ToString()); 6542 m_log.InfoFormat("[SCENE PRESENCE]: HG Teleport Flags include {0}", ((TeleportFlags)i).ToString());
5117 } 6543 }
5118 6544
5119 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************"); 6545 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************");
5120 6546
6547 }
6548
6549 private void parcelGodCheck(UUID currentParcelID)
6550 {
6551 List<ScenePresence> allpresences = m_scene.GetScenePresences();
6552
6553 foreach (ScenePresence p in allpresences)
6554 {
6555 if (p.IsDeleted || p.IsChildAgent || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
6556 continue;
6557
6558 if (p.ParcelHideThisAvatar && p.currentParcelUUID != currentParcelID)
6559 {
6560 if (IsViewerUIGod)
6561 p.SendViewTo(this);
6562 else
6563 p.SendKillTo(this);
6564 }
6565 }
6566 }
6567
6568 private void ParcelCrossCheck(UUID currentParcelID,UUID previusParcelID,
6569 bool currentParcelHide, bool previusParcelHide, bool oldhide, bool check)
6570 {
6571 List<ScenePresence> killsToSendto = new List<ScenePresence>();
6572 List<ScenePresence> killsToSendme = new List<ScenePresence>();
6573 List<ScenePresence> viewsToSendto = new List<ScenePresence>();
6574 List<ScenePresence> viewsToSendme = new List<ScenePresence>();
6575 List<ScenePresence> allpresences = null;
6576
6577 if (IsInTransit || IsChildAgent)
6578 return;
6579
6580 if (check)
6581 {
6582 // check is relative to current parcel only
6583 if (oldhide == currentParcelHide)
6584 return;
6585
6586 allpresences = m_scene.GetScenePresences();
6587
6588 if (oldhide)
6589 { // where private
6590 foreach (ScenePresence p in allpresences)
6591 {
6592 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
6593 continue;
6594
6595 // those on not on parcel see me
6596 if (currentParcelID != p.currentParcelUUID)
6597 {
6598 viewsToSendto.Add(p); // they see me
6599 }
6600 }
6601 } // where private end
6602
6603 else
6604 { // where public
6605 foreach (ScenePresence p in allpresences)
6606 {
6607 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
6608 continue;
6609
6610 // those not on parcel dont see me
6611 if (currentParcelID != p.currentParcelUUID && !p.IsViewerUIGod)
6612 {
6613 killsToSendto.Add(p); // they dont see me
6614 }
6615 }
6616 } // where public end
6617
6618 allpresences.Clear();
6619 }
6620 else
6621 {
6622 if (currentParcelHide)
6623 {
6624 // now on a private parcel
6625 allpresences = m_scene.GetScenePresences();
6626
6627 if (previusParcelHide && previusParcelID != UUID.Zero)
6628 {
6629 foreach (ScenePresence p in allpresences)
6630 {
6631 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
6632 continue;
6633
6634 // only those on previus parcel need receive kills
6635 if (previusParcelID == p.currentParcelUUID)
6636 {
6637 if(!p.IsViewerUIGod)
6638 killsToSendto.Add(p); // they dont see me
6639 if(!IsViewerUIGod)
6640 killsToSendme.Add(p); // i dont see them
6641 }
6642 // only those on new parcel need see
6643 if (currentParcelID == p.currentParcelUUID)
6644 {
6645 viewsToSendto.Add(p); // they see me
6646 viewsToSendme.Add(p); // i see them
6647 }
6648 }
6649 }
6650 else
6651 {
6652 //was on a public area
6653 allpresences = m_scene.GetScenePresences();
6654
6655 foreach (ScenePresence p in allpresences)
6656 {
6657 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
6658 continue;
6659
6660 // those not on new parcel dont see me
6661 if (currentParcelID != p.currentParcelUUID && !p.IsViewerUIGod)
6662 {
6663 killsToSendto.Add(p); // they dont see me
6664 }
6665 else
6666 {
6667 viewsToSendme.Add(p); // i see those on it
6668 }
6669 }
6670 }
6671 allpresences.Clear();
6672 } // now on a private parcel end
6673
6674 else
6675 {
6676 // now on public parcel
6677 if (previusParcelHide && previusParcelID != UUID.Zero)
6678 {
6679 // was on private area
6680 allpresences = m_scene.GetScenePresences();
6681
6682 foreach (ScenePresence p in allpresences)
6683 {
6684 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
6685 continue;
6686 // only those old parcel need kills
6687 if (previusParcelID == p.currentParcelUUID && !IsViewerUIGod)
6688 {
6689 killsToSendme.Add(p); // i dont see them
6690 }
6691 else
6692 {
6693 viewsToSendto.Add(p); // they see me
6694 }
6695 }
6696 }
6697 else
6698 return; // was on a public area also
6699 } // now on public parcel end
6700 }
6701
6702 // send the things
6703
6704 if (killsToSendto.Count > 0)
6705 {
6706 foreach (ScenePresence p in killsToSendto)
6707 {
6708// m_log.Debug("[AVATAR]: killTo: " + Lastname + " " + p.Lastname);
6709 SendKillTo(p);
6710 }
6711 }
6712
6713 if (killsToSendme.Count > 0)
6714 {
6715 foreach (ScenePresence p in killsToSendme)
6716 {
6717// m_log.Debug("[AVATAR]: killToMe: " + Lastname + " " + p.Lastname);
6718 p.SendKillTo(this);
6719 }
6720 }
6721
6722 if (viewsToSendto.Count > 0)
6723 {
6724 foreach (ScenePresence p in viewsToSendto)
6725 {
6726 SendViewTo(p);
6727 }
6728 }
6729
6730 if (viewsToSendme.Count > 0 )
6731 {
6732 foreach (ScenePresence p in viewsToSendme)
6733 {
6734 if (p.IsChildAgent)
6735 continue;
6736// m_log.Debug("[AVATAR]: viewMe: " + Lastname + "<-" + p.Lastname);
6737 p.SendViewTo(this);
6738 }
6739 }
6740 }
6741
6742 public void HasMovedAway(bool nearRegion)
6743 {
6744 if (nearRegion)
6745 {
6746 if (Scene.AttachmentsModule != null)
6747 Scene.AttachmentsModule.DeleteAttachmentsFromScene(this, true);
6748
6749 if (!ParcelHideThisAvatar || IsViewerUIGod)
6750 return;
6751
6752 List<ScenePresence> allpresences = m_scene.GetScenePresences();
6753 foreach (ScenePresence p in allpresences)
6754 {
6755 if (p.IsDeleted || p == this || p.IsChildAgent || p.ControllingClient == null || !p.ControllingClient.IsActive)
6756 continue;
6757
6758 if (p.currentParcelUUID == m_currentParcelUUID)
6759 {
6760 p.SendKillTo(this);
6761 }
6762 }
6763 }
6764 else
6765 {
6766 GodController.HasMovedAway();
6767 List<ScenePresence> allpresences = m_scene.GetScenePresences();
6768 foreach (ScenePresence p in allpresences)
6769 {
6770 if (p == this)
6771 continue;
6772 SendKillTo(p);
6773 if (!p.IsChildAgent)
6774 p.SendKillTo(this);
6775 }
6776
6777 if (Scene.AttachmentsModule != null)
6778 Scene.AttachmentsModule.DeleteAttachmentsFromScene(this, true);
6779 }
6780 }
6781
6782
6783// kill with attachs root kills
6784 public void SendKillTo(ScenePresence p)
6785 {
6786 List<uint> ids = new List<uint>(m_attachments.Count + 1);
6787 foreach (SceneObjectGroup sog in m_attachments)
6788 {
6789 ids.Add(sog.RootPart.LocalId);
6790 }
6791
6792 ids.Add(LocalId);
6793 p.ControllingClient.SendKillObject(ids);
6794 }
6795
6796/*
6797// kill with hack
6798 public void SendKillTo(ScenePresence p)
6799 {
6800 foreach (SceneObjectGroup sog in m_attachments)
6801 p.ControllingClient.SendPartFullUpdate(sog.RootPart, LocalId + 1);
6802 p.ControllingClient.SendKillObject(new List<uint> { LocalId });
6803 }
6804*/
6805 public void SendViewTo(ScenePresence p)
6806 {
6807 SendAvatarDataToAgentNF(p);
6808 SendAppearanceToAgent(p);
6809 if (Animator != null)
6810 Animator.SendAnimPackToClient(p.ControllingClient);
6811 SendAttachmentsToAgentNF(p);
6812 }
6813
6814 public void SetAnimationOverride(string animState, UUID animID)
6815 {
6816 Overrides.SetOverride(animState, animID);
6817// Animator.SendAnimPack();
6818 Animator.ForceUpdateMovementAnimations();
6819 }
6820
6821 public UUID GetAnimationOverride(string animState)
6822 {
6823 return Overrides.GetOverriddenAnimation(animState);
5121 } 6824 }
5122 } 6825 }
5123} 6826}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs b/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs
index cae7fe5..e7b09ea 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs
@@ -40,7 +40,7 @@ namespace OpenSim.Region.Framework.Scenes
40 /// Running => PreRemove, Removing 40 /// Running => PreRemove, Removing
41 /// PreRemove => Running, Removing 41 /// PreRemove => Running, Removing
42 /// Removing => Removed 42 /// Removing => Removed
43 /// 43 ///
44 /// All other methods should only see the scene presence in running state - this is the normal operational state 44 /// All other methods should only see the scene presence in running state - this is the normal operational state
45 /// Removed state occurs when the presence has been removed. This is the end state with no exit. 45 /// Removed state occurs when the presence has been removed. This is the end state with no exit.
46 /// </remarks> 46 /// </remarks>
@@ -89,13 +89,13 @@ namespace OpenSim.Region.Framework.Scenes
89 else if (newState == ScenePresenceState.PreRemove && m_state == ScenePresenceState.Running) 89 else if (newState == ScenePresenceState.PreRemove && m_state == ScenePresenceState.Running)
90 transitionOkay = true; 90 transitionOkay = true;
91 else if (newState == ScenePresenceState.Removing) 91 else if (newState == ScenePresenceState.Removing)
92 { 92 {
93 if (m_state == ScenePresenceState.Running || m_state == ScenePresenceState.PreRemove) 93 if (m_state == ScenePresenceState.Running || m_state == ScenePresenceState.PreRemove)
94 transitionOkay = true; 94 transitionOkay = true;
95 } 95 }
96 else if (newState == ScenePresenceState.Removed && m_state == ScenePresenceState.Removing) 96 else if (newState == ScenePresenceState.Removed && m_state == ScenePresenceState.Removing)
97 transitionOkay = true; 97 transitionOkay = true;
98 } 98 }
99 99
100 if (!transitionOkay) 100 if (!transitionOkay)
101 { 101 {
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs
index f45158b..abcb573 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs
@@ -78,7 +78,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
78 List<SceneObjectGroup> coaObjects = coa.Objects; 78 List<SceneObjectGroup> coaObjects = coa.Objects;
79 79
80// m_log.DebugFormat( 80// m_log.DebugFormat(
81// "[COALESCED SCENE OBJECTS SERIALIZER]: Writing {0} objects for coalesced object", 81// "[COALESCED SCENE OBJECTS SERIALIZER]: Writing {0} objects for coalesced object",
82// coaObjects.Count); 82// coaObjects.Count);
83 83
84 // This is weak - we're relying on the set of coalesced objects still being identical 84 // This is weak - we're relying on the set of coalesced objects still being identical
@@ -86,9 +86,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
86 86
87 writer.WriteStartElement("CoalescedObject"); 87 writer.WriteStartElement("CoalescedObject");
88 88
89 writer.WriteAttributeString("x", size.X.ToString()); 89 writer.WriteAttributeString("x", size.X.ToString(Culture.FormatProvider));
90 writer.WriteAttributeString("y", size.Y.ToString()); 90 writer.WriteAttributeString("y", size.Y.ToString(Culture.FormatProvider));
91 writer.WriteAttributeString("z", size.Z.ToString()); 91 writer.WriteAttributeString("z", size.Z.ToString(Culture.FormatProvider));
92 92
93 // Embed the offsets into the group XML 93 // Embed the offsets into the group XML
94 for (int i = 0; i < coaObjects.Count; i++) 94 for (int i = 0; i < coaObjects.Count; i++)
@@ -96,13 +96,13 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
96 SceneObjectGroup obj = coaObjects[i]; 96 SceneObjectGroup obj = coaObjects[i];
97 97
98// m_log.DebugFormat( 98// m_log.DebugFormat(
99// "[COALESCED SCENE OBJECTS SERIALIZER]: Writing offset for object {0}, {1}", 99// "[COALESCED SCENE OBJECTS SERIALIZER]: Writing offset for object {0}, {1}",
100// i, obj.Name); 100// i, obj.Name);
101 101
102 writer.WriteStartElement("SceneObjectGroup"); 102 writer.WriteStartElement("SceneObjectGroup");
103 writer.WriteAttributeString("offsetx", offsets[i].X.ToString()); 103 writer.WriteAttributeString("offsetx", offsets[i].X.ToString(Culture.FormatProvider));
104 writer.WriteAttributeString("offsety", offsets[i].Y.ToString()); 104 writer.WriteAttributeString("offsety", offsets[i].Y.ToString(Culture.FormatProvider));
105 writer.WriteAttributeString("offsetz", offsets[i].Z.ToString()); 105 writer.WriteAttributeString("offsetz", offsets[i].Z.ToString(Culture.FormatProvider));
106 106
107 SceneObjectSerializer.ToOriginalXmlFormat(obj, writer, doScriptStates); 107 SceneObjectSerializer.ToOriginalXmlFormat(obj, writer, doScriptStates);
108 108
@@ -133,12 +133,14 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
133 { 133 {
134 using (XmlTextReader reader = new XmlTextReader(sr)) 134 using (XmlTextReader reader = new XmlTextReader(sr))
135 { 135 {
136 reader.ProhibitDtd = true;
137
136 reader.MoveToContent(); // skip possible xml declaration 138 reader.MoveToContent(); // skip possible xml declaration
137 139
138 if (reader.Name != "CoalescedObject") 140 if (reader.Name != "CoalescedObject")
139 { 141 {
140 // m_log.DebugFormat( 142 // m_log.DebugFormat(
141 // "[COALESCED SCENE OBJECTS SERIALIZER]: TryFromXml() root element was {0} so returning false", 143 // "[COALESCED SCENE OBJECTS SERIALIZER]: TryFromXml() root element was {0} so returning false",
142 // reader.Name); 144 // reader.Name);
143 145
144 return false; 146 return false;
@@ -147,6 +149,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
147 } 149 }
148 150
149 XmlDocument doc = new XmlDocument(); 151 XmlDocument doc = new XmlDocument();
152 doc.XmlResolver=null;
150 doc.LoadXml(xml); 153 doc.LoadXml(xml);
151 XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject"); 154 XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject");
152 if (e == null) 155 if (e == null)
@@ -166,10 +169,10 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
166 } 169 }
167 else 170 else
168 { 171 {
169 // XXX: Possibly we should fail outright here rather than continuing if a particular component of the 172 // XXX: Possibly we should fail outright here rather than continuing if a particular component of the
170 // coalesced object fails to load. 173 // coalesced object fails to load.
171 m_log.WarnFormat( 174 m_log.WarnFormat(
172 "[COALESCED SCENE OBJECTS SERIALIZER]: Deserialization of xml for component {0} failed. Continuing.", 175 "[COALESCED SCENE OBJECTS SERIALIZER]: Deserialization of xml for component {0} failed. Continuing.",
173 i); 176 i);
174 } 177 }
175 178
@@ -178,9 +181,8 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
178 } 181 }
179 catch (Exception e) 182 catch (Exception e)
180 { 183 {
181 m_log.Error("[COALESCED SCENE OBJECTS SERIALIZER]: Deserialization of xml failed "); 184 m_log.Error("[COALESCED SCENE OBJECTS SERIALIZER]: Deserialization of xml failed ", e);
182//// m_log.Error("[COALESCED SCENE OBJECTS SERIALIZER]: Deserialization of xml failed ", e); 185 Util.LogFailedXML("[COALESCED SCENE OBJECTS SERIALIZER]:", xml);
183//// Util.LogFailedXML("[COALESCED SCENE OBJECTS SERIALIZER]:", xml);
184 return false; 186 return false;
185 } 187 }
186 188
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index 1ff788e..c5a3a22 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -63,16 +63,16 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
63 String fixedData = ExternalRepresentationUtils.SanitizeXml(xmlData); 63 String fixedData = ExternalRepresentationUtils.SanitizeXml(xmlData);
64 using (XmlTextReader wrappedReader = new XmlTextReader(fixedData, XmlNodeType.Element, null)) 64 using (XmlTextReader wrappedReader = new XmlTextReader(fixedData, XmlNodeType.Element, null))
65 { 65 {
66 using (XmlReader reader = XmlReader.Create(wrappedReader, new XmlReaderSettings() { IgnoreWhitespace = true, ConformanceLevel = ConformanceLevel.Fragment })) 66 using (XmlReader reader = XmlReader.Create(wrappedReader, new XmlReaderSettings() { IgnoreWhitespace = true, ConformanceLevel = ConformanceLevel.Fragment, ProhibitDtd = true }))
67 { 67 {
68 try { 68 try
69 {
69 return FromOriginalXmlFormat(reader); 70 return FromOriginalXmlFormat(reader);
70 } 71 }
71 catch (Exception e) 72 catch (Exception e)
72 { 73 {
73 m_log.Error("[SERIALIZER]: Deserialization of xml failed "); 74 m_log.Error("[SERIALIZER]: Deserialization of xml failed ", e);
74//// m_log.Error("[SERIALIZER]: Deserialization of xml failed ", e); 75 Util.LogFailedXML("[SERIALIZER]:", fixedData);
75//// Util.LogFailedXML("[SERIALIZER]:", fixedData);
76 return null; 76 return null;
77 } 77 }
78 } 78 }
@@ -110,12 +110,24 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
110 } 110 }
111 } 111 }
112 while (reader.ReadToNextSibling("Part")); 112 while (reader.ReadToNextSibling("Part"));
113 reader.ReadEndElement();
113 } 114 }
114 115
116 if (reader.Name == "KeyframeMotion" && reader.NodeType == XmlNodeType.Element)
117 {
118
119 string innerkeytxt = reader.ReadElementContentAsString();
120 sceneObject.RootPart.KeyframeMotion =
121 KeyframeMotion.FromData(sceneObject, Convert.FromBase64String(innerkeytxt));
122 }
123 else
124 sceneObject.RootPart.KeyframeMotion = null;
125
115 // Script state may, or may not, exist. Not having any, is NOT 126 // Script state may, or may not, exist. Not having any, is NOT
116 // ever a problem. 127 // ever a problem.
117 sceneObject.LoadScriptState(reader); 128 sceneObject.LoadScriptState(reader);
118 129
130 sceneObject.InvalidateDeepEffectivePerms();
119 return sceneObject; 131 return sceneObject;
120 } 132 }
121 133
@@ -211,9 +223,19 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
211 223
212 writer.WriteEndElement(); // OtherParts 224 writer.WriteEndElement(); // OtherParts
213 225
226 if (sceneObject.RootPart.KeyframeMotion != null)
227 {
228 Byte[] data = sceneObject.RootPart.KeyframeMotion.Serialize();
229
230 writer.WriteStartElement(String.Empty, "KeyframeMotion", String.Empty);
231 writer.WriteBase64(data, 0, data.Length);
232 writer.WriteEndElement();
233 }
234
214 if (doScriptStates) 235 if (doScriptStates)
215 sceneObject.SaveScriptedState(writer); 236 sceneObject.SaveScriptedState(writer);
216 237
238
217 if (!noRootElement) 239 if (!noRootElement)
218 writer.WriteEndElement(); // SceneObjectGroup 240 writer.WriteEndElement(); // SceneObjectGroup
219 241
@@ -233,6 +255,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
233 try 255 try
234 { 256 {
235 XmlDocument doc = new XmlDocument(); 257 XmlDocument doc = new XmlDocument();
258 doc.XmlResolver=null;
236 doc.LoadXml(xmlData); 259 doc.LoadXml(xmlData);
237 260
238 XmlNodeList parts = doc.GetElementsByTagName("SceneObjectPart"); 261 XmlNodeList parts = doc.GetElementsByTagName("SceneObjectPart");
@@ -244,18 +267,28 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
244 return null; 267 return null;
245 } 268 }
246 269
247 StringReader sr = new StringReader(parts[0].OuterXml); 270 SceneObjectGroup sceneObject;
248 XmlTextReader reader = new XmlTextReader(sr); 271 using(StringReader sr = new StringReader(parts[0].OuterXml))
249 SceneObjectGroup sceneObject = new SceneObjectGroup(SceneObjectPart.FromXml(reader)); 272 {
250 reader.Close(); 273 using(XmlTextReader reader = new XmlTextReader(sr))
251 sr.Close(); 274 {
275 reader.ProhibitDtd = true;
276
277 sceneObject = new SceneObjectGroup(SceneObjectPart.FromXml(reader));
278 }
279 }
252 280
253 // Then deal with the rest 281 // Then deal with the rest
282 SceneObjectPart part;
254 for (int i = 1; i < parts.Count; i++) 283 for (int i = 1; i < parts.Count; i++)
255 { 284 {
256 sr = new StringReader(parts[i].OuterXml); 285 using(StringReader sr = new StringReader(parts[i].OuterXml))
257 reader = new XmlTextReader(sr); 286 {
258 SceneObjectPart part = SceneObjectPart.FromXml(reader); 287 using(XmlTextReader reader = new XmlTextReader(sr))
288 {
289 part = SceneObjectPart.FromXml(reader);
290 }
291 }
259 292
260 int originalLinkNum = part.LinkNum; 293 int originalLinkNum = part.LinkNum;
261 294
@@ -266,8 +299,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
266 if (originalLinkNum != 0) 299 if (originalLinkNum != 0)
267 part.LinkNum = originalLinkNum; 300 part.LinkNum = originalLinkNum;
268 301
269 reader.Close();
270 sr.Close();
271 } 302 }
272 303
273 XmlNodeList keymotion = doc.GetElementsByTagName("KeyframeMotion"); 304 XmlNodeList keymotion = doc.GetElementsByTagName("KeyframeMotion");
@@ -279,14 +310,13 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
279 // Script state may, or may not, exist. Not having any, is NOT 310 // Script state may, or may not, exist. Not having any, is NOT
280 // ever a problem. 311 // ever a problem.
281 sceneObject.LoadScriptState(doc); 312 sceneObject.LoadScriptState(doc);
282 313// sceneObject.AggregatePerms();
283 return sceneObject; 314 return sceneObject;
284 } 315 }
285 catch (Exception e) 316 catch (Exception e)
286 { 317 {
287 m_log.Error("[SERIALIZER]: Deserialization of xml failed "); 318 m_log.Error("[SERIALIZER]: Deserialization of xml failed ", e);
288//// m_log.Error("[SERIALIZER]: Deserialization of xml failed ", e); 319 Util.LogFailedXML("[SERIALIZER]:", xmlData);
289//// Util.LogFailedXML("[SERIALIZER]:", xmlData);
290 return null; 320 return null;
291 } 321 }
292 } 322 }
@@ -309,7 +339,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
309 } 339 }
310 } 340 }
311 341
312
313 /// <summary> 342 /// <summary>
314 /// Modifies a SceneObjectGroup. 343 /// Modifies a SceneObjectGroup.
315 /// </summary> 344 /// </summary>
@@ -330,7 +359,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
330 CoalescedSceneObjects coa = null; 359 CoalescedSceneObjects coa = null;
331 360
332 string xmlData = ExternalRepresentationUtils.SanitizeXml(Utils.BytesToString(data)); 361 string xmlData = ExternalRepresentationUtils.SanitizeXml(Utils.BytesToString(data));
333
334 if (CoalescedSceneObjectsSerializer.TryFromXml(xmlData, out coa)) 362 if (CoalescedSceneObjectsSerializer.TryFromXml(xmlData, out coa))
335 { 363 {
336 // m_log.DebugFormat("[SERIALIZER]: Loaded coalescence {0} has {1} objects", assetId, coa.Count); 364 // m_log.DebugFormat("[SERIALIZER]: Loaded coalescence {0} has {1} objects", assetId, coa.Count);
@@ -376,7 +404,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
376 return data; 404 return data;
377 } 405 }
378 406
379
380 #region manual serialization 407 #region manual serialization
381 408
382 private static Dictionary<string, Action<SceneObjectPart, XmlReader>> m_SOPXmlProcessors 409 private static Dictionary<string, Action<SceneObjectPart, XmlReader>> m_SOPXmlProcessors
@@ -433,6 +460,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
433 m_SOPXmlProcessors.Add("GroupID", ProcessGroupID); 460 m_SOPXmlProcessors.Add("GroupID", ProcessGroupID);
434 m_SOPXmlProcessors.Add("OwnerID", ProcessOwnerID); 461 m_SOPXmlProcessors.Add("OwnerID", ProcessOwnerID);
435 m_SOPXmlProcessors.Add("LastOwnerID", ProcessLastOwnerID); 462 m_SOPXmlProcessors.Add("LastOwnerID", ProcessLastOwnerID);
463 m_SOPXmlProcessors.Add("RezzerID", ProcessRezzerID);
436 m_SOPXmlProcessors.Add("BaseMask", ProcessBaseMask); 464 m_SOPXmlProcessors.Add("BaseMask", ProcessBaseMask);
437 m_SOPXmlProcessors.Add("OwnerMask", ProcessOwnerMask); 465 m_SOPXmlProcessors.Add("OwnerMask", ProcessOwnerMask);
438 m_SOPXmlProcessors.Add("GroupMask", ProcessGroupMask); 466 m_SOPXmlProcessors.Add("GroupMask", ProcessGroupMask);
@@ -452,11 +480,29 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
452 m_SOPXmlProcessors.Add("PayPrice3", ProcessPayPrice3); 480 m_SOPXmlProcessors.Add("PayPrice3", ProcessPayPrice3);
453 m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4); 481 m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4);
454 482
483 m_SOPXmlProcessors.Add("Buoyancy", ProcessBuoyancy);
484 m_SOPXmlProcessors.Add("Force", ProcessForce);
485 m_SOPXmlProcessors.Add("Torque", ProcessTorque);
486 m_SOPXmlProcessors.Add("VolumeDetectActive", ProcessVolumeDetectActive);
487
488 m_SOPXmlProcessors.Add("Vehicle", ProcessVehicle);
489
490 m_SOPXmlProcessors.Add("PhysicsInertia", ProcessPhysicsInertia);
491
492 m_SOPXmlProcessors.Add("RotationAxisLocks", ProcessRotationAxisLocks);
455 m_SOPXmlProcessors.Add("PhysicsShapeType", ProcessPhysicsShapeType); 493 m_SOPXmlProcessors.Add("PhysicsShapeType", ProcessPhysicsShapeType);
456 m_SOPXmlProcessors.Add("Density", ProcessDensity); 494 m_SOPXmlProcessors.Add("Density", ProcessDensity);
457 m_SOPXmlProcessors.Add("Friction", ProcessFriction); 495 m_SOPXmlProcessors.Add("Friction", ProcessFriction);
458 m_SOPXmlProcessors.Add("Bounce", ProcessBounce); 496 m_SOPXmlProcessors.Add("Bounce", ProcessBounce);
459 m_SOPXmlProcessors.Add("GravityModifier", ProcessGravityModifier); 497 m_SOPXmlProcessors.Add("GravityModifier", ProcessGravityModifier);
498 m_SOPXmlProcessors.Add("CameraEyeOffset", ProcessCameraEyeOffset);
499 m_SOPXmlProcessors.Add("CameraAtOffset", ProcessCameraAtOffset);
500
501 m_SOPXmlProcessors.Add("SoundID", ProcessSoundID);
502 m_SOPXmlProcessors.Add("SoundGain", ProcessSoundGain);
503 m_SOPXmlProcessors.Add("SoundFlags", ProcessSoundFlags);
504 m_SOPXmlProcessors.Add("SoundRadius", ProcessSoundRadius);
505 m_SOPXmlProcessors.Add("SoundQueueing", ProcessSoundQueueing);
460 506
461 #endregion 507 #endregion
462 508
@@ -686,6 +732,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
686 obj.ClickAction = (byte)reader.ReadElementContentAsInt("ClickAction", String.Empty); 732 obj.ClickAction = (byte)reader.ReadElementContentAsInt("ClickAction", String.Empty);
687 } 733 }
688 734
735 private static void ProcessRotationAxisLocks(SceneObjectPart obj, XmlReader reader)
736 {
737 obj.RotationAxisLocks = (byte)reader.ReadElementContentAsInt("RotationAxisLocks", String.Empty);
738 }
739
689 private static void ProcessPhysicsShapeType(SceneObjectPart obj, XmlReader reader) 740 private static void ProcessPhysicsShapeType(SceneObjectPart obj, XmlReader reader)
690 { 741 {
691 obj.PhysicsShapeType = (byte)reader.ReadElementContentAsInt("PhysicsShapeType", String.Empty); 742 obj.PhysicsShapeType = (byte)reader.ReadElementContentAsInt("PhysicsShapeType", String.Empty);
@@ -711,6 +762,75 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
711 obj.GravityModifier = reader.ReadElementContentAsFloat("GravityModifier", String.Empty); 762 obj.GravityModifier = reader.ReadElementContentAsFloat("GravityModifier", String.Empty);
712 } 763 }
713 764
765 private static void ProcessCameraEyeOffset(SceneObjectPart obj, XmlReader reader)
766 {
767 obj.SetCameraEyeOffset(Util.ReadVector(reader, "CameraEyeOffset"));
768 }
769
770 private static void ProcessCameraAtOffset(SceneObjectPart obj, XmlReader reader)
771 {
772 obj.SetCameraAtOffset(Util.ReadVector(reader, "CameraAtOffset"));
773 }
774
775 private static void ProcessSoundID(SceneObjectPart obj, XmlReader reader)
776 {
777 obj.Sound = Util.ReadUUID(reader, "SoundID");
778 }
779
780 private static void ProcessSoundGain(SceneObjectPart obj, XmlReader reader)
781 {
782 obj.SoundGain = reader.ReadElementContentAsDouble("SoundGain", String.Empty);
783 }
784
785 private static void ProcessSoundFlags(SceneObjectPart obj, XmlReader reader)
786 {
787 obj.SoundFlags = (byte)reader.ReadElementContentAsInt("SoundFlags", String.Empty);
788 }
789
790 private static void ProcessSoundRadius(SceneObjectPart obj, XmlReader reader)
791 {
792 obj.SoundRadius = reader.ReadElementContentAsDouble("SoundRadius", String.Empty);
793 }
794
795 private static void ProcessSoundQueueing(SceneObjectPart obj, XmlReader reader)
796 {
797 obj.SoundQueueing = Util.ReadBoolean(reader);
798 }
799
800 private static void ProcessVehicle(SceneObjectPart obj, XmlReader reader)
801 {
802 SOPVehicle vehicle = SOPVehicle.FromXml2(reader);
803
804 if (vehicle == null)
805 {
806 obj.VehicleParams = null;
807 m_log.DebugFormat(
808 "[SceneObjectSerializer]: Parsing Vehicle for object part {0} {1} encountered errors. Please see earlier log entries.",
809 obj.Name, obj.UUID);
810 }
811 else
812 {
813 obj.VehicleParams = vehicle;
814 }
815 }
816
817 private static void ProcessPhysicsInertia(SceneObjectPart obj, XmlReader reader)
818 {
819 PhysicsInertiaData pdata = PhysicsInertiaData.FromXml2(reader);
820
821 if (pdata == null)
822 {
823 obj.PhysicsInertia = null;
824 m_log.DebugFormat(
825 "[SceneObjectSerializer]: Parsing PhysicsInertiaData for object part {0} {1} encountered errors. Please see earlier log entries.",
826 obj.Name, obj.UUID);
827 }
828 else
829 {
830 obj.PhysicsInertia = pdata;
831 }
832 }
833
714 private static void ProcessShape(SceneObjectPart obj, XmlReader reader) 834 private static void ProcessShape(SceneObjectPart obj, XmlReader reader)
715 { 835 {
716 List<string> errorNodeNames; 836 List<string> errorNodeNames;
@@ -795,6 +915,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
795 obj.LastOwnerID = Util.ReadUUID(reader, "LastOwnerID"); 915 obj.LastOwnerID = Util.ReadUUID(reader, "LastOwnerID");
796 } 916 }
797 917
918 private static void ProcessRezzerID(SceneObjectPart obj, XmlReader reader)
919 {
920 obj.RezzerID = Util.ReadUUID(reader, "RezzerID");
921 }
922
798 private static void ProcessBaseMask(SceneObjectPart obj, XmlReader reader) 923 private static void ProcessBaseMask(SceneObjectPart obj, XmlReader reader)
799 { 924 {
800 obj.BaseMask = (uint)reader.ReadElementContentAsInt("BaseMask", String.Empty); 925 obj.BaseMask = (uint)reader.ReadElementContentAsInt("BaseMask", String.Empty);
@@ -885,6 +1010,25 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
885 obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty); 1010 obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty);
886 } 1011 }
887 1012
1013 private static void ProcessBuoyancy(SceneObjectPart obj, XmlReader reader)
1014 {
1015 obj.Buoyancy = (float)reader.ReadElementContentAsFloat("Buoyancy", String.Empty);
1016 }
1017
1018 private static void ProcessForce(SceneObjectPart obj, XmlReader reader)
1019 {
1020 obj.Force = Util.ReadVector(reader, "Force");
1021 }
1022 private static void ProcessTorque(SceneObjectPart obj, XmlReader reader)
1023 {
1024 obj.Torque = Util.ReadVector(reader, "Torque");
1025 }
1026
1027 private static void ProcessVolumeDetectActive(SceneObjectPart obj, XmlReader reader)
1028 {
1029 obj.VolumeDetectActive = Util.ReadBoolean(reader);
1030 }
1031
888 #endregion 1032 #endregion
889 1033
890 #region TaskInventoryXmlProcessors 1034 #region TaskInventoryXmlProcessors
@@ -1249,8 +1393,27 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1249 1393
1250 private static void ProcessShpMedia(PrimitiveBaseShape shp, XmlReader reader) 1394 private static void ProcessShpMedia(PrimitiveBaseShape shp, XmlReader reader)
1251 { 1395 {
1252 string value = reader.ReadElementContentAsString("Media", String.Empty); 1396 string value = String.Empty;
1253 shp.Media = PrimitiveBaseShape.MediaList.FromXml(value); 1397 try
1398 {
1399 // The STANDARD content of Media elemet is escaped XML string (with &gt; etc).
1400 value = reader.ReadElementContentAsString("Media", String.Empty);
1401 shp.Media = PrimitiveBaseShape.MediaList.FromXml(value);
1402 }
1403 catch (XmlException e)
1404 {
1405 // There are versions of OAR files that contain unquoted XML.
1406 // ie ONE comercial fork that never wanted their oars to be read by our code
1407 try
1408 {
1409 value = reader.ReadInnerXml();
1410 shp.Media = PrimitiveBaseShape.MediaList.FromXml(value);
1411 }
1412 catch
1413 {
1414 m_log.ErrorFormat("[SERIALIZER] Failed parsing halcyon MOAP information");
1415 }
1416 }
1254 } 1417 }
1255 1418
1256 #endregion 1419 #endregion
@@ -1280,6 +1443,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1280 writer.WriteEndElement(); 1443 writer.WriteEndElement();
1281 } 1444 }
1282 1445
1446
1283 writer.WriteEndElement(); 1447 writer.WriteEndElement();
1284 } 1448 }
1285 1449
@@ -1327,10 +1491,10 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1327 writer.WriteElementString("Description", sop.Description); 1491 writer.WriteElementString("Description", sop.Description);
1328 1492
1329 writer.WriteStartElement("Color"); 1493 writer.WriteStartElement("Color");
1330 writer.WriteElementString("R", sop.Color.R.ToString(Utils.EnUsCulture)); 1494 writer.WriteElementString("R", sop.Color.R.ToString(Culture.FormatProvider));
1331 writer.WriteElementString("G", sop.Color.G.ToString(Utils.EnUsCulture)); 1495 writer.WriteElementString("G", sop.Color.G.ToString(Culture.FormatProvider));
1332 writer.WriteElementString("B", sop.Color.B.ToString(Utils.EnUsCulture)); 1496 writer.WriteElementString("B", sop.Color.B.ToString(Culture.FormatProvider));
1333 writer.WriteElementString("A", sop.Color.A.ToString(Utils.EnUsCulture)); 1497 writer.WriteElementString("A", sop.Color.A.ToString(Culture.FormatProvider));
1334 writer.WriteEndElement(); 1498 writer.WriteEndElement();
1335 1499
1336 writer.WriteElementString("Text", sop.Text); 1500 writer.WriteElementString("Text", sop.Text);
@@ -1343,7 +1507,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1343 WriteShape(writer, sop.Shape, options); 1507 WriteShape(writer, sop.Shape, options);
1344 1508
1345 WriteVector(writer, "Scale", sop.Scale); 1509 WriteVector(writer, "Scale", sop.Scale);
1346 WriteQuaternion(writer, "SitTargetOrientation", sop.SitTargetOrientation); 1510 WriteQuaternion(writer, "SitTargetOrientation", sop.SitTargetOrientation);
1347 WriteVector(writer, "SitTargetPosition", sop.SitTargetPosition); 1511 WriteVector(writer, "SitTargetPosition", sop.SitTargetPosition);
1348 WriteVector(writer, "SitTargetPositionLL", sop.SitTargetPositionLL); 1512 WriteVector(writer, "SitTargetPositionLL", sop.SitTargetPositionLL);
1349 WriteQuaternion(writer, "SitTargetOrientationLL", sop.SitTargetOrientationLL); 1513 WriteQuaternion(writer, "SitTargetOrientationLL", sop.SitTargetOrientationLL);
@@ -1363,6 +1527,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1363 UUID lastOwnerID = options.ContainsKey("wipe-owners") ? UUID.Zero : sop.LastOwnerID; 1527 UUID lastOwnerID = options.ContainsKey("wipe-owners") ? UUID.Zero : sop.LastOwnerID;
1364 WriteUUID(writer, "LastOwnerID", lastOwnerID, options); 1528 WriteUUID(writer, "LastOwnerID", lastOwnerID, options);
1365 1529
1530 UUID rezzerID = options.ContainsKey("wipe-owners") ? UUID.Zero : sop.RezzerID;
1531 WriteUUID(writer, "RezzerID", rezzerID, options);
1532
1366 writer.WriteElementString("BaseMask", sop.BaseMask.ToString()); 1533 writer.WriteElementString("BaseMask", sop.BaseMask.ToString());
1367 writer.WriteElementString("OwnerMask", sop.OwnerMask.ToString()); 1534 writer.WriteElementString("OwnerMask", sop.OwnerMask.ToString());
1368 writer.WriteElementString("GroupMask", sop.GroupMask.ToString()); 1535 writer.WriteElementString("GroupMask", sop.GroupMask.ToString());
@@ -1370,7 +1537,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1370 writer.WriteElementString("NextOwnerMask", sop.NextOwnerMask.ToString()); 1537 writer.WriteElementString("NextOwnerMask", sop.NextOwnerMask.ToString());
1371 WriteFlags(writer, "Flags", sop.Flags.ToString(), options); 1538 WriteFlags(writer, "Flags", sop.Flags.ToString(), options);
1372 WriteUUID(writer, "CollisionSound", sop.CollisionSound, options); 1539 WriteUUID(writer, "CollisionSound", sop.CollisionSound, options);
1373 writer.WriteElementString("CollisionSoundVolume", sop.CollisionSoundVolume.ToString()); 1540 writer.WriteElementString("CollisionSoundVolume", sop.CollisionSoundVolume.ToString(Culture.FormatProvider));
1374 if (sop.MediaUrl != null) 1541 if (sop.MediaUrl != null)
1375 writer.WriteElementString("MediaUrl", sop.MediaUrl.ToString()); 1542 writer.WriteElementString("MediaUrl", sop.MediaUrl.ToString());
1376 WriteVector(writer, "AttachedPos", sop.AttachedPos); 1543 WriteVector(writer, "AttachedPos", sop.AttachedPos);
@@ -1390,16 +1557,41 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1390 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString()); 1557 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString());
1391 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString()); 1558 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString());
1392 1559
1393 if(sop.PhysicsShapeType != sop.DefaultPhysicsShapeType()) 1560 writer.WriteElementString("Buoyancy", sop.Buoyancy.ToString(Culture.FormatProvider));
1394 writer.WriteElementString("PhysicsShapeType", sop.PhysicsShapeType.ToString().ToLower()); 1561
1562 WriteVector(writer, "Force", sop.Force);
1563 WriteVector(writer, "Torque", sop.Torque);
1564
1565 writer.WriteElementString("VolumeDetectActive", sop.VolumeDetectActive.ToString().ToLower());
1566
1567 if (sop.VehicleParams != null)
1568 sop.VehicleParams.ToXml2(writer);
1569
1570 if (sop.PhysicsInertia != null)
1571 sop.PhysicsInertia.ToXml2(writer);
1572
1573 if(sop.RotationAxisLocks != 0)
1574 writer.WriteElementString("RotationAxisLocks", sop.RotationAxisLocks.ToString().ToLower());
1575 writer.WriteElementString("PhysicsShapeType", sop.PhysicsShapeType.ToString().ToLower());
1395 if (sop.Density != 1000.0f) 1576 if (sop.Density != 1000.0f)
1396 writer.WriteElementString("Density", sop.Density.ToString().ToLower()); 1577 writer.WriteElementString("Density", sop.Density.ToString(Culture.FormatProvider));
1397 if (sop.Friction != 0.6f) 1578 if (sop.Friction != 0.6f)
1398 writer.WriteElementString("Friction", sop.Friction.ToString().ToLower()); 1579 writer.WriteElementString("Friction", sop.Friction.ToString(Culture.FormatProvider));
1399 if (sop.Restitution != 0.5f) 1580 if (sop.Restitution != 0.5f)
1400 writer.WriteElementString("Bounce", sop.Restitution.ToString().ToLower()); 1581 writer.WriteElementString("Bounce", sop.Restitution.ToString(Culture.FormatProvider));
1401 if (sop.GravityModifier != 1.0f) 1582 if (sop.GravityModifier != 1.0f)
1402 writer.WriteElementString("GravityModifier", sop.GravityModifier.ToString().ToLower()); 1583 writer.WriteElementString("GravityModifier", sop.GravityModifier.ToString(Culture.FormatProvider));
1584 WriteVector(writer, "CameraEyeOffset", sop.GetCameraEyeOffset());
1585 WriteVector(writer, "CameraAtOffset", sop.GetCameraAtOffset());
1586
1587 // if (sop.Sound != UUID.Zero) force it till sop crossing does clear it on child prim
1588 {
1589 WriteUUID(writer, "SoundID", sop.Sound, options);
1590 writer.WriteElementString("SoundGain", sop.SoundGain.ToString(Culture.FormatProvider));
1591 writer.WriteElementString("SoundFlags", sop.SoundFlags.ToString().ToLower());
1592 writer.WriteElementString("SoundRadius", sop.SoundRadius.ToString(Culture.FormatProvider));
1593 }
1594 writer.WriteElementString("SoundQueueing", sop.SoundQueueing.ToString().ToLower());
1403 1595
1404 writer.WriteEndElement(); 1596 writer.WriteEndElement();
1405 } 1597 }
@@ -1417,19 +1609,19 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1417 static void WriteVector(XmlTextWriter writer, string name, Vector3 vec) 1609 static void WriteVector(XmlTextWriter writer, string name, Vector3 vec)
1418 { 1610 {
1419 writer.WriteStartElement(name); 1611 writer.WriteStartElement(name);
1420 writer.WriteElementString("X", vec.X.ToString(Utils.EnUsCulture)); 1612 writer.WriteElementString("X", vec.X.ToString(Culture.FormatProvider));
1421 writer.WriteElementString("Y", vec.Y.ToString(Utils.EnUsCulture)); 1613 writer.WriteElementString("Y", vec.Y.ToString(Culture.FormatProvider));
1422 writer.WriteElementString("Z", vec.Z.ToString(Utils.EnUsCulture)); 1614 writer.WriteElementString("Z", vec.Z.ToString(Culture.FormatProvider));
1423 writer.WriteEndElement(); 1615 writer.WriteEndElement();
1424 } 1616 }
1425 1617
1426 static void WriteQuaternion(XmlTextWriter writer, string name, Quaternion quat) 1618 static void WriteQuaternion(XmlTextWriter writer, string name, Quaternion quat)
1427 { 1619 {
1428 writer.WriteStartElement(name); 1620 writer.WriteStartElement(name);
1429 writer.WriteElementString("X", quat.X.ToString(Utils.EnUsCulture)); 1621 writer.WriteElementString("X", quat.X.ToString(Culture.FormatProvider));
1430 writer.WriteElementString("Y", quat.Y.ToString(Utils.EnUsCulture)); 1622 writer.WriteElementString("Y", quat.Y.ToString(Culture.FormatProvider));
1431 writer.WriteElementString("Z", quat.Z.ToString(Utils.EnUsCulture)); 1623 writer.WriteElementString("Z", quat.Z.ToString(Culture.FormatProvider));
1432 writer.WriteElementString("W", quat.W.ToString(Utils.EnUsCulture)); 1624 writer.WriteElementString("W", quat.W.ToString(Culture.FormatProvider));
1433 writer.WriteEndElement(); 1625 writer.WriteEndElement();
1434 } 1626 }
1435 1627
@@ -1571,22 +1763,22 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1571 // Don't serialize SculptData. It's just a copy of the asset, which can be loaded separately using 'SculptTexture'. 1763 // Don't serialize SculptData. It's just a copy of the asset, which can be loaded separately using 'SculptTexture'.
1572 1764
1573 writer.WriteElementString("FlexiSoftness", shp.FlexiSoftness.ToString()); 1765 writer.WriteElementString("FlexiSoftness", shp.FlexiSoftness.ToString());
1574 writer.WriteElementString("FlexiTension", shp.FlexiTension.ToString()); 1766 writer.WriteElementString("FlexiTension", shp.FlexiTension.ToString(Culture.FormatProvider));
1575 writer.WriteElementString("FlexiDrag", shp.FlexiDrag.ToString()); 1767 writer.WriteElementString("FlexiDrag", shp.FlexiDrag.ToString(Culture.FormatProvider));
1576 writer.WriteElementString("FlexiGravity", shp.FlexiGravity.ToString()); 1768 writer.WriteElementString("FlexiGravity", shp.FlexiGravity.ToString(Culture.FormatProvider));
1577 writer.WriteElementString("FlexiWind", shp.FlexiWind.ToString()); 1769 writer.WriteElementString("FlexiWind", shp.FlexiWind.ToString(Culture.FormatProvider));
1578 writer.WriteElementString("FlexiForceX", shp.FlexiForceX.ToString()); 1770 writer.WriteElementString("FlexiForceX", shp.FlexiForceX.ToString(Culture.FormatProvider));
1579 writer.WriteElementString("FlexiForceY", shp.FlexiForceY.ToString()); 1771 writer.WriteElementString("FlexiForceY", shp.FlexiForceY.ToString(Culture.FormatProvider));
1580 writer.WriteElementString("FlexiForceZ", shp.FlexiForceZ.ToString()); 1772 writer.WriteElementString("FlexiForceZ", shp.FlexiForceZ.ToString(Culture.FormatProvider));
1581 1773
1582 writer.WriteElementString("LightColorR", shp.LightColorR.ToString()); 1774 writer.WriteElementString("LightColorR", shp.LightColorR.ToString(Culture.FormatProvider));
1583 writer.WriteElementString("LightColorG", shp.LightColorG.ToString()); 1775 writer.WriteElementString("LightColorG", shp.LightColorG.ToString(Culture.FormatProvider));
1584 writer.WriteElementString("LightColorB", shp.LightColorB.ToString()); 1776 writer.WriteElementString("LightColorB", shp.LightColorB.ToString(Culture.FormatProvider));
1585 writer.WriteElementString("LightColorA", shp.LightColorA.ToString()); 1777 writer.WriteElementString("LightColorA", shp.LightColorA.ToString(Culture.FormatProvider));
1586 writer.WriteElementString("LightRadius", shp.LightRadius.ToString()); 1778 writer.WriteElementString("LightRadius", shp.LightRadius.ToString(Culture.FormatProvider));
1587 writer.WriteElementString("LightCutoff", shp.LightCutoff.ToString()); 1779 writer.WriteElementString("LightCutoff", shp.LightCutoff.ToString(Culture.FormatProvider));
1588 writer.WriteElementString("LightFalloff", shp.LightFalloff.ToString()); 1780 writer.WriteElementString("LightFalloff", shp.LightFalloff.ToString(Culture.FormatProvider));
1589 writer.WriteElementString("LightIntensity", shp.LightIntensity.ToString()); 1781 writer.WriteElementString("LightIntensity", shp.LightIntensity.ToString(Culture.FormatProvider));
1590 1782
1591 writer.WriteElementString("FlexiEntry", shp.FlexiEntry.ToString().ToLower()); 1783 writer.WriteElementString("FlexiEntry", shp.FlexiEntry.ToString().ToLower());
1592 writer.WriteElementString("LightEntry", shp.LightEntry.ToString().ToLower()); 1784 writer.WriteElementString("LightEntry", shp.LightEntry.ToString().ToLower());
@@ -1619,6 +1811,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1619 1811
1620 reader.ReadEndElement(); // SceneObjectPart 1812 reader.ReadEndElement(); // SceneObjectPart
1621 1813
1814 obj.AggregateInnerPerms();
1622 // m_log.DebugFormat("[SceneObjectSerializer]: parsed SOP {0} {1}", obj.Name, obj.UUID); 1815 // m_log.DebugFormat("[SceneObjectSerializer]: parsed SOP {0} {1}", obj.Name, obj.UUID);
1623 return obj; 1816 return obj;
1624 } 1817 }
@@ -1627,12 +1820,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1627 { 1820 {
1628 TaskInventoryDictionary tinv = new TaskInventoryDictionary(); 1821 TaskInventoryDictionary tinv = new TaskInventoryDictionary();
1629 1822
1630 if (reader.IsEmptyElement)
1631 {
1632 reader.Read();
1633 return tinv;
1634 }
1635
1636 reader.ReadStartElement(name, String.Empty); 1823 reader.ReadStartElement(name, String.Empty);
1637 1824
1638 while (reader.Name == "TaskInventoryItem") 1825 while (reader.Name == "TaskInventoryItem")
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneXmlLoader.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneXmlLoader.cs
index 3c03130..0ebc645 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneXmlLoader.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneXmlLoader.cs
@@ -49,14 +49,18 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
49 public static void LoadPrimsFromXml(Scene scene, string fileName, bool newIDS, Vector3 loadOffset) 49 public static void LoadPrimsFromXml(Scene scene, string fileName, bool newIDS, Vector3 loadOffset)
50 { 50 {
51 XmlDocument doc = new XmlDocument(); 51 XmlDocument doc = new XmlDocument();
52 doc.XmlResolver=null;
52 XmlNode rootNode; 53 XmlNode rootNode;
53 54
54 if (fileName.StartsWith("http:") || File.Exists(fileName)) 55 if (fileName.StartsWith("http:") || File.Exists(fileName))
55 { 56 {
56 XmlTextReader reader = new XmlTextReader(fileName); 57 using(XmlTextReader reader = new XmlTextReader(fileName))
57 reader.WhitespaceHandling = WhitespaceHandling.None; 58 {
58 doc.Load(reader); 59 reader.WhitespaceHandling = WhitespaceHandling.None;
59 reader.Close(); 60 reader.ProhibitDtd = true;
61
62 doc.Load(reader);
63 }
60 rootNode = doc.FirstChild; 64 rootNode = doc.FirstChild;
61 foreach (XmlNode aPrimNode in rootNode.ChildNodes) 65 foreach (XmlNode aPrimNode in rootNode.ChildNodes)
62 { 66 {
@@ -70,6 +74,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
70 //obj.RegenerateFullIDs(); 74 //obj.RegenerateFullIDs();
71 75
72 scene.AddNewSceneObject(obj, true); 76 scene.AddNewSceneObject(obj, true);
77 obj.InvalidateDeepEffectivePerms();
73 } 78 }
74 } 79 }
75 else 80 else
@@ -265,6 +270,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
265 foreach (XmlNode aPrimNode in rootNode.ChildNodes) 270 foreach (XmlNode aPrimNode in rootNode.ChildNodes)
266 { 271 {
267 SceneObjectGroup obj = DeserializeGroupFromXml2(aPrimNode.OuterXml); 272 SceneObjectGroup obj = DeserializeGroupFromXml2(aPrimNode.OuterXml);
273 scene.AddNewSceneObject(obj, true);
268 if (startScripts) 274 if (startScripts)
269 sceneObjects.Add(obj); 275 sceneObjects.Add(obj);
270 } 276 }
diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
index 3effee7..bc440fc 100644..100755
--- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
+++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
@@ -28,6 +28,7 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Timers; 30using System.Timers;
31using System.Threading;
31using OpenMetaverse.Packets; 32using OpenMetaverse.Packets;
32using OpenSim.Framework; 33using OpenSim.Framework;
33using OpenSim.Framework.Monitoring; 34using OpenSim.Framework.Monitoring;
@@ -62,8 +63,10 @@ namespace OpenSim.Region.Framework.Scenes
62 private YourStatsAreWrong handlerStatsIncorrect; 63 private YourStatsAreWrong handlerStatsIncorrect;
63 64
64 // Determines the size of the array that is used to collect StatBlocks 65 // Determines the size of the array that is used to collect StatBlocks
65 // for sending to the SimStats and SimExtraStatsCollector 66 // for sending viewer compatible stats must be conform with sb array filling below
66 private const int m_statisticArraySize = 28; 67 private const int m_statisticViewerArraySize = 38;
68 // size of LastReportedSimFPS with extra stats.
69 private const int m_statisticExtraArraySize = (int)(Stats.SimExtraCountEnd - Stats.SimExtraCountStart);
67 70
68 /// <summary> 71 /// <summary>
69 /// These are the IDs of stats sent in the StatsPacket to the viewer. 72 /// These are the IDs of stats sent in the StatsPacket to the viewer.
@@ -74,6 +77,7 @@ namespace OpenSim.Region.Framework.Scenes
74 /// </remarks> 77 /// </remarks>
75 public enum Stats : uint 78 public enum Stats : uint
76 { 79 {
80// viewers defined IDs
77 TimeDilation = 0, 81 TimeDilation = 0,
78 SimFPS = 1, 82 SimFPS = 1,
79 PhysicsFPS = 2, 83 PhysicsFPS = 2,
@@ -90,7 +94,7 @@ namespace OpenSim.Region.Framework.Scenes
90 Agents = 13, 94 Agents = 13,
91 ChildAgents = 14, 95 ChildAgents = 14,
92 ActiveScripts = 15, 96 ActiveScripts = 15,
93 ScriptLinesPerSecond = 16, 97 LSLScriptLinesPerSecond = 16, // viewers don't like this anymore
94 InPacketsPerSecond = 17, 98 InPacketsPerSecond = 17,
95 OutPacketsPerSecond = 18, 99 OutPacketsPerSecond = 18,
96 PendingDownloads = 19, 100 PendingDownloads = 19,
@@ -109,11 +113,24 @@ namespace OpenSim.Region.Framework.Scenes
109 SimSpareMs = 32, 113 SimSpareMs = 32,
110 SimSleepMs = 33, 114 SimSleepMs = 33,
111 SimIoPumpTime = 34, 115 SimIoPumpTime = 34,
112 FrameDilation = 35, 116 SimPCTSscriptsRun = 35,
113 UsersLoggingIn = 36, 117 SimRegionIdle = 36, // dataserver only
114 TotalGeoPrim = 37, 118 SimRegionIdlePossible = 37, // dataserver only
115 TotalMesh = 38, 119 SimAIStepTimeMS = 38,
116 ThreadCount = 39 120 SimSkippedSillouet_PS = 39,
121 SimSkippedCharsPerC = 40,
122
123// extra stats IDs irrelevant, just far from viewer defined ones
124 SimExtraCountStart = 1000,
125
126 internalLSLScriptLinesPerSecond = 1000,
127 FrameDilation2 = 1001,
128 UsersLoggingIn = 1002,
129 TotalGeoPrim = 1003,
130 TotalMesh = 1004,
131 ThreadCount = 1005,
132
133 SimExtraCountEnd = 1006
117 } 134 }
118 135
119 /// <summary> 136 /// <summary>
@@ -158,19 +175,14 @@ namespace OpenSim.Region.Framework.Scenes
158 175
159 // Sending a stats update every 3 seconds- 176 // Sending a stats update every 3 seconds-
160 private int m_statsUpdatesEveryMS = 3000; 177 private int m_statsUpdatesEveryMS = 3000;
161 private float m_statsUpdateFactor; 178 private double m_lastUpdateTS;
179 private double m_prevFrameStatsTS;
180 private double m_FrameStatsTS;
162 private float m_timeDilation; 181 private float m_timeDilation;
163 private int m_fps; 182 private int m_fps;
164 183
165 /// <summary> 184 private object m_statsLock = new object();
166 /// Number of the last frame on which we processed a stats udpate. 185 private object m_statsFrameLock = new object();
167 /// </summary>
168 private uint m_lastUpdateFrame;
169
170 /// <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 186
175 /// <summary> 187 /// <summary>
176 /// Parameter to adjust reported scene fps 188 /// Parameter to adjust reported scene fps
@@ -186,10 +198,10 @@ namespace OpenSim.Region.Framework.Scenes
186 /// corresponding, with default heartbeat rate, to a value of 5. 198 /// corresponding, with default heartbeat rate, to a value of 5.
187 /// </remarks> 199 /// </remarks>
188 private float m_statisticsFPSfactor = 5.0f; 200 private float m_statisticsFPSfactor = 5.0f;
189 201 private float m_targetFrameTime = 0.1f;
190 // saved last reported value so there is something available for llGetRegionFPS 202 // saved last reported value so there is something available for llGetRegionFPS
191 private float lastReportedSimFPS; 203 private float lastReportedSimFPS;
192 private float[] lastReportedSimStats = new float[m_statisticArraySize]; 204 private float[] lastReportedSimStats = new float[m_statisticExtraArraySize + m_statisticViewerArraySize];
193 private float m_pfps; 205 private float m_pfps;
194 206
195 /// <summary> 207 /// <summary>
@@ -202,14 +214,15 @@ namespace OpenSim.Region.Framework.Scenes
202 /// </summary> 214 /// </summary>
203 private int m_objectUpdates; 215 private int m_objectUpdates;
204 216
205 private int m_frameMS; 217 private float m_frameMS;
206 private int m_spareMS; 218
207 private int m_netMS; 219 private float m_netMS;
208 private int m_agentMS; 220 private float m_agentMS;
209 private int m_physicsMS; 221 private float m_physicsMS;
210 private int m_imageMS; 222 private float m_imageMS;
211 private int m_otherMS; 223 private float m_otherMS;
212 private int m_scriptMS; 224 private float m_sleeptimeMS;
225 private float m_scriptTimeMS;
213 226
214 private int m_rootAgents; 227 private int m_rootAgents;
215 private int m_childAgents; 228 private int m_childAgents;
@@ -224,31 +237,11 @@ namespace OpenSim.Region.Framework.Scenes
224 private int m_pendingUploads = 0; // FIXME: Not currently filled in 237 private int m_pendingUploads = 0; // FIXME: Not currently filled in
225 private int m_activeScripts; 238 private int m_activeScripts;
226 private int m_scriptLinesPerSecond; 239 private int m_scriptLinesPerSecond;
240 private int m_scriptEventsPerSecond;
227 241
228 private int m_objectCapacity = 45000; 242 private int m_objectCapacity = 45000;
229 243
230 // This is the number of frames that will be stored and then averaged for 244 // The current number of users attempting to login to the region
231 // the Total, Simulation, Physics, and Network Frame Time; It is set to
232 // 10 by default but can be changed by the OpenSim.ini configuration file
233 // NumberOfFrames parameter
234 private int m_numberFramesStored;
235
236 // The arrays that will hold the time it took to run the past N frames,
237 // where N is the num_frames_to_average given by the configuration file
238 private double[] m_totalFrameTimeMilliseconds;
239 private double[] m_simulationFrameTimeMilliseconds;
240 private double[] m_physicsFrameTimeMilliseconds;
241 private double[] m_networkFrameTimeMilliseconds;
242
243 // The location of the next time in milliseconds that will be
244 // (over)written when the next frame completes
245 private int m_nextLocation = 0;
246
247 // The correct number of frames that have completed since the last stats
248 // update for physics
249 private int m_numberPhysicsFrames;
250
251 // The current number of users attempting to login to the region
252 private int m_usersLoggingIn; 245 private int m_usersLoggingIn;
253 246
254 // The last reported value of threads from the SmartThreadPool inside of 247 // The last reported value of threads from the SmartThreadPool inside of
@@ -259,51 +252,39 @@ namespace OpenSim.Region.Framework.Scenes
259 252
260 private RegionInfo ReportingRegion; 253 private RegionInfo ReportingRegion;
261 254
262 private Timer m_report = new Timer(); 255 private System.Timers.Timer m_report = new System.Timers.Timer();
263 256
264 private IEstateModule estateModule; 257 private IEstateModule estateModule;
265 258
266 public SimStatsReporter(Scene scene) 259 public SimStatsReporter(Scene scene)
267 : this(scene, Scene.m_defaultNumberFramesStored)
268 { 260 {
269 }
270
271 public SimStatsReporter(Scene scene, int numberOfFrames)
272 {
273 // Store the number of frames from the OpenSim.ini configuration file
274 m_numberFramesStored = numberOfFrames;
275
276 // Initialize the different frame time arrays to the correct sizes
277 m_totalFrameTimeMilliseconds = new double[m_numberFramesStored];
278 m_simulationFrameTimeMilliseconds = new double[m_numberFramesStored];
279 m_physicsFrameTimeMilliseconds = new double[m_numberFramesStored];
280 m_networkFrameTimeMilliseconds = new double[m_numberFramesStored];
281
282 // Initialize the current number of users logging into the region
283 m_usersLoggingIn = 0;
284
285 m_scene = scene; 261 m_scene = scene;
286 262
287 m_statsUpdateFactor = (float)(m_statsUpdatesEveryMS / 1000);
288 ReportingRegion = scene.RegionInfo; 263 ReportingRegion = scene.RegionInfo;
289 264
290 if(scene.Normalized55FPS) 265 if(scene.Normalized55FPS)
291 m_statisticsFPSfactor = 55.0f * m_scene.MinFrameTicks / 1000.0f; 266 m_statisticsFPSfactor = 55.0f * m_scene.FrameTime;
292 else 267 else
293 m_statisticsFPSfactor = 1.0f; 268 m_statisticsFPSfactor = 1.0f;
294 269
270 m_targetFrameTime = 1000.0f * m_scene.FrameTime / m_statisticsFPSfactor;
271
295 m_objectCapacity = scene.RegionInfo.ObjectCapacity; 272 m_objectCapacity = scene.RegionInfo.ObjectCapacity;
296 m_report.AutoReset = true; 273 m_report.AutoReset = true;
297 m_report.Interval = m_statsUpdatesEveryMS; 274 m_report.Interval = m_statsUpdatesEveryMS;
298 m_report.Elapsed += TriggerStatsHeartbeat; 275 m_report.Elapsed += TriggerStatsHeartbeat;
299 m_report.Enabled = true; 276 m_report.Enabled = true;
300 277
278 m_lastUpdateTS = Util.GetTimeStampMS();
279 m_FrameStatsTS = m_lastUpdateTS;
280 m_prevFrameStatsTS = m_lastUpdateTS;
281
301 if (StatsManager.SimExtraStats != null) 282 if (StatsManager.SimExtraStats != null)
302 OnSendStatsResult += StatsManager.SimExtraStats.ReceiveClassicSimStatsPacket; 283 OnSendStatsResult += StatsManager.SimExtraStats.ReceiveClassicSimStatsPacket;
303 284
304 /// At the moment, we'll only report if a frame is over 120% of target, since commonly frames are a bit 285 /// At the moment, we'll only report if a frame is over 120% of target, since commonly frames are a bit
305 /// longer than ideal (which in itself is a concern). 286 /// longer than ideal (which in itself is a concern).
306 SlowFramesStatReportThreshold = (int)Math.Ceiling(scene.MinFrameTicks * 1.2); 287 SlowFramesStatReportThreshold = (int)Math.Ceiling(m_scene.FrameTime * 1000 * 1.2);
307 288
308 SlowFramesStat 289 SlowFramesStat
309 = new Stat( 290 = new Stat(
@@ -318,7 +299,6 @@ namespace OpenSim.Region.Framework.Scenes
318 StatVerbosity.Info); 299 StatVerbosity.Info);
319 300
320 StatsManager.RegisterStat(SlowFramesStat); 301 StatsManager.RegisterStat(SlowFramesStat);
321
322 } 302 }
323 303
324 304
@@ -335,7 +315,6 @@ namespace OpenSim.Region.Framework.Scenes
335 public void SetUpdateMS(int ms) 315 public void SetUpdateMS(int ms)
336 { 316 {
337 m_statsUpdatesEveryMS = ms; 317 m_statsUpdatesEveryMS = ms;
338 m_statsUpdateFactor = (float)(m_statsUpdatesEveryMS / 1000);
339 m_report.Interval = m_statsUpdatesEveryMS; 318 m_report.Interval = m_statsUpdatesEveryMS;
340 } 319 }
341 320
@@ -355,29 +334,20 @@ namespace OpenSim.Region.Framework.Scenes
355 334
356 private void statsHeartBeat(object sender, EventArgs e) 335 private void statsHeartBeat(object sender, EventArgs e)
357 { 336 {
358 double totalSumFrameTime; 337 if (!m_scene.Active)
359 double simulationSumFrameTime;
360 double physicsSumFrameTime;
361 double networkSumFrameTime;
362 float frameDilation;
363 int currentFrame;
364
365 if (!m_scene.Active)
366 return; 338 return;
367 339
368 // Create arrays to hold the statistics for this current scene, 340 // dont do it if if still been done
369 // these will be passed to the SimExtraStatsCollector, they are also 341
370 // sent to the SimStats class 342 if(Monitor.TryEnter(m_statsLock))
371 SimStatsPacket.StatBlock[] sb = new
372 SimStatsPacket.StatBlock[m_statisticArraySize];
373 SimStatsPacket.RegionBlock rb = new SimStatsPacket.RegionBlock();
374
375 // Know what's not thread safe in Mono... modifying timers.
376 // m_log.Debug("Firing Stats Heart Beat");
377 lock (m_report)
378 { 343 {
344 // m_log.Debug("Firing Stats Heart Beat");
345
346 SimStatsPacket.StatBlock[] sb = new SimStatsPacket.StatBlock[m_statisticViewerArraySize];
347 SimStatsPacket.StatBlock[] sbex = new SimStatsPacket.StatBlock[m_statisticExtraArraySize];
348 SimStatsPacket.RegionBlock rb = new SimStatsPacket.RegionBlock();
379 uint regionFlags = 0; 349 uint regionFlags = 0;
380 350
381 try 351 try
382 { 352 {
383 if (estateModule == null) 353 if (estateModule == null)
@@ -390,22 +360,93 @@ namespace OpenSim.Region.Framework.Scenes
390 } 360 }
391 361
392#region various statistic googly moogly 362#region various statistic googly moogly
363 double timeTmp = m_lastUpdateTS;
364 m_lastUpdateTS = Util.GetTimeStampMS();
365 float updateElapsed = (float)((m_lastUpdateTS - timeTmp)/1000.0);
393 366
394 int reportedFPS = (int)(m_fps * m_statisticsFPSfactor); 367 // factor to consider updates integration time
368 float updateTimeFactor = 1.0f / updateElapsed;
395 369
396 // save the reported value so there is something available for llGetRegionFPS
397 lastReportedSimFPS = reportedFPS / m_statsUpdateFactor;
398 370
399 // ORIGINAL code commented out until we have time to add our own 371 // scene frame stats
400 // statistics to the statistics window 372 float reportedFPS;
401 //float physfps = ((m_pfps / 1000)); 373 float physfps;
402 float physfps = m_numberPhysicsFrames * m_statisticsFPSfactor; 374 float timeDilation;
375 float agentMS;
376 float physicsMS;
377 float otherMS;
378 float sleeptime;
379 float scriptTimeMS;
380 float totalFrameTime;
403 381
404 //if (physfps > 600) 382 float invFrameElapsed;
405 //physfps = physfps - (physfps - 600);
406 383
407 if (physfps < 0) 384 // get a copy under lock and reset
408 physfps = 0; 385 lock(m_statsFrameLock)
386 {
387 timeDilation = m_timeDilation;
388 reportedFPS = m_fps;
389 physfps = m_pfps;
390 agentMS = m_agentMS;
391 physicsMS = m_physicsMS;
392 otherMS = m_otherMS;
393 sleeptime = m_sleeptimeMS;
394 scriptTimeMS = m_scriptTimeMS;
395 totalFrameTime = m_frameMS;
396 // still not inv
397 invFrameElapsed = (float)((m_FrameStatsTS - m_prevFrameStatsTS) / 1000.0);
398
399 ResetFrameStats();
400 }
401
402 if (invFrameElapsed / updateElapsed < 0.8)
403 // scene is in trouble, its account of time is most likely wrong
404 // can even be in stall
405 invFrameElapsed = updateTimeFactor;
406 else
407 invFrameElapsed = 1.0f / invFrameElapsed;
408
409 float perframefactor;
410 if (reportedFPS <= 0)
411 {
412 reportedFPS = 0.0f;
413 physfps = 0.0f;
414 perframefactor = 1.0f;
415 timeDilation = 0.0f;
416 }
417 else
418 {
419 timeDilation /= reportedFPS;
420 reportedFPS *= m_statisticsFPSfactor;
421 perframefactor = 1.0f / (float)reportedFPS;
422 reportedFPS *= invFrameElapsed;
423 physfps *= invFrameElapsed * m_statisticsFPSfactor;
424 }
425
426 // some engines track frame time with error related to the simulation step size
427 if(physfps > reportedFPS)
428 physfps = reportedFPS;
429
430 // save the reported value so there is something available for llGetRegionFPS
431 lastReportedSimFPS = reportedFPS;
432
433 // scale frame stats
434
435 totalFrameTime *= perframefactor;
436 sleeptime *= perframefactor;
437 otherMS *= perframefactor;
438 physicsMS *= perframefactor;
439 agentMS *= perframefactor;
440 scriptTimeMS *= perframefactor;
441
442 // estimate spare time
443 float sparetime;
444 sparetime = m_targetFrameTime - (physicsMS + agentMS + otherMS);
445
446 if (sparetime < 0)
447 sparetime = 0;
448 else if (sparetime > totalFrameTime)
449 sparetime = totalFrameTime;
409 450
410#endregion 451#endregion
411 452
@@ -416,79 +457,28 @@ namespace OpenSim.Region.Framework.Scenes
416 m_numMesh = m_scene.SceneGraph.GetTotalMeshObjectsCount(); 457 m_numMesh = m_scene.SceneGraph.GetTotalMeshObjectsCount();
417 m_activePrim = m_scene.SceneGraph.GetActiveObjectsCount(); 458 m_activePrim = m_scene.SceneGraph.GetActiveObjectsCount();
418 m_activeScripts = m_scene.SceneGraph.GetActiveScriptsCount(); 459 m_activeScripts = m_scene.SceneGraph.GetActiveScriptsCount();
460 m_scriptLinesPerSecond = m_scene.SceneGraph.GetScriptLPS();
419 461
420 // FIXME: Checking for stat sanity is a complex approach. What we really need to do is fix the code 462 // FIXME: Checking for stat sanity is a complex approach. What we really need to do is fix the code
421 // so that stat numbers are always consistent. 463 // so that stat numbers are always consistent.
422 CheckStatSanity(); 464 CheckStatSanity();
423
424 //Our time dilation is 0.91 when we're running a full speed,
425 // therefore to make sure we get an appropriate range,
426 // we have to factor in our error. (0.10f * statsUpdateFactor)
427 // multiplies the fix for the error times the amount of times it'll occur a second
428 // / 10 divides the value by the number of times the sim heartbeat runs (10fps)
429 // Then we divide the whole amount by the amount of seconds pass in between stats updates.
430
431 // 'statsUpdateFactor' is how often stats packets are sent in seconds. Used below to change
432 // values to X-per-second values.
433
434 uint thisFrame = m_scene.Frame;
435 uint numFrames = thisFrame - m_lastUpdateFrame;
436 float framesUpdated = (float)numFrames * m_statisticsFPSfactor;
437 m_lastUpdateFrame = thisFrame;
438
439 // Avoid div-by-zero if somehow we've not updated any frames.
440 if (framesUpdated == 0)
441 framesUpdated = 1;
442
443 for (int i = 0; i < m_statisticArraySize; i++)
444 {
445 sb[i] = new SimStatsPacket.StatBlock();
446 }
447 465
448 // Resetting the sums of the frame times to prevent any errors 466 for (int i = 0; i < m_statisticViewerArraySize; i++)
449 // in calculating the moving average for frame time
450 totalSumFrameTime = 0;
451 simulationSumFrameTime = 0;
452 physicsSumFrameTime = 0;
453 networkSumFrameTime = 0;
454
455 // Loop through all the frames that were stored for the current
456 // heartbeat to process the moving average of frame times
457 for (int i = 0; i < m_numberFramesStored; i++)
458 { 467 {
459 // Sum up each frame time in order to calculate the moving 468 sb[i] = new SimStatsPacket.StatBlock();
460 // average of frame time
461 totalSumFrameTime += m_totalFrameTimeMilliseconds[i];
462 simulationSumFrameTime +=
463 m_simulationFrameTimeMilliseconds[i];
464 physicsSumFrameTime += m_physicsFrameTimeMilliseconds[i];
465 networkSumFrameTime += m_networkFrameTimeMilliseconds[i];
466 } 469 }
467 470
468 // Get the index that represents the current frame based on the next one known; go back
469 // to the last index if next one is stated to restart at 0
470 if (m_nextLocation == 0)
471 currentFrame = m_numberFramesStored - 1;
472 else
473 currentFrame = m_nextLocation - 1;
474
475 // Calculate the frame dilation; which is currently based on the ratio between the sum of the
476 // physics and simulation rate, and the set minimum time to run a scene's frame
477 frameDilation = (float)(m_simulationFrameTimeMilliseconds[currentFrame] +
478 m_physicsFrameTimeMilliseconds[currentFrame]) / m_scene.MinFrameTicks;
479
480 // ORIGINAL code commented out until we have time to add our own
481 sb[0].StatID = (uint) Stats.TimeDilation; 471 sb[0].StatID = (uint) Stats.TimeDilation;
482 sb[0].StatValue = (Single.IsNaN(m_timeDilation)) ? 0.1f : m_timeDilation ; //((((m_timeDilation + (0.10f * statsUpdateFactor)) /10) / statsUpdateFactor)); 472 sb[0].StatValue = (Single.IsNaN(timeDilation)) ? 0.0f : (float)Math.Round(timeDilation,3);
483 473
484 sb[1].StatID = (uint) Stats.SimFPS; 474 sb[1].StatID = (uint) Stats.SimFPS;
485 sb[1].StatValue = reportedFPS / m_statsUpdateFactor; 475 sb[1].StatValue = (float)Math.Round(reportedFPS,1);;
486 476
487 sb[2].StatID = (uint) Stats.PhysicsFPS; 477 sb[2].StatID = (uint) Stats.PhysicsFPS;
488 sb[2].StatValue = physfps / m_statsUpdateFactor; 478 sb[2].StatValue = (float)Math.Round(physfps,1);
489 479
490 sb[3].StatID = (uint) Stats.AgentUpdates; 480 sb[3].StatID = (uint) Stats.AgentUpdates;
491 sb[3].StatValue = (m_agentUpdates / m_statsUpdateFactor); 481 sb[3].StatValue = m_agentUpdates * updateTimeFactor;
492 482
493 sb[4].StatID = (uint) Stats.Agents; 483 sb[4].StatID = (uint) Stats.Agents;
494 sb[4].StatValue = m_rootAgents; 484 sb[4].StatValue = m_rootAgents;
@@ -502,38 +492,32 @@ namespace OpenSim.Region.Framework.Scenes
502 sb[7].StatID = (uint) Stats.ActivePrim; 492 sb[7].StatID = (uint) Stats.ActivePrim;
503 sb[7].StatValue = m_activePrim; 493 sb[7].StatValue = m_activePrim;
504 494
505 // ORIGINAL code commented out until we have time to add our own
506 // statistics to the statistics window
507 sb[8].StatID = (uint)Stats.FrameMS; 495 sb[8].StatID = (uint)Stats.FrameMS;
508 //sb[8].StatValue = m_frameMS / framesUpdated; 496 sb[8].StatValue = totalFrameTime;
509 sb[8].StatValue = (float) totalSumFrameTime / m_numberFramesStored / m_statisticsFPSfactor;
510 497
511 sb[9].StatID = (uint)Stats.NetMS; 498 sb[9].StatID = (uint)Stats.NetMS;
512 //sb[9].StatValue = m_netMS / framesUpdated; 499 sb[9].StatValue = m_netMS * perframefactor;
513 sb[9].StatValue = (float) networkSumFrameTime / m_numberFramesStored / m_statisticsFPSfactor;
514 500
515 sb[10].StatID = (uint)Stats.PhysicsMS; 501 sb[10].StatID = (uint)Stats.PhysicsMS;
516 //sb[10].StatValue = m_physicsMS / framesUpdated; 502 sb[10].StatValue = physicsMS;
517 sb[10].StatValue = (float) physicsSumFrameTime / m_numberFramesStored / m_statisticsFPSfactor;
518 503
519 sb[11].StatID = (uint)Stats.ImageMS ; 504 sb[11].StatID = (uint)Stats.ImageMS ;
520 sb[11].StatValue = m_imageMS / framesUpdated; 505 sb[11].StatValue = m_imageMS * perframefactor;
521 506
522 sb[12].StatID = (uint)Stats.OtherMS; 507 sb[12].StatID = (uint)Stats.OtherMS;
523 //sb[12].StatValue = m_otherMS / framesUpdated; 508 sb[12].StatValue = otherMS;
524 sb[12].StatValue = (float) simulationSumFrameTime / m_numberFramesStored / m_statisticsFPSfactor;
525 509
526 sb[13].StatID = (uint)Stats.InPacketsPerSecond; 510 sb[13].StatID = (uint)Stats.InPacketsPerSecond;
527 sb[13].StatValue = (m_inPacketsPerSecond / m_statsUpdateFactor); 511 sb[13].StatValue = (float)Math.Round(m_inPacketsPerSecond * updateTimeFactor);
528 512
529 sb[14].StatID = (uint)Stats.OutPacketsPerSecond; 513 sb[14].StatID = (uint)Stats.OutPacketsPerSecond;
530 sb[14].StatValue = (m_outPacketsPerSecond / m_statsUpdateFactor); 514 sb[14].StatValue = (float)Math.Round(m_outPacketsPerSecond * updateTimeFactor);
531 515
532 sb[15].StatID = (uint)Stats.UnAckedBytes; 516 sb[15].StatID = (uint)Stats.UnAckedBytes;
533 sb[15].StatValue = m_unAckedBytes; 517 sb[15].StatValue = m_unAckedBytes;
534 518
535 sb[16].StatID = (uint)Stats.AgentMS; 519 sb[16].StatID = (uint)Stats.AgentMS;
536 sb[16].StatValue = m_agentMS / framesUpdated; 520 sb[16].StatValue = agentMS;
537 521
538 sb[17].StatID = (uint)Stats.PendingDownloads; 522 sb[17].StatID = (uint)Stats.PendingDownloads;
539 sb[17].StatValue = m_pendingDownloads; 523 sb[17].StatValue = m_pendingDownloads;
@@ -544,120 +528,155 @@ namespace OpenSim.Region.Framework.Scenes
544 sb[19].StatID = (uint)Stats.ActiveScripts; 528 sb[19].StatID = (uint)Stats.ActiveScripts;
545 sb[19].StatValue = m_activeScripts; 529 sb[19].StatValue = m_activeScripts;
546 530
547 sb[20].StatID = (uint)Stats.ScriptLinesPerSecond; 531 sb[20].StatID = (uint)Stats.SimSleepMs;
548 sb[20].StatValue = m_scriptLinesPerSecond / m_statsUpdateFactor; 532 sb[20].StatValue = sleeptime;
549 533
550 sb[21].StatID = (uint)Stats.SimSpareMs; 534 sb[21].StatID = (uint)Stats.SimSpareMs;
551 sb[21].StatValue = m_spareMS / framesUpdated; 535 sb[21].StatValue = sparetime;
536
537 // this should came from phys engine
538 sb[22].StatID = (uint)Stats.SimPhysicsStepMs;
539 sb[22].StatValue = 20;
540
541 // send the ones we dont have as zeros, to clean viewers state
542 // specially arriving from regions with wrond IDs in use
543
544 sb[23].StatID = (uint)Stats.VirtualSizeKb;
545 sb[23].StatValue = 0;
546
547 sb[24].StatID = (uint)Stats.ResidentSizeKb;
548 sb[24].StatValue = 0;
549
550 sb[25].StatID = (uint)Stats.PendingLocalUploads;
551 sb[25].StatValue = 0;
552 552
553 // Current ratio between the sum of physics and sim rate, and the 553 sb[26].StatID = (uint)Stats.PhysicsPinnedTasks;
554 // minimum time to run a scene's frame 554 sb[26].StatValue = 0;
555 sb[22].StatID = (uint)Stats.FrameDilation;
556 sb[22].StatValue = frameDilation;
557 555
558 // Current number of users currently attemptint to login to region 556 sb[27].StatID = (uint)Stats.PhysicsLodTasks;
559 sb[23].StatID = (uint)Stats.UsersLoggingIn; 557 sb[27].StatValue = 0;
560 sb[23].StatValue = m_usersLoggingIn;
561 558
562 // Total number of geometric primitives in the scene 559 sb[28].StatID = (uint)Stats.ScriptEps; // we actuall have this, but not messing array order AGAIN
563 sb[24].StatID = (uint)Stats.TotalGeoPrim; 560 sb[28].StatValue = (float)Math.Round(m_scriptEventsPerSecond * updateTimeFactor);
564 sb[24].StatValue = m_numGeoPrim;
565 561
566 // Total number of mesh objects in the scene 562 sb[29].StatID = (uint)Stats.SimAIStepTimeMS;
567 sb[25].StatID = (uint)Stats.TotalMesh; 563 sb[29].StatValue = 0;
568 sb[25].StatValue = m_numMesh;
569 564
570 // Current number of threads that XEngine is using 565 sb[30].StatID = (uint)Stats.SimIoPumpTime;
571 sb[26].StatID = (uint)Stats.ThreadCount; 566 sb[30].StatValue = 0;
572 sb[26].StatValue = m_inUseThreads;
573 567
574 sb[27].StatID = (uint)Stats.ScriptMS; 568 sb[31].StatID = (uint)Stats.SimPCTSscriptsRun;
575 sb[27].StatValue = (numFrames <= 0) ? 0 : ((float)m_scriptMS / numFrames); 569 sb[31].StatValue = 0;
576 570
577 for (int i = 0; i < m_statisticArraySize; i++) 571 sb[32].StatID = (uint)Stats.SimRegionIdle;
572 sb[32].StatValue = 0;
573
574 sb[33].StatID = (uint)Stats.SimRegionIdlePossible;
575 sb[33].StatValue = 0;
576
577 sb[34].StatID = (uint)Stats.SimSkippedSillouet_PS;
578 sb[34].StatValue = 0;
579
580 sb[35].StatID = (uint)Stats.SimSkippedCharsPerC;
581 sb[35].StatValue = 0;
582
583 sb[36].StatID = (uint)Stats.SimPhysicsMemory;
584 sb[36].StatValue = 0;
585
586 sb[37].StatID = (uint)Stats.ScriptMS;
587 sb[37].StatValue = scriptTimeMS;
588
589 for (int i = 0; i < m_statisticViewerArraySize; i++)
578 { 590 {
579 lastReportedSimStats[i] = sb[i].StatValue; 591 lastReportedSimStats[i] = sb[i].StatValue;
580 } 592 }
581 593
582 SimStats simStats 594
595 // add extra stats for internal use
596
597 for (int i = 0; i < m_statisticExtraArraySize; i++)
598 {
599 sbex[i] = new SimStatsPacket.StatBlock();
600 }
601
602 sbex[0].StatID = (uint)Stats.LSLScriptLinesPerSecond;
603 sbex[0].StatValue = m_scriptLinesPerSecond * updateTimeFactor;
604 lastReportedSimStats[38] = m_scriptLinesPerSecond * updateTimeFactor;
605
606 sbex[1].StatID = (uint)Stats.FrameDilation2;
607 sbex[1].StatValue = (Single.IsNaN(timeDilation)) ? 0.1f : timeDilation;
608 lastReportedSimStats[39] = (Single.IsNaN(timeDilation)) ? 0.1f : timeDilation;
609
610 sbex[2].StatID = (uint)Stats.UsersLoggingIn;
611 sbex[2].StatValue = m_usersLoggingIn;
612 lastReportedSimStats[40] = m_usersLoggingIn;
613
614 sbex[3].StatID = (uint)Stats.TotalGeoPrim;
615 sbex[3].StatValue = m_numGeoPrim;
616 lastReportedSimStats[41] = m_numGeoPrim;
617
618 sbex[4].StatID = (uint)Stats.TotalMesh;
619 sbex[4].StatValue = m_numMesh;
620 lastReportedSimStats[42] = m_numMesh;
621
622 sbex[5].StatID = (uint)Stats.ThreadCount;
623 sbex[5].StatValue = m_inUseThreads;
624 lastReportedSimStats[43] = m_inUseThreads;
625
626 SimStats simStats
583 = new SimStats( 627 = new SimStats(
584 ReportingRegion.RegionLocX, ReportingRegion.RegionLocY, regionFlags, (uint)m_objectCapacity, 628 ReportingRegion.RegionLocX, ReportingRegion.RegionLocY, regionFlags, (uint)m_objectCapacity,
585 rb, sb, m_scene.RegionInfo.originRegionID); 629 rb, sb, sbex, m_scene.RegionInfo.originRegionID);
586 630
587 handlerSendStatResult = OnSendStatsResult; 631 handlerSendStatResult = OnSendStatsResult;
588 if (handlerSendStatResult != null) 632 if (handlerSendStatResult != null)
589 { 633 {
590 handlerSendStatResult(simStats); 634 handlerSendStatResult(simStats);
591 } 635 }
592 636
593 // Extra statistics that aren't currently sent to clients 637 // Extra statistics that aren't currently sent to clients
594 lock (m_lastReportedExtraSimStats) 638 if (m_scene.PhysicsScene != null)
595 { 639 {
596 m_lastReportedExtraSimStats[LastReportedObjectUpdateStatName] = m_objectUpdates / m_statsUpdateFactor; 640 lock (m_lastReportedExtraSimStats)
597 m_lastReportedExtraSimStats[SlowFramesStat.ShortName] = (float)SlowFramesStat.Value;
598
599 Dictionary<string, float> physicsStats = m_scene.PhysicsScene.GetStats();
600
601 if (physicsStats != null)
602 { 641 {
603 foreach (KeyValuePair<string, float> tuple in physicsStats) 642 m_lastReportedExtraSimStats[LastReportedObjectUpdateStatName] = m_objectUpdates * updateTimeFactor;
643 m_lastReportedExtraSimStats[SlowFramesStat.ShortName] = (float)SlowFramesStat.Value;
644
645 Dictionary<string, float> physicsStats = m_scene.PhysicsScene.GetStats();
646
647 if (physicsStats != null)
604 { 648 {
605 // FIXME: An extremely dirty hack to divide MS stats per frame rather than per second 649 foreach (KeyValuePair<string, float> tuple in physicsStats)
606 // Need to change things so that stats source can indicate whether they are per second or 650 {
607 // per frame. 651 // FIXME: An extremely dirty hack to divide MS stats per frame rather than per second
608 if (tuple.Key.EndsWith("MS")) 652 // Need to change things so that stats source can indicate whether they are per second or
609 m_lastReportedExtraSimStats[tuple.Key] = tuple.Value / framesUpdated; 653 // per frame.
610 else 654 if (tuple.Key.EndsWith("MS"))
611 m_lastReportedExtraSimStats[tuple.Key] = tuple.Value / m_statsUpdateFactor; 655 m_lastReportedExtraSimStats[tuple.Key] = tuple.Value * perframefactor;
656 else
657 m_lastReportedExtraSimStats[tuple.Key] = tuple.Value * updateTimeFactor;
658 }
612 } 659 }
613 } 660 }
614 } 661 }
615 662
663// LastReportedObjectUpdates = m_objectUpdates / m_statsUpdateFactor;
616 ResetValues(); 664 ResetValues();
665 Monitor.Exit(m_statsLock);
617 } 666 }
618 } 667 }
619 668
620 private void ResetValues() 669 private void ResetValues()
621 { 670 {
622 // Reset the number of frames that the physics library has
623 // processed since the last stats report
624 m_numberPhysicsFrames = 0;
625
626 m_timeDilation = 0;
627 m_fps = 0;
628 m_pfps = 0;
629 m_agentUpdates = 0; 671 m_agentUpdates = 0;
630 m_objectUpdates = 0; 672 m_objectUpdates = 0;
631 //m_inPacketsPerSecond = 0;
632 //m_outPacketsPerSecond = 0;
633 m_unAckedBytes = 0; 673 m_unAckedBytes = 0;
634 m_scriptLinesPerSecond = 0; 674 m_scriptEventsPerSecond = 0;
635 675
636 m_frameMS = 0;
637 m_agentMS = 0;
638 m_netMS = 0; 676 m_netMS = 0;
639 m_physicsMS = 0;
640 m_imageMS = 0; 677 m_imageMS = 0;
641 m_otherMS = 0;
642 m_scriptMS = 0;
643 m_spareMS = 0;
644 } 678 }
645 679
646 # region methods called from Scene
647 // The majority of these functions are additive
648 // so that you can easily change the amount of
649 // seconds in between sim stats updates
650
651 public void AddTimeDilation(float td)
652 {
653 //float tdsetting = td;
654 //if (tdsetting > 1.0f)
655 //tdsetting = (tdsetting - (tdsetting - 0.91f));
656
657 //if (tdsetting < 0)
658 //tdsetting = 0.0f;
659 m_timeDilation = td;
660 }
661 680
662 internal void CheckStatSanity() 681 internal void CheckStatSanity()
663 { 682 {
@@ -675,14 +694,44 @@ namespace OpenSim.Region.Framework.Scenes
675 } 694 }
676 } 695 }
677 696
678 public void AddFPS(int frames) 697 # region methods called from Scene
698
699 public void AddFrameStats(float _timeDilation, float _physicsFPS, float _agentMS,
700 float _physicsMS, float _otherMS , float _sleepMS,
701 float _frameMS, float _scriptTimeMS)
679 { 702 {
680 m_fps += frames; 703 lock(m_statsFrameLock)
704 {
705 m_fps++;
706 m_timeDilation += _timeDilation;
707 m_pfps += _physicsFPS;
708 m_agentMS += _agentMS;
709 m_physicsMS += _physicsMS;
710 m_otherMS += _otherMS;
711 m_sleeptimeMS += _sleepMS;
712 m_frameMS += _frameMS;
713 m_scriptTimeMS += _scriptTimeMS;
714
715 if (_frameMS > SlowFramesStatReportThreshold)
716 SlowFramesStat.Value++;
717
718 m_FrameStatsTS = Util.GetTimeStampMS();
719 }
681 } 720 }
682 721
683 public void AddPhysicsFPS(float frames) 722 private void ResetFrameStats()
684 { 723 {
685 m_pfps += frames; 724 m_fps = 0;
725 m_timeDilation = 0.0f;
726 m_pfps = 0.0f;
727 m_agentMS = 0.0f;
728 m_physicsMS = 0.0f;
729 m_otherMS = 0.0f;
730 m_sleeptimeMS = 0.0f;
731 m_frameMS = 0.0f;
732 m_scriptTimeMS = 0.0f;
733
734 m_prevFrameStatsTS = m_FrameStatsTS;
686 } 735 }
687 736
688 public void AddObjectUpdates(int numUpdates) 737 public void AddObjectUpdates(int numUpdates)
@@ -711,77 +760,17 @@ namespace OpenSim.Region.Framework.Scenes
711 if (m_unAckedBytes < 0) m_unAckedBytes = 0; 760 if (m_unAckedBytes < 0) m_unAckedBytes = 0;
712 } 761 }
713 762
714 public void addFrameMS(int ms)
715 {
716 m_frameMS += ms;
717
718 // At the moment, we'll only report if a frame is over 120% of target, since commonly frames are a bit
719 // longer than ideal due to the inaccuracy of the Sleep in Scene.Update() (which in itself is a concern).
720 if (ms > SlowFramesStatReportThreshold)
721 SlowFramesStat.Value++;
722 }
723
724 public void AddSpareMS(int ms)
725 {
726 m_spareMS += ms;
727 }
728 763
729 public void addNetMS(int ms) 764 public void addNetMS(float ms)
730 { 765 {
731 m_netMS += ms; 766 m_netMS += ms;
732 } 767 }
733 768
734 public void addAgentMS(int ms) 769 public void addImageMS(float ms)
735 {
736 m_agentMS += ms;
737 }
738
739 public void addPhysicsMS(int ms)
740 {
741 m_physicsMS += ms;
742 }
743
744 public void addImageMS(int ms)
745 { 770 {
746 m_imageMS += ms; 771 m_imageMS += ms;
747 } 772 }
748 773
749 public void addOtherMS(int ms)
750 {
751 m_otherMS += ms;
752 }
753
754 public void AddScriptMS(int ms)
755 {
756 m_scriptMS += ms;
757 }
758
759 public void addPhysicsFrame(int frames)
760 {
761 // Add the number of physics frames to the correct total physics
762 // frames
763 m_numberPhysicsFrames += frames;
764 }
765
766 public void addFrameTimeMilliseconds(double total, double simulation,
767 double physics, double network)
768 {
769 // Save the frame times from the current frame into the appropriate
770 // arrays
771 m_totalFrameTimeMilliseconds[m_nextLocation] = total;
772 m_simulationFrameTimeMilliseconds[m_nextLocation] = simulation;
773 m_physicsFrameTimeMilliseconds[m_nextLocation] = physics;
774 m_networkFrameTimeMilliseconds[m_nextLocation] = network;
775
776 // Update to the next location in the list
777 m_nextLocation++;
778
779 // Since the list will begin to overwrite the oldest frame values
780 // first, the next location needs to loop back to the beginning of the
781 // list whenever it reaches the end
782 m_nextLocation = m_nextLocation % m_numberFramesStored;
783 }
784
785 public void AddPendingDownloads(int count) 774 public void AddPendingDownloads(int count)
786 { 775 {
787 m_pendingDownloads += count; 776 m_pendingDownloads += count;
@@ -792,9 +781,9 @@ namespace OpenSim.Region.Framework.Scenes
792 //m_log.InfoFormat("[stats]: Adding {0} to pending downloads to make {1}", count, m_pendingDownloads); 781 //m_log.InfoFormat("[stats]: Adding {0} to pending downloads to make {1}", count, m_pendingDownloads);
793 } 782 }
794 783
795 public void addScriptLines(int count) 784 public void addScriptEvents(int count)
796 { 785 {
797 m_scriptLinesPerSecond += count; 786 m_scriptEventsPerSecond += count;
798 } 787 }
799 788
800 public void AddPacketsStats(int inPackets, int outPackets, int unAckedBytes) 789 public void AddPacketsStats(int inPackets, int outPackets, int unAckedBytes)
diff --git a/OpenSim/Region/Framework/Scenes/TerrainChannel.cs b/OpenSim/Region/Framework/Scenes/TerrainChannel.cs
index 3d563a6..20bad94 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 {
@@ -195,13 +196,15 @@ namespace OpenSim.Region.Framework.Scenes
195 // ITerrainChannel.LoadFromXmlString() 196 // ITerrainChannel.LoadFromXmlString()
196 public void LoadFromXmlString(string data) 197 public void LoadFromXmlString(string data)
197 { 198 {
198 StringReader sr = new StringReader(data); 199 using(StringReader sr = new StringReader(data))
199 XmlTextReader reader = new XmlTextReader(sr); 200 {
200 reader.Read(); 201 using(XmlTextReader reader = new XmlTextReader(sr))
202 {
203 reader.ProhibitDtd = true;
201 204
202 ReadXml(reader); 205 ReadXml(reader);
203 reader.Close(); 206 }
204 sr.Close(); 207 }
205 } 208 }
206 209
207 // ITerrainChannel.Merge 210 // ITerrainChannel.Merge
@@ -278,6 +281,148 @@ namespace OpenSim.Region.Framework.Scenes
278 } 281 }
279 } 282 }
280 283
284 /// <summary>
285 /// A new version of terrain merge that processes the terrain in a specific order and corrects the problems with rotated terrains
286 /// having 'holes' in that need to be smoothed. The correct way to rotate something is to iterate over the target, taking data from
287 /// the source, not the other way around. This ensures that the target has no holes in it.
288 /// The processing order of an incoming terrain is:
289 /// 1. Apply rotation
290 /// 2. Apply bounding rectangle
291 /// 3. Apply displacement
292 /// rotationCenter is no longer needed and has been discarded.
293 /// </summary>
294 /// <param name="newTerrain"></param>
295 /// <param name="displacement">&lt;x, y, z&gt;</param>
296 /// <param name="rotationDegrees"></param>
297 /// <param name="boundingOrigin">&lt;x, y&gt;</param>
298 /// <param name="boundingSize">&lt;x, y&gt;</param>
299 public void MergeWithBounding(ITerrainChannel newTerrain, Vector3 displacement, float rotationDegrees, Vector2 boundingOrigin, Vector2 boundingSize)
300 {
301 m_log.DebugFormat("{0} MergeWithBounding: inSize=<{1},{2}>, rot={3}, boundingOrigin={4}, boundingSize={5}, disp={6}, outSize=<{7},{8}>",
302 LogHeader, newTerrain.Width, newTerrain.Height, rotationDegrees, boundingOrigin.ToString(),
303 boundingSize.ToString(), displacement, m_terrainData.SizeX, m_terrainData.SizeY);
304
305 // get the size of the incoming terrain
306 int baseX = newTerrain.Width;
307 int baseY = newTerrain.Height;
308
309 // create an intermediate terrain map that is 25% bigger on each side that we can work with to handle rotation
310 int offsetX = baseX / 4; // the original origin will now be at these coordinates so now we can have imaginary negative coordinates ;)
311 int offsetY = baseY / 4;
312 int tmpX = baseX + baseX / 2;
313 int tmpY = baseY + baseY / 2;
314 int centreX = tmpX / 2;
315 int centreY = tmpY / 2;
316 TerrainData terrain_tmp = new HeightmapTerrainData(tmpX, tmpY, (int)Constants.RegionHeight);
317 for (int xx = 0; xx < tmpX; xx++)
318 for (int yy = 0; yy < tmpY; yy++)
319 terrain_tmp[xx, yy] = -65535f; //use this height like an 'alpha' mask channel
320
321 double radianRotation = Math.PI * rotationDegrees / 180f;
322 double cosR = Math.Cos(radianRotation);
323 double sinR = Math.Sin(radianRotation);
324 if (rotationDegrees < 0f) rotationDegrees += 360f; //-90=270 -180=180 -270=90
325
326 // So first we apply the rotation to the incoming terrain, storing the result in terrain_tmp
327 // We special case orthogonal rotations for accuracy because even using double precision math, Math.Cos(90 degrees) is never fully 0
328 // and we can never rotate around a centre 'pixel' because the 'bitmap' size is always even
329
330 int x, y, sx, sy;
331 for (y = 0; y <= tmpY; y++)
332 {
333 for (x = 0; x <= tmpX; x++)
334 {
335 if (rotationDegrees == 0f)
336 {
337 sx = x - offsetX;
338 sy = y - offsetY;
339 }
340 else if (rotationDegrees == 90f)
341 {
342 sx = y - offsetX;
343 sy = tmpY - 1 - x - offsetY;
344 }
345 else if (rotationDegrees == 180f)
346 {
347 sx = tmpX - 1 - x - offsetX;
348 sy = tmpY - 1 - y - offsetY;
349 }
350 else if (rotationDegrees == 270f)
351 {
352 sx = tmpX - 1 - y - offsetX;
353 sy = x - offsetY;
354 }
355 else
356 {
357 // arbitary rotation: hmmm should I be using (centreX - 0.5) and (centreY - 0.5) and round cosR and sinR to say only 5 decimal places?
358 sx = centreX + (int)Math.Round((((double)x - centreX) * cosR) + (((double)y - centreY) * sinR)) - offsetX;
359 sy = centreY + (int)Math.Round((((double)y - centreY) * cosR) - (((double)x - centreX) * sinR)) - offsetY;
360 }
361
362 if (sx >= 0 && sx < baseX && sy >= 0 && sy < baseY)
363 {
364 try
365 {
366 terrain_tmp[x, y] = (float)newTerrain[sx, sy];
367 }
368 catch (Exception) //just in case we've still not taken care of every way the arrays might go out of bounds! ;)
369 {
370 m_log.DebugFormat("{0} MergeWithBounding - Rotate: Out of Bounds sx={1} sy={2} dx={3} dy={4}", sx, sy, x, y);
371 }
372 }
373 }
374 }
375
376 // We could also incorporate the next steps, bounding-rectangle and displacement in the loop above, but it's simpler to visualise if done separately
377 // and will also make it much easier when later I want the option for maybe a circular or oval bounding shape too ;).
378
379 int newX = m_terrainData.SizeX;
380 int newY = m_terrainData.SizeY;
381 // displacement is relative to <0,0> in the destination region and defines where the origin of the data selected by the bounding-rectangle is placed
382 int dispX = (int)Math.Floor(displacement.X);
383 int dispY = (int)Math.Floor(displacement.Y);
384
385 // startX/Y and endX/Y are coordinates in bitmap_tmp
386 int startX = (int)Math.Floor(boundingOrigin.X) + offsetX;
387 if (startX > tmpX) startX = tmpX;
388 if (startX < 0) startX = 0;
389 int startY = (int)Math.Floor(boundingOrigin.Y) + offsetY;
390 if (startY > tmpY) startY = tmpY;
391 if (startY < 0) startY = 0;
392
393 int endX = (int)Math.Floor(boundingOrigin.X + boundingSize.X) + offsetX;
394 if (endX > tmpX) endX = tmpX;
395 if (endX < 0) endX = 0;
396 int endY = (int)Math.Floor(boundingOrigin.Y + boundingSize.Y) + offsetY;
397 if (endY > tmpY) endY = tmpY;
398 if (endY < 0) endY = 0;
399
400 //m_log.DebugFormat("{0} MergeWithBounding: inSize=<{1},{2}>, disp=<{3},{4}> rot={5}, offset=<{6},{7}>, boundingStart=<{8},{9}>, boundingEnd=<{10},{11}>, cosR={12}, sinR={13}, outSize=<{14},{15}>", LogHeader,
401 // baseX, baseY, dispX, dispY, radianRotation, offsetX, offsetY, startX, startY, endX, endY, cosR, sinR, newX, newY);
402
403 int dx, dy;
404 for (y = startY; y < endY; y++)
405 {
406 for (x = startX; x < endX; x++)
407 {
408 dx = x - startX + dispX;
409 dy = y - startY + dispY;
410 if (dx >= 0 && dx < newX && dy >= 0 && dy < newY)
411 {
412 try
413 {
414 float newHeight = (float)terrain_tmp[x, y]; //use 'alpha' mask
415 if (newHeight != -65535f) m_terrainData[dx, dy] = newHeight + displacement.Z;
416 }
417 catch (Exception) //just in case we've still not taken care of every way the arrays might go out of bounds! ;)
418 {
419 m_log.DebugFormat("{0} MergeWithBounding - Bound & Displace: Out of Bounds sx={1} sy={2} dx={3} dy={4}", x, y, dx, dy);
420 }
421 }
422 }
423 }
424 }
425
281 #endregion 426 #endregion
282 427
283 public TerrainChannel Copy() 428 public TerrainChannel Copy()
@@ -343,7 +488,7 @@ namespace OpenSim.Region.Framework.Scenes
343 int index = 0; 488 int index = 0;
344 489
345 m_terrainData = new HeightmapTerrainData(Height, Width, (int)Constants.RegionHeight); 490 m_terrainData = new HeightmapTerrainData(Height, Width, (int)Constants.RegionHeight);
346 491
347 for (int y = 0; y < Height; y++) 492 for (int y = 0; y < Height; y++)
348 { 493 {
349 for (int x = 0; x < Width; x++) 494 for (int x = 0; x < Width; x++)
@@ -363,8 +508,8 @@ namespace OpenSim.Region.Framework.Scenes
363 public int SizeY; 508 public int SizeY;
364 public int SizeZ; 509 public int SizeZ;
365 public float CompressionFactor; 510 public float CompressionFactor;
366 public int[] Map; 511 public float[] Map;
367 public TerrainChannelXMLPackage(int pX, int pY, int pZ, float pCompressionFactor, int[] pMap) 512 public TerrainChannelXMLPackage(int pX, int pY, int pZ, float pCompressionFactor, float[] pMap)
368 { 513 {
369 Version = 1; 514 Version = 1;
370 SizeX = pX; 515 SizeX = pX;
@@ -395,17 +540,22 @@ namespace OpenSim.Region.Framework.Scenes
395 // Fill the heightmap with the center bump terrain 540 // Fill the heightmap with the center bump terrain
396 private void PinHeadIsland() 541 private void PinHeadIsland()
397 { 542 {
543 float cx = m_terrainData.SizeX * 0.5f;
544 float cy = m_terrainData.SizeY * 0.5f;
545 float h;
398 for (int x = 0; x < Width; x++) 546 for (int x = 0; x < Width; x++)
399 { 547 {
400 for (int y = 0; y < Height; y++) 548 for (int y = 0; y < Height; y++)
401 { 549 {
402 m_terrainData[x, y] = (float)TerrainUtil.PerlinNoise2D(x, y, 2, 0.125) * 10; 550 // 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); 551 h = 1.0f;
404 float spherFacB = (float)(TerrainUtil.SphericalFactor(x, y, m_terrainData.SizeX / 2.0, m_terrainData.SizeY / 2.0, 100) * 0.001d); 552 float spherFacA = (float)(TerrainUtil.SphericalFactor(x, y, cx, cy, 50) * 0.01d);
405 if (m_terrainData[x, y]< spherFacA) 553 float spherFacB = (float)(TerrainUtil.SphericalFactor(x, y, cx, cy, 100) * 0.001d);
406 m_terrainData[x, y]= spherFacA; 554 if (h < spherFacA)
407 if (m_terrainData[x, y]< spherFacB) 555 h = spherFacA;
408 m_terrainData[x, y] = spherFacB; 556 if (h < spherFacB)
557 h = spherFacB;
558 m_terrainData[x, y] = h;
409 } 559 }
410 } 560 }
411 } 561 }
diff --git a/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs b/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs
index fc8f8cd..9d1f815 100644
--- a/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs
+++ b/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs
@@ -27,10 +27,13 @@
27 27
28/* Freely adapted from the Aurora version of the terrain compressor. 28/* Freely adapted from the Aurora version of the terrain compressor.
29 * Copyright (c) Contributors, http://aurora-sim.org/, http://opensimulator.org/ 29 * Copyright (c) Contributors, http://aurora-sim.org/, http://opensimulator.org/
30 * Aurora version created from libOpenMetaverse Library terrain compressor
30 */ 31 */
31 32
32using System; 33using System;
34using System.Collections.Generic;
33using System.Reflection; 35using System.Reflection;
36using System.Diagnostics;
34 37
35using log4net; 38using log4net;
36 39
@@ -45,7 +48,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
45{ 48{
46 public static class OpenSimTerrainCompressor 49 public static class OpenSimTerrainCompressor
47 { 50 {
48// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 51 // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49 52
50#pragma warning disable 414 53#pragma warning disable 414
51 private static string LogHeader = "[TERRAIN COMPRESSOR]"; 54 private static string LogHeader = "[TERRAIN COMPRESSOR]";
@@ -61,47 +64,41 @@ namespace OpenSim.Region.ClientStack.LindenUDP
61 private const int POSITIVE_VALUE = 0x6; 64 private const int POSITIVE_VALUE = 0x6;
62 private const int NEGATIVE_VALUE = 0x7; 65 private const int NEGATIVE_VALUE = 0x7;
63 66
64 private static readonly float[] DequantizeTable16 =
65 new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
66
67 private static readonly float[] DequantizeTable32 =
68 new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
69 67
70 private static readonly float[] CosineTable16 = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 68// private static readonly float[] CosineTable16 = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
71 //private static readonly float[] CosineTable32 = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize]; 69 private static readonly int[] CopyMatrix16 = new int[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
72 private static readonly int[] CopyMatrix16 = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
73 private static readonly int[] CopyMatrix32 = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
74 70
75 private static readonly float[] QuantizeTable16 = 71 private static readonly float[] QuantizeTable16 =
76 new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 72 new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
73 private static readonly float[] DequantizeTable16 =
74 new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
77 75
78 static OpenSimTerrainCompressor() 76 static OpenSimTerrainCompressor()
79 { 77 {
80 // Initialize the decompression tables 78 // Initialize the decompression tables
81 BuildDequantizeTable16(); 79 BuildDequantizeTable16();
82 SetupCosines16(); 80// SetupCosines16();
83 BuildCopyMatrix16(); 81 BuildCopyMatrix16();
84 BuildQuantizeTable16(); 82 BuildQuantizeTable16();
85 } 83 }
86 84
87 // Used to send cloud and wind patches 85 // Used to send cloud and wind patches
88 public static LayerDataPacket CreateLayerDataPacket(TerrainPatch[] patches, byte type, int pRegionSizeX, 86 public static LayerDataPacket CreateLayerDataPacketStandardSize(TerrainPatch[] patches, byte type)
89 int pRegionSizeY)
90 { 87 {
91 LayerDataPacket layer = new LayerDataPacket {LayerID = {Type = type}}; 88 LayerDataPacket layer = new LayerDataPacket { LayerID = { Type = type } };
92 89
93 TerrainPatch.GroupHeader header = new TerrainPatch.GroupHeader 90 TerrainPatch.GroupHeader header = new TerrainPatch.GroupHeader
94 {Stride = STRIDE, PatchSize = Constants.TerrainPatchSize}; 91 { Stride = STRIDE, PatchSize = Constants.TerrainPatchSize };
95 92
96 // Should be enough to fit even the most poorly packed data 93 // Should be enough to fit even the most poorly packed data
97 byte[] data = new byte[patches.Length*Constants.TerrainPatchSize*Constants.TerrainPatchSize*2]; 94 byte[] data = new byte[patches.Length * Constants.TerrainPatchSize * Constants.TerrainPatchSize * 2];
98 BitPack bitpack = new BitPack(data, 0); 95 BitPack bitpack = new BitPack(data, 0);
99 bitpack.PackBits(header.Stride, 16); 96 bitpack.PackBits(header.Stride, 16);
100 bitpack.PackBits(header.PatchSize, 8); 97 bitpack.PackBits(header.PatchSize, 8);
101 bitpack.PackBits(type, 8); 98 bitpack.PackBits(type, 8);
102 99
103 foreach (TerrainPatch t in patches) 100 foreach (TerrainPatch t in patches)
104 CreatePatch(bitpack, t.Data, t.X, t.Y, pRegionSizeX, pRegionSizeY); 101 CreatePatchtStandardSize(bitpack, t.Data, t.X, t.Y);
105 102
106 bitpack.PackBits(END_OF_PATCHES, 8); 103 bitpack.PackBits(END_OF_PATCHES, 8);
107 104
@@ -111,122 +108,131 @@ namespace OpenSim.Region.ClientStack.LindenUDP
111 return layer; 108 return layer;
112 } 109 }
113 110
114 // Create a land packet for a single patch. 111 public static void CreatePatchtStandardSize(BitPack output, float[] patchData, int x, int y)
115 public static LayerDataPacket CreateLandPacket(TerrainData terrData, int patchX, int patchY)
116 { 112 {
117 int[] xPieces = new int[1]; 113 TerrainPatch.Header header = PrescanPatch(patchData);
118 int[] yPieces = new int[1]; 114 header.QuantWBits = 136;
119 xPieces[0] = patchX; // patch X dimension
120 yPieces[0] = patchY;
121 115
122 return CreateLandPacket(terrData, xPieces, yPieces); 116 header.PatchIDs = (y & 0x1F);
117 header.PatchIDs += (x << 5);
118
119 int wbits;
120 int[] patch = CompressPatch(patchData, header, 10, out wbits);
121 EncodePatchHeader(output, header, patch, false, ref wbits);
122 EncodePatch(output, patch, 0, wbits);
123 } 123 }
124 124
125 public static LayerDataPacket CreateLandPacket(TerrainData terrData, int[] xPieces, int[] yPieces) 125 private static TerrainPatch.Header PrescanPatch(float[] patch)
126 { 126 {
127 byte landPacketType = (byte)TerrainPatch.LayerType.Land; 127 TerrainPatch.Header header = new TerrainPatch.Header();
128 if (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize) 128 float zmax = -99999999.0f;
129 float zmin = 99999999.0f;
130
131 for (int i = 0; i < Constants.TerrainPatchSize * Constants.TerrainPatchSize; i++)
129 { 132 {
130 landPacketType = (byte)TerrainPatch.LayerType.LandExtended; 133 float val = patch[i];
134 if (val > zmax) zmax = val;
135 if (val < zmin) zmin = val;
131 } 136 }
132 137
133 return CreateLandPacket(terrData, xPieces, yPieces, landPacketType); 138 header.DCOffset = zmin;
139 header.Range = (int)((zmax - zmin) + 1.0f);
140
141 return header;
134 } 142 }
135 143
136 /// <summary> 144 private static int[] CompressPatch(float[] patchData, TerrainPatch.Header header, int prequant, out int wbits)
137 /// Creates a LayerData packet for compressed land data given a full
138 /// simulator heightmap and an array of indices of patches to compress
139 /// </summary>
140 /// <param name="terrData">
141 /// Terrain data that can result in a meter square heightmap.
142 /// </param>
143 /// <param name="x">
144 /// Array of indexes in the grid of patches
145 /// for this simulator.
146 /// If creating a packet for multiple patches, there will be entries in
147 /// both the X and Y arrays for each of the patches.
148 /// For example if patches 1 and 17 are to be sent,
149 /// x[] = {1,1} and y[] = {0,1} which specifies the patches at
150 /// indexes <1,0> and <1,1> (presuming the terrain size is 16x16 patches).
151 /// </param>
152 /// <param name="y">
153 /// Array of indexes in the grid of patches.
154 /// </param>
155 /// <param name="type"></param>
156 /// <returns></returns>
157 public static LayerDataPacket CreateLandPacket(TerrainData terrData, int[] x, int[] y, byte type)
158 { 145 {
159 LayerDataPacket layer = new LayerDataPacket {LayerID = {Type = type}}; 146 float[] block = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
147 float oozrange = 1.0f / header.Range;
148 float range = (1 << prequant);
149 float premult = oozrange * range;
160 150
161 TerrainPatch.GroupHeader header = new TerrainPatch.GroupHeader
162 {Stride = STRIDE, PatchSize = Constants.TerrainPatchSize};
163 151
164 byte[] data = new byte[x.Length * Constants.TerrainPatchSize * Constants.TerrainPatchSize * 2]; 152 float sub = 0.5f * header.Range + header.DCOffset;
165 BitPack bitpack = new BitPack(data, 0);
166 bitpack.PackBits(header.Stride, 16);
167 bitpack.PackBits(header.PatchSize, 8);
168 bitpack.PackBits(type, 8);
169 153
170 for (int i = 0; i < x.Length; i++) 154 int wordsize = (prequant - 2) & 0x0f;
171 CreatePatchFromHeightmap(bitpack, terrData, x[i], y[i]); 155 header.QuantWBits = wordsize;
156 header.QuantWBits |= wordsize << 4;
172 157
173 bitpack.PackBits(END_OF_PATCHES, 8); 158 int k = 0;
159 for (int j = 0; j < Constants.TerrainPatchSize; j++)
160 {
161 for (int i = 0; i < Constants.TerrainPatchSize; i++)
162 block[k++] = (patchData[j * Constants.TerrainPatchSize + i] - sub) * premult;
163 }
174 164
175 layer.LayerData.Data = new byte[bitpack.BytePos + 1]; 165 float[] ftemp = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
176 Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1); 166 int[] iout = new int[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
177 167
178 return layer; 168 wbits = (prequant >> 1);
169
170 dct16x16(block, iout, ref wbits);
171
172 return iout;
179 } 173 }
180 174
181 // Unused: left for historical reference. 175 // new using terrain data and patchs indexes
182 public static void CreatePatch(BitPack output, float[] patchData, int x, int y, int pRegionSizeX, int pRegionSizeY) 176 public static List<LayerDataPacket> CreateLayerDataPackets(TerrainData terrData, int[] x, int[] y, byte landPacketType)
183 { 177 {
184 TerrainPatch.Header header = PrescanPatch(patchData); 178 List<LayerDataPacket> ret = new List<LayerDataPacket>();
185 header.QuantWBits = 136; 179
186 if (pRegionSizeX > Constants.RegionSize || pRegionSizeY > Constants.RegionSize) 180 //create packet and global header
187 { 181 LayerDataPacket layer = new LayerDataPacket();
188 header.PatchIDs = (y & 0xFFFF); 182
189 header.PatchIDs += (x << 16); 183 layer.LayerID.Type = landPacketType;
190 } 184
191 else 185 byte[] data = new byte[x.Length * Constants.TerrainPatchSize * Constants.TerrainPatchSize * 2];
186 BitPack bitpack = new BitPack(data, 0);
187 bitpack.PackBits(STRIDE, 16);
188 bitpack.PackBits(Constants.TerrainPatchSize, 8);
189 bitpack.PackBits(landPacketType, 8);
190
191 for (int i = 0; i < x.Length; i++)
192 { 192 {
193 header.PatchIDs = (y & 0x1F); 193 CreatePatchFromTerrainData(bitpack, terrData, x[i], y[i]);
194 header.PatchIDs += (x << 5); 194 if (bitpack.BytePos > 980 && i != x.Length - 1)
195 {
196 //finish this packet
197 bitpack.PackBits(END_OF_PATCHES, 8);
198
199 layer.LayerData.Data = new byte[bitpack.BytePos + 1];
200 Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1);
201 ret.Add(layer);
202
203 // start another
204 layer = new LayerDataPacket();
205 layer.LayerID.Type = landPacketType;
206
207 bitpack = new BitPack(data, 0);
208 bitpack.PackBits(STRIDE, 16);
209 bitpack.PackBits(Constants.TerrainPatchSize, 8);
210 bitpack.PackBits(landPacketType, 8);
211 }
195 } 212 }
196 213
197 // NOTE: No idea what prequant and postquant should be or what they do 214 bitpack.PackBits(END_OF_PATCHES, 8);
198 215
199 int wbits; 216 layer.LayerData.Data = new byte[bitpack.BytePos + 1];
200 int[] patch = CompressPatch(patchData, header, 10, out wbits); 217 Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1);
201 wbits = EncodePatchHeader(output, header, patch, Constants.RegionSize, Constants.RegionSize, wbits); 218 ret.Add(layer);
202 EncodePatch(output, patch, 0, wbits); 219
220 return ret;
203 } 221 }
204 222
205 /// <summary> 223 public static void CreatePatchFromTerrainData(BitPack output, TerrainData terrData, int patchX, int patchY)
206 /// Add a patch of terrain to a BitPacker
207 /// </summary>
208 /// <param name="output">BitPacker to write the patch to</param>
209 /// <param name="heightmap">
210 /// Heightmap of the simulator. Presumed to be an sizeX*sizeY array.
211 /// </param>
212 /// <param name="patchX">
213 /// X offset of the patch to create.
214 /// </param>
215 /// <param name="patchY">
216 /// Y offset of the patch to create.
217 /// </param>
218 /// <param name="pRegionSizeX"></param>
219 /// <param name="pRegionSizeY"></param>
220 public static void CreatePatchFromHeightmap(BitPack output, TerrainData terrData, int patchX, int patchY)
221 { 224 {
222 TerrainPatch.Header header = PrescanPatch(terrData, patchX, patchY); 225 float frange;
223 header.QuantWBits = 136; 226 TerrainPatch.Header header = PrescanPatch(terrData, patchX, patchY, out frange);
227 header.QuantWBits = 130;
224 228
229 bool largeRegion = false;
225 // If larger than legacy region size, pack patch X and Y info differently. 230 // If larger than legacy region size, pack patch X and Y info differently.
226 if (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize) 231 if (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize)
227 { 232 {
228 header.PatchIDs = (patchY & 0xFFFF); 233 header.PatchIDs = (patchY & 0xFFFF);
229 header.PatchIDs += (patchX << 16); 234 header.PatchIDs += (patchX << 16);
235 largeRegion = true;
230 } 236 }
231 else 237 else
232 { 238 {
@@ -234,45 +240,45 @@ namespace OpenSim.Region.ClientStack.LindenUDP
234 header.PatchIDs += (patchX << 5); 240 header.PatchIDs += (patchX << 5);
235 } 241 }
236 242
237 // m_log.DebugFormat("{0} CreatePatchFromHeightmap. patchX={1}, patchY={2}, DCOffset={3}, range={4}", 243 if (Math.Round((double)frange, 2) == 1.0)
238 // LogHeader, patchX, patchY, header.DCOffset, header.Range); 244 {
245 // flat terrain speed up things
239 246
240 // NOTE: No idea what prequant and postquant should be or what they do 247 header.DCOffset -= 0.5f;
241 int wbits;
242 int[] patch = CompressPatch(terrData, patchX, patchY, header, 10, out wbits);
243 wbits = EncodePatchHeader(output, header, patch, (uint)terrData.SizeX, (uint)terrData.SizeY, wbits);
244 EncodePatch(output, patch, 0, wbits);
245 }
246 248
247 private static TerrainPatch.Header PrescanPatch(float[] patch) 249 header.QuantWBits = 0x00;
248 { 250 output.PackBits(header.QuantWBits, 8);
249 TerrainPatch.Header header = new TerrainPatch.Header(); 251 output.PackFloat(header.DCOffset);
250 float zmax = -99999999.0f; 252 output.PackBits(1, 16);
251 float zmin = 99999999.0f; 253 if (largeRegion)
254 output.PackBits(header.PatchIDs, 32);
255 else
256 output.PackBits(header.PatchIDs, 10);
252 257
253 for (int i = 0; i < Constants.TerrainPatchSize*Constants.TerrainPatchSize; i++) 258 // and thats all
254 { 259 output.PackBits(ZERO_EOB, 2);
255 float val = patch[i]; 260 return;
256 if (val > zmax) zmax = val;
257 if (val < zmin) zmin = val;
258 } 261 }
259 262
260 header.DCOffset = zmin; 263 int wbits;
261 header.Range = (int) ((zmax - zmin) + 1.0f); 264 int[] patch = CompressPatch(terrData, patchX, patchY, header, 10, out wbits);
262 265 EncodePatchHeader(output, header, patch, largeRegion, ref wbits);
263 return header; 266 EncodePatch(output, patch, 0, wbits);
264 } 267 }
265 268
266 // Scan the height info we're returning and return a patch packet header for this patch. 269 // Scan the height info we're returning and return a patch packet header for this patch.
267 private static TerrainPatch.Header PrescanPatch(TerrainData terrData, int patchX, int patchY) 270 private static TerrainPatch.Header PrescanPatch(TerrainData terrData, int patchX, int patchY, out float frange)
268 { 271 {
269 TerrainPatch.Header header = new TerrainPatch.Header(); 272 TerrainPatch.Header header = new TerrainPatch.Header();
270 float zmax = -99999999.0f; 273 float zmax = float.MinValue;
271 float zmin = 99999999.0f; 274 float zmin = float.MaxValue;
272 275
273 for (int j = patchY*Constants.TerrainPatchSize; j < (patchY + 1)*Constants.TerrainPatchSize; j++) 276 int startx = patchX * Constants.TerrainPatchSize;
277 int starty = patchY * Constants.TerrainPatchSize;
278
279 for (int j = starty; j < starty + Constants.TerrainPatchSize; j++)
274 { 280 {
275 for (int i = patchX*Constants.TerrainPatchSize; i < (patchX + 1)*Constants.TerrainPatchSize; i++) 281 for (int i = startx; i < startx + Constants.TerrainPatchSize; i++)
276 { 282 {
277 float val = terrData[i, j]; 283 float val = terrData[i, j];
278 if (val > zmax) zmax = val; 284 if (val > zmax) zmax = val;
@@ -281,309 +287,430 @@ namespace OpenSim.Region.ClientStack.LindenUDP
281 } 287 }
282 288
283 header.DCOffset = zmin; 289 header.DCOffset = zmin;
284 header.Range = (int)((zmax - zmin) + 1.0f); 290 frange = ((zmax - zmin) + 1.0f);
285 291 header.Range = (int)frange;
286 return header;
287 }
288
289 public static TerrainPatch.Header DecodePatchHeader(BitPack bitpack)
290 {
291 TerrainPatch.Header header = new TerrainPatch.Header {QuantWBits = bitpack.UnpackBits(8)};
292
293 // Quantized word bits
294 if (header.QuantWBits == END_OF_PATCHES)
295 return header;
296
297 // DC offset
298 header.DCOffset = bitpack.UnpackFloat();
299
300 // Range
301 header.Range = bitpack.UnpackBits(16);
302
303 // Patch IDs (10 bits)
304 header.PatchIDs = bitpack.UnpackBits(10);
305
306 // Word bits
307 header.WordBits = (uint) ((header.QuantWBits & 0x0f) + 2);
308 292
309 return header; 293 return header;
310 } 294 }
311 295
312 private static int EncodePatchHeader(BitPack output, TerrainPatch.Header header, int[] patch, uint pRegionSizeX, 296 private static void EncodePatchHeader(BitPack output, TerrainPatch.Header header, int[] patch, bool largeRegion, ref int wbits)
313 uint pRegionSizeY, int wbits)
314 { 297 {
315 /*
316 int temp;
317 int wbits = (header.QuantWBits & 0x0f) + 2;
318 uint maxWbits = (uint)wbits + 5;
319 uint minWbits = ((uint)wbits >> 1);
320 int wbitsMaxValue;
321 */
322 // goal is to determ minimum number of bits to use so all data fits
323 /*
324 wbits = (int)minWbits;
325 wbitsMaxValue = (1 << wbits);
326
327 for (int i = 0; i < patch.Length; i++)
328 {
329 temp = patch[i];
330 if (temp != 0)
331 {
332 // Get the absolute value
333 if (temp < 0) temp *= -1;
334
335 no coments..
336
337 for (int j = (int)maxWbits; j > (int)minWbits; j--)
338 {
339 if ((temp & (1 << j)) != 0)
340 {
341 if (j > wbits) wbits = j;
342 break;
343 }
344 }
345
346 while (temp > wbitsMaxValue)
347 {
348 wbits++;
349 if (wbits == maxWbits)
350 goto Done;
351 wbitsMaxValue = 1 << wbits;
352 }
353 }
354 }
355
356 Done:
357
358 // wbits += 1;
359 */
360 // better check
361 if (wbits > 17) 298 if (wbits > 17)
362 wbits = 16; 299 wbits = 17;
363 else if (wbits < 3) 300 else if (wbits < 2)
364 wbits = 3; 301 wbits = 2;
365 302
366 header.QuantWBits &= 0xf0; 303 header.QuantWBits &= 0xf0;
367
368 header.QuantWBits |= (wbits - 2); 304 header.QuantWBits |= (wbits - 2);
369 305
370 output.PackBits(header.QuantWBits, 8); 306 output.PackBits(header.QuantWBits, 8);
371 output.PackFloat(header.DCOffset); 307 output.PackFloat(header.DCOffset);
372 output.PackBits(header.Range, 16); 308 output.PackBits(header.Range, 16);
373 if (pRegionSizeX > Constants.RegionSize || pRegionSizeY > Constants.RegionSize) 309 if (largeRegion)
374 output.PackBits(header.PatchIDs, 32); 310 output.PackBits(header.PatchIDs, 32);
375 else 311 else
376 output.PackBits(header.PatchIDs, 10); 312 output.PackBits(header.PatchIDs, 10);
377
378 return wbits;
379 } 313 }
380 314
381 private static void IDCTColumn16(float[] linein, float[] lineout, int column) 315 private static void EncodePatch(BitPack output, int[] patch, int postquant, int wbits)
382 { 316 {
383 for (int n = 0; n < Constants.TerrainPatchSize; n++) 317 int maxwbitssize = (1 << wbits) - 1;
384 { 318 int fullSize = Constants.TerrainPatchSize * Constants.TerrainPatchSize;
385 float total = OO_SQRT2*linein[column];
386
387 for (int u = 1; u < Constants.TerrainPatchSize; u++)
388 {
389 int usize = u*Constants.TerrainPatchSize;
390 total += linein[usize + column]*CosineTable16[usize + n];
391 }
392 319
393 lineout[Constants.TerrainPatchSize*n + column] = total; 320 if (postquant > fullSize || postquant < 0)
321 {
322 Logger.Log("Postquant is outside the range of allowed values in EncodePatch()", Helpers.LogLevel.Error);
323 return;
394 } 324 }
395 }
396 325
397 private static void IDCTLine16(float[] linein, float[] lineout, int line) 326 if (postquant != 0)
398 { 327 patch[fullSize - postquant] = 0;
399 const float oosob = 2.0f/Constants.TerrainPatchSize;
400 int lineSize = line*Constants.TerrainPatchSize;
401 328
402 for (int n = 0; n < Constants.TerrainPatchSize; n++) 329 int lastZeroindx = fullSize - postquant;
330
331 for (int i = 0; i < fullSize; i++)
403 { 332 {
404 float total = OO_SQRT2*linein[lineSize]; 333 int temp = patch[i];
405 334
406 for (int u = 1; u < Constants.TerrainPatchSize; u++) 335 if (temp == 0)
407 { 336 {
408 total += linein[lineSize + u]*CosineTable16[u*Constants.TerrainPatchSize + n]; 337 bool eob = true;
338
339 for (int j = i; j < lastZeroindx; j++)
340 {
341 if (patch[j] != 0)
342 {
343 eob = false;
344 break;
345 }
346 }
347
348 if (eob)
349 {
350 output.PackBits(ZERO_EOB, 2);
351 return;
352 }
353 output.PackBits(ZERO_CODE, 1);
409 } 354 }
355 else
356 {
357 if (temp < 0)
358 {
359 temp *= -1;
360
361 if (temp > maxwbitssize) temp = maxwbitssize;
362
363 output.PackBits(NEGATIVE_VALUE, 3);
364 output.PackBits(temp, wbits);
365 }
366 else
367 {
368 if (temp > maxwbitssize) temp = maxwbitssize;
410 369
411 lineout[lineSize + n] = total*oosob; 370 output.PackBits(POSITIVE_VALUE, 3);
371 output.PackBits(temp, wbits);
372 }
373 }
412 } 374 }
413 } 375 }
414 376
415/* 377 private static int[] CompressPatch(TerrainData terrData, int patchX, int patchY, TerrainPatch.Header header,
416 private static void DCTLine16(float[] linein, float[] lineout, int line) 378 int prequant, out int wbits)
417 { 379 {
418 float total = 0.0f; 380 float[] block = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
419 int lineSize = line * Constants.TerrainPatchSize; 381 int[] iout = new int[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
420 382
421 for (int n = 0; n < Constants.TerrainPatchSize; n++) 383 float oozrange = 1.0f / header.Range;
422 { 384 float invprequat = (1 << prequant);
423 total += linein[lineSize + n]; 385 float premult = oozrange * invprequat;
424 }
425 386
426 lineout[lineSize] = OO_SQRT2 * total; 387 float sub = 0.5f * header.Range + header.DCOffset;
427 388
428 int uptr = 0; 389 int wordsize = (prequant - 2) & 0x0f;
429 for (int u = 1; u < Constants.TerrainPatchSize; u++) 390 header.QuantWBits = wordsize;
430 { 391 header.QuantWBits |= wordsize << 4;
431 total = 0.0f;
432 uptr += Constants.TerrainPatchSize;
433 392
434 for (int n = 0; n < Constants.TerrainPatchSize; n++) 393 int k = 0;
394 int startX = patchX * Constants.TerrainPatchSize;
395 int startY = patchY * Constants.TerrainPatchSize;
396 for (int y = startY; y < startY + Constants.TerrainPatchSize; y++)
397 {
398 for (int x = startX; x < startX + Constants.TerrainPatchSize; x++)
435 { 399 {
436 total += linein[lineSize + n] * CosineTable16[uptr + n]; 400 block[k++] = (terrData[x, y] - sub) * premult;
437 } 401 }
438
439 lineout[lineSize + u] = total;
440 } 402 }
403
404 wbits = (prequant >> 1);
405
406 dct16x16(block, iout, ref wbits);
407
408 return iout;
441 } 409 }
442*/
443 410
444 private static void DCTLine16(float[] linein, float[] lineout, int line) 411 #region Initialization
445 {
446 // outputs transpose data (lines exchanged with coluns )
447 // so to save a bit of cpu when doing coluns
448 float total = 0.0f;
449 int lineSize = line*Constants.TerrainPatchSize;
450 412
451 for (int n = 0; n < Constants.TerrainPatchSize; n++) 413 private static void BuildDequantizeTable16()
414 {
415 for (int j = 0; j < Constants.TerrainPatchSize; j++)
452 { 416 {
453 total += linein[lineSize + n]; 417 for (int i = 0; i < Constants.TerrainPatchSize; i++)
418 {
419 DequantizeTable16[j * Constants.TerrainPatchSize + i] = 1.0f + 2.0f * (i + j);
420 }
454 } 421 }
422 }
455 423
456 lineout[line] = OO_SQRT2*total; 424 private static void BuildQuantizeTable16()
457 425 {
458 for (int u = Constants.TerrainPatchSize; 426 const float oosob = 2.0f / Constants.TerrainPatchSize;
459 u < Constants.TerrainPatchSize*Constants.TerrainPatchSize; 427 for (int j = 0; j < Constants.TerrainPatchSize; j++)
460 u += Constants.TerrainPatchSize)
461 { 428 {
462 total = 0.0f; 429 for (int i = 0; i < Constants.TerrainPatchSize; i++)
463 for (int ptrn = lineSize, ptru = u; ptrn < lineSize + Constants.TerrainPatchSize; ptrn++,ptru++)
464 { 430 {
465 total += linein[ptrn]*CosineTable16[ptru]; 431 QuantizeTable16[j * Constants.TerrainPatchSize + i] = oosob / (1.0f + 2.0f * (i + (float)j));
466 } 432 }
467
468 lineout[line + u] = total;
469 } 433 }
470 } 434 }
471 435
436 private static void BuildCopyMatrix16()
437 {
438 bool diag = false;
439 bool right = true;
440 int i = 0;
441 int j = 0;
442 int count = 0;
443
444 while (i < Constants.TerrainPatchSize && j < Constants.TerrainPatchSize)
445 {
446 CopyMatrix16[j * Constants.TerrainPatchSize + i] = count++;
472 447
473 /* 448 if (!diag)
474 private static void DCTColumn16(float[] linein, int[] lineout, int column)
475 { 449 {
476 float total = 0.0f; 450 if (right)
477 // const float oosob = 2.0f / Constants.TerrainPatchSize;
478
479 for (int n = 0; n < Constants.TerrainPatchSize; n++)
480 { 451 {
481 total += linein[Constants.TerrainPatchSize * n + column]; 452 if (i < Constants.TerrainPatchSize - 1) i++;
482 } 453 else j++;
483
484 // lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * oosob * QuantizeTable16[column]);
485 lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * QuantizeTable16[column]);
486 454
487 for (int uptr = Constants.TerrainPatchSize; uptr < Constants.TerrainPatchSize * Constants.TerrainPatchSize; uptr += Constants.TerrainPatchSize) 455 right = false;
456 diag = true;
457 }
458 else
488 { 459 {
489 total = 0.0f; 460 if (j < Constants.TerrainPatchSize - 1) j++;
490 461 else i++;
491 for (int n = 0; n < Constants.TerrainPatchSize; n++)
492 {
493 total += linein[Constants.TerrainPatchSize * n + column] * CosineTable16[uptr + n];
494 }
495 462
496 // lineout[CopyMatrix16[Constants.TerrainPatchSize * u + column]] = (int)(total * oosob * QuantizeTable16[Constants.TerrainPatchSize * u + column]); 463 right = true;
497 lineout[CopyMatrix16[uptr + column]] = (int)(total * QuantizeTable16[uptr + column]); 464 diag = true;
498 } 465 }
466 }
467 else
468 {
469 if (right)
470 {
471 i++;
472 j--;
473 if (i == Constants.TerrainPatchSize - 1 || j == 0) diag = false;
474 }
475 else
476 {
477 i--;
478 j++;
479 if (j == Constants.TerrainPatchSize - 1 || i == 0) diag = false;
480 }
499 } 481 }
482 }
483 }
500 484
501 private static void DCTColumn16(float[] linein, int[] lineout, int column) 485 #endregion Initialization
502 {
503 // input columns are in fact stored in lines now
504 486
505 float total = 0.0f;
506// const float oosob = 2.0f / Constants.TerrainPatchSize;
507 int inlinesptr = Constants.TerrainPatchSize*column;
508 487
509 for (int n = 0; n < Constants.TerrainPatchSize; n++)
510 {
511 total += linein[inlinesptr + n];
512 }
513 488
514 // lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * oosob * QuantizeTable16[column]);
515 lineout[CopyMatrix16[column]] = (int) (OO_SQRT2*total*QuantizeTable16[column]);
516 489
517 for (int uptr = Constants.TerrainPatchSize; 490 #region DCT
518 uptr < Constants.TerrainPatchSize*Constants.TerrainPatchSize;
519 uptr += Constants.TerrainPatchSize)
520 {
521 total = 0.0f;
522 491
523 for (int n = inlinesptr, ptru = uptr; n < inlinesptr + Constants.TerrainPatchSize; n++, ptru++) 492 /* DCT (Discrete Cosine Transform)
524 { 493 adaptation from
525 total += linein[n]*CosineTable16[ptru]; 494 General Purpose 2D,3D FFT (Fast Fourier Transform) Package
526 } 495 by Takuya OOURA (email: ooura@kurims.kyoto-u.ac.jp)
527 496
528// lineout[CopyMatrix16[Constants.TerrainPatchSize * u + column]] = (int)(total * oosob * QuantizeTable16[Constants.TerrainPatchSize * u + column]); 497 -------- 16x16 DCT (Discrete Cosine Transform) / Inverse of DCT --------
529 lineout[CopyMatrix16[uptr + column]] = (int) (total*QuantizeTable16[uptr + column]); 498 [definition]
530 } 499 <case1> Normalized 16x16 IDCT
531 } 500 C[k1 + k2] = (1/8) * sum_j1=0^15 sum_j2=0^15
501 tmp[j1 + j2] * s[j1] * s[j2] *
502 cos(pi*j1*(k1+1/2)/16) *
503 cos(pi*j2*(k2+1/2)/16), 0<=k1<16, 0<=k2<16
504 (s[0] = 1/sqrt(2), s[j] = 1, j > 0)
505 <case2> Normalized 16x16 DCT
506 C[k1 + k2] = (1/8) * s[k1] * s[k2] * sum_j1=0^15 sum_j2=0^15
507 tmp[j1 + j2] *
508 cos(pi*(j1+1/2)*k1/16) *
509 cos(pi*(j2+1/2)*k2/16), 0<=k1<16, 0<=k2<16
510 (s[0] = 1/sqrt(2), s[j] = 1, j > 0)
532 */ 511 */
533 512
534 private static int DCTColumn16Wbits(float[] linein, int[] lineout, int column, int wbits, int maxwbits) 513 /* Cn_kR = sqrt(2.0/n) * cos(pi/2*k/n) */
514 /* Cn_kI = sqrt(2.0/n) * sin(pi/2*k/n) */
515 /* Wn_kR = cos(pi/2*k/n) */
516 /* Wn_kI = sin(pi/2*k/n) */
517
518 const float C16_1R = 0.35185093438159561476f * 2.82842712474619f;
519 const float C16_1I = 0.03465429229977286565f * 2.82842712474619f;
520 const float C16_2R = 0.34675996133053686546f * 2.82842712474619f;
521 const float C16_2I = 0.06897484482073575308f * 2.82842712474619f;
522 const float C16_3R = 0.33832950029358816957f * 2.82842712474619f;
523 const float C16_3I = 0.10263113188058934529f * 2.82842712474619f;
524 const float C16_4R = 0.32664074121909413196f * 2.82842712474619f;
525 const float C16_4I = 0.13529902503654924610f * 2.82842712474619f;
526 const float C16_5R = 0.31180625324666780814f * 2.82842712474619f;
527 const float C16_5I = 0.16666391461943662432f * 2.82842712474619f;
528 const float C16_6R = 0.29396890060483967924f * 2.82842712474619f;
529 const float C16_6I = 0.19642373959677554532f * 2.82842712474619f;
530 const float C16_7R = 0.27330046675043937206f * 2.82842712474619f;
531 const float C16_7I = 0.22429189658565907106f * 2.82842712474619f;
532 const float C16_8R = 0.25f * 2.82842712474619f;
533 const float W16_4R = 0.92387953251128675613f;
534 const float W16_4I = 0.38268343236508977173f;
535 const float W16_8R = 0.70710678118654752440f;
536
537 static void dct16x16(float[] a, int[] iout, ref int wbits)
535 { 538 {
536 // input columns are in fact stored in lines now 539 float[] tmp = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
537 540
538 bool dowbits = wbits != maxwbits; 541 float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
539 int wbitsMaxValue = 1 << wbits; 542 float x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i;
543 float xr, xi;
544 float ftmp;
540 545
541 float total = 0.0f; 546 int fullSize = Constants.TerrainPatchSize * Constants.TerrainPatchSize;
542 // const float oosob = 2.0f / Constants.TerrainPatchSize; 547 int itmp;
543 int inlinesptr = Constants.TerrainPatchSize*column; 548 int j, k;
549 int indx;
544 550
545 for (int n = 0; n < Constants.TerrainPatchSize; n++) 551 const int maxwbits = 17; // per header encoding
552 int wbitsMaxValue = 1 << wbits;
553 bool dowbits = wbits < 17;
554
555 for (j = 0, k = 0; j < fullSize; j += Constants.TerrainPatchSize, k++)
546 { 556 {
547 total += linein[inlinesptr + n]; 557 x4r = a[0 + j] - a[15 + j];
558 xr = a[0 + j] + a[15 + j];
559 x4i = a[8 + j] - a[7 + j];
560 xi = a[8 + j] + a[7 + j];
561 x0r = xr + xi;
562 x0i = xr - xi;
563 x5r = a[2 + j] - a[13 + j];
564 xr = a[2 + j] + a[13 + j];
565 x5i = a[10 + j] - a[5 + j];
566 xi = a[10 + j] + a[5 + j];
567 x1r = xr + xi;
568 x1i = xr - xi;
569 x6r = a[4 + j] - a[11 + j];
570 xr = a[4 + j] + a[11 + j];
571 x6i = a[12 + j] - a[3 + j];
572 xi = a[12 + j] + a[3 + j];
573 x2r = xr + xi;
574 x2i = xr - xi;
575 x7r = a[6 + j] - a[9 + j];
576 xr = a[6 + j] + a[9 + j];
577 x7i = a[14 + j] - a[1 + j];
578 xi = a[14 + j] + a[1 + j];
579 x3r = xr + xi;
580 x3i = xr - xi;
581 xr = x0r + x2r;
582 xi = x1r + x3r;
583 tmp[k] = C16_8R * (xr + xi); //
584 tmp[8 * Constants.TerrainPatchSize + k] = C16_8R * (xr - xi); //
585 xr = x0r - x2r;
586 xi = x1r - x3r;
587 tmp[4 * Constants.TerrainPatchSize + k] = C16_4R * xr - C16_4I * xi; //
588 tmp[12 * Constants.TerrainPatchSize + k] = C16_4R * xi + C16_4I * xr; //
589 x0r = W16_8R * (x1i - x3i);
590 x2r = W16_8R * (x1i + x3i);
591 xr = x0i + x0r;
592 xi = x2r + x2i;
593 tmp[2 * Constants.TerrainPatchSize + k] = C16_2R * xr - C16_2I * xi; //
594 tmp[14 * Constants.TerrainPatchSize + k] = C16_2R * xi + C16_2I * xr; //
595 xr = x0i - x0r;
596 xi = x2r - x2i;
597 tmp[6 * Constants.TerrainPatchSize + k] = C16_6R * xr - C16_6I * xi; //
598 tmp[10 * Constants.TerrainPatchSize + k] = C16_6R * xi + C16_6I * xr; //
599 xr = W16_8R * (x6r - x6i);
600 xi = W16_8R * (x6i + x6r);
601 x6r = x4r - xr;
602 x6i = x4i - xi;
603 x4r += xr;
604 x4i += xi;
605 xr = W16_4I * x7r - W16_4R * x7i;
606 xi = W16_4I * x7i + W16_4R * x7r;
607 x7r = W16_4R * x5r - W16_4I * x5i;
608 x7i = W16_4R * x5i + W16_4I * x5r;
609 x5r = x7r + xr;
610 x5i = x7i + xi;
611 x7r -= xr;
612 x7i -= xi;
613 xr = x4r + x5r;
614 xi = x5i + x4i;
615 tmp[Constants.TerrainPatchSize + k] = C16_1R * xr - C16_1I * xi; //
616 tmp[15 * Constants.TerrainPatchSize + k] = C16_1R * xi + C16_1I * xr; //
617 xr = x4r - x5r;
618 xi = x5i - x4i;
619 tmp[7 * Constants.TerrainPatchSize + k] = C16_7R * xr - C16_7I * xi; //
620 tmp[9 * Constants.TerrainPatchSize + k] = C16_7R * xi + C16_7I * xr; //
621 xr = x6r - x7i;
622 xi = x7r + x6i;
623 tmp[5 * Constants.TerrainPatchSize + k] = C16_5R * xr - C16_5I * xi; //
624 tmp[11 * Constants.TerrainPatchSize + k] = C16_5R * xi + C16_5I * xr; //
625 xr = x6r + x7i;
626 xi = x7r - x6i;
627 tmp[3 * Constants.TerrainPatchSize + k] = C16_3R * xr - C16_3I * xi; //
628 tmp[13 * Constants.TerrainPatchSize + k] = C16_3R * xi + C16_3I * xr; //
548 } 629 }
549 630
550 // lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * oosob * QuantizeTable16[column]); 631 for (j = 0, k = 0; j < fullSize; j += Constants.TerrainPatchSize, k++)
551 int tmp = (int) (OO_SQRT2*total*QuantizeTable16[column]);
552 lineout[CopyMatrix16[column]] = tmp;
553
554 if (dowbits)
555 { 632 {
556 if (tmp < 0) tmp *= -1; 633 x4r = tmp[0 + j] - tmp[15 + j];
557 while (tmp > wbitsMaxValue) 634 xr = tmp[0 + j] + tmp[15 + j];
635 x4i = tmp[8 + j] - tmp[7 + j];
636 xi = tmp[8 + j] + tmp[7 + j];
637 x0r = xr + xi;
638 x0i = xr - xi;
639 x5r = tmp[2 + j] - tmp[13 + j];
640 xr = tmp[2 + j] + tmp[13 + j];
641 x5i = tmp[10 + j] - tmp[5 + j];
642 xi = tmp[10 + j] + tmp[5 + j];
643 x1r = xr + xi;
644 x1i = xr - xi;
645 x6r = tmp[4 + j] - tmp[11 + j];
646 xr = tmp[4 + j] + tmp[11 + j];
647 x6i = tmp[12 + j] - tmp[3 + j];
648 xi = tmp[12 + j] + tmp[3 + j];
649 x2r = xr + xi;
650 x2i = xr - xi;
651 x7r = tmp[6 + j] - tmp[9 + j];
652 xr = tmp[6 + j] + tmp[9 + j];
653 x7i = tmp[14 + j] - tmp[1 + j];
654 xi = tmp[14 + j] + tmp[1 + j];
655 x3r = xr + xi;
656 x3i = xr - xi;
657 xr = x0r + x2r;
658 xi = x1r + x3r;
659
660 //tmp[0 + k] = C16_8R * (xr + xi); //
661 ftmp = C16_8R * (xr + xi);
662 itmp = (int)(ftmp * QuantizeTable16[k]);
663 iout[CopyMatrix16[k]] = itmp;
664
665 if (dowbits)
558 { 666 {
559 wbits++; 667 if (itmp < 0) itmp *= -1;
560 wbitsMaxValue = 1 << wbits; 668 while (itmp > wbitsMaxValue)
561 if (wbits == maxwbits)
562 { 669 {
563 dowbits = false; 670 wbits++;
564 break; 671 wbitsMaxValue = 1 << wbits;
672 if (wbits == maxwbits)
673 {
674 dowbits = false;
675 break;
676 }
565 } 677 }
566 } 678 }
567 }
568 679
569 for (int uptr = Constants.TerrainPatchSize; 680 //tmp[8 * Constants.TerrainPatchSize + k] = C16_8R * (xr - xi); //
570 uptr < Constants.TerrainPatchSize*Constants.TerrainPatchSize; 681 ftmp = C16_8R * (xr - xi);
571 uptr += Constants.TerrainPatchSize) 682 indx = 8 * Constants.TerrainPatchSize + k;
572 { 683 itmp = (int)(ftmp * QuantizeTable16[indx]);
573 total = 0.0f; 684 iout[CopyMatrix16[indx]] = itmp;
574 685
575 for (int n = inlinesptr, ptru = uptr; n < inlinesptr + Constants.TerrainPatchSize; n++, ptru++) 686 if (dowbits)
576 { 687 {
577 total += linein[n]*CosineTable16[ptru]; 688 if (itmp < 0) itmp *= -1;
689 while (itmp > wbitsMaxValue)
690 {
691 wbits++;
692 wbitsMaxValue = 1 << wbits;
693 if (wbits == maxwbits)
694 {
695 dowbits = false;
696 break;
697 }
698 }
578 } 699 }
579 700
580 tmp = (int) (total*QuantizeTable16[uptr + column]); 701 xr = x0r - x2r;
581 lineout[CopyMatrix16[uptr + column]] = tmp; 702 xi = x1r - x3r;
703
704 //tmp[4 * Constants.TerrainPatchSize + k] = C16_4R * xr - C16_4I * xi; //
705 ftmp = C16_4R * xr - C16_4I * xi;
706 indx = 4 * Constants.TerrainPatchSize + k;
707 itmp = (int)(ftmp * QuantizeTable16[indx]);
708 iout[CopyMatrix16[indx]] = itmp;
582 709
583 if (dowbits) 710 if (dowbits)
584 { 711 {
585 if (tmp < 0) tmp *= -1; 712 if (itmp < 0) itmp *= -1;
586 while (tmp > wbitsMaxValue) 713 while (itmp > wbitsMaxValue)
587 { 714 {
588 wbits++; 715 wbits++;
589 wbitsMaxValue = 1 << wbits; 716 wbitsMaxValue = 1 << wbits;
@@ -594,355 +721,605 @@ namespace OpenSim.Region.ClientStack.LindenUDP
594 } 721 }
595 } 722 }
596 } 723 }
597 }
598 return wbits;
599 }
600 724
601 public static void DecodePatch(int[] patches, BitPack bitpack, TerrainPatch.Header header, int size) 725 //tmp[12 * Constants.TerrainPatchSize + k] = C16_4R * xi + C16_4I * xr; //
602 { 726 ftmp = C16_4R * xi + C16_4I * xr;
603 for (int n = 0; n < size*size; n++) 727 indx = 12 * Constants.TerrainPatchSize + k;
604 { 728 itmp = (int)(ftmp * QuantizeTable16[indx]);
605 // ? 729 iout[CopyMatrix16[indx]] = itmp;
606 int temp = bitpack.UnpackBits(1); 730
607 if (temp != 0) 731 if (dowbits)
608 { 732 {
609 // Value or EOB 733 if (itmp < 0) itmp *= -1;
610 temp = bitpack.UnpackBits(1); 734 while (itmp > wbitsMaxValue)
611 if (temp != 0)
612 { 735 {
613 // Value 736 wbits++;
614 temp = bitpack.UnpackBits(1); 737 wbitsMaxValue = 1 << wbits;
615 if (temp != 0) 738 if (wbits == maxwbits)
616 {
617 // Negative
618 temp = bitpack.UnpackBits((int) header.WordBits);
619 patches[n] = temp*-1;
620 }
621 else
622 { 739 {
623 // Positive 740 dowbits = false;
624 temp = bitpack.UnpackBits((int) header.WordBits); 741 break;
625 patches[n] = temp;
626 } 742 }
627 } 743 }
628 else 744 }
745
746 x0r = W16_8R * (x1i - x3i);
747 x2r = W16_8R * (x1i + x3i);
748 xr = x0i + x0r;
749 xi = x2r + x2i;
750
751 //tmp[2 * Constants.TerrainPatchSize + k] = C16_2R * xr - C16_2I * xi; //
752 ftmp = C16_2R * xr - C16_2I * xi;
753 indx = 2 * Constants.TerrainPatchSize + k;
754 itmp = (int)(ftmp * QuantizeTable16[indx]);
755 iout[CopyMatrix16[indx]] = itmp;
756
757 if (dowbits)
758 {
759 if (itmp < 0) itmp *= -1;
760 while (itmp > wbitsMaxValue)
629 { 761 {
630 // Set the rest to zero 762 wbits++;
631 // TODO: This might not be necessary 763 wbitsMaxValue = 1 << wbits;
632 for (int o = n; o < size*size; o++) 764 if (wbits == maxwbits)
633 { 765 {
634 patches[o] = 0; 766 dowbits = false;
767 break;
635 } 768 }
636 break;
637 } 769 }
638 } 770 }
639 else
640 {
641 patches[n] = 0;
642 }
643 }
644 }
645 771
646 private static void EncodePatch(BitPack output, int[] patch, int postquant, int wbits) 772 //tmp[14 * Constants.TerrainPatchSize + k] = C16_2R * xi + C16_2I * xr; //
647 { 773 ftmp = C16_2R * xi + C16_2I * xr;
648 int maxwbitssize = (1 << wbits) - 1; 774 indx = 14 * Constants.TerrainPatchSize + k;
775 itmp = (int)(ftmp * QuantizeTable16[indx]);
776 iout[CopyMatrix16[indx]] = itmp;
649 777
650 if (postquant > Constants.TerrainPatchSize*Constants.TerrainPatchSize || postquant < 0) 778 if (dowbits)
651 { 779 {
652 Logger.Log("Postquant is outside the range of allowed values in EncodePatch()", Helpers.LogLevel.Error); 780 if (itmp < 0) itmp *= -1;
653 return; 781 while (itmp > wbitsMaxValue)
654 } 782 {
783 wbits++;
784 wbitsMaxValue = 1 << wbits;
785 if (wbits == maxwbits)
786 {
787 dowbits = false;
788 break;
789 }
790 }
791 }
655 792
656 if (postquant != 0) patch[Constants.TerrainPatchSize*Constants.TerrainPatchSize - postquant] = 0; 793 xr = x0i - x0r;
794 xi = x2r - x2i;
657 795
658 for (int i = 0; i < Constants.TerrainPatchSize*Constants.TerrainPatchSize; i++) 796 //tmp[6 * Constants.TerrainPatchSize + k] = C16_6R * xr - C16_6I * xi; //
659 { 797 ftmp = C16_6R * xr - C16_6I * xi;
660 int temp = patch[i]; 798 indx = 6 * Constants.TerrainPatchSize + k;
799 itmp = (int)(ftmp * QuantizeTable16[indx]);
800 iout[CopyMatrix16[indx]] = itmp;
661 801
662 if (temp == 0) 802 if (dowbits)
663 { 803 {
664 bool eob = true; 804 if (itmp < 0) itmp *= -1;
665 805 while (itmp > wbitsMaxValue)
666 for (int j = i; j < Constants.TerrainPatchSize*Constants.TerrainPatchSize - postquant; j++)
667 { 806 {
668 if (patch[j] != 0) 807 wbits++;
808 wbitsMaxValue = 1 << wbits;
809 if (wbits == maxwbits)
669 { 810 {
670 eob = false; 811 dowbits = false;
671 break; 812 break;
672 } 813 }
673 } 814 }
815 }
674 816
675 if (eob) 817 //tmp[10 * Constants.TerrainPatchSize + k] = C16_6R * xi + C16_6I * xr; //
818 ftmp = C16_6R * xi + C16_6I * xr;
819 indx = 10 * Constants.TerrainPatchSize + k;
820 itmp = (int)(ftmp * QuantizeTable16[indx]);
821 iout[CopyMatrix16[indx]] = itmp;
822
823 if (dowbits)
824 {
825 if (itmp < 0) itmp *= -1;
826 while (itmp > wbitsMaxValue)
676 { 827 {
677 output.PackBits(ZERO_EOB, 2); 828 wbits++;
678 return; 829 wbitsMaxValue = 1 << wbits;
830 if (wbits == maxwbits)
831 {
832 dowbits = false;
833 break;
834 }
679 } 835 }
680 output.PackBits(ZERO_CODE, 1);
681 } 836 }
682 else
683 {
684 if (temp < 0)
685 {
686 temp *= -1;
687 837
688 if (temp > maxwbitssize) temp = maxwbitssize; 838 xr = W16_8R * (x6r - x6i);
839 xi = W16_8R * (x6i + x6r);
840 x6r = x4r - xr;
841 x6i = x4i - xi;
842 x4r += xr;
843 x4i += xi;
844 xr = W16_4I * x7r - W16_4R * x7i;
845 xi = W16_4I * x7i + W16_4R * x7r;
846 x7r = W16_4R * x5r - W16_4I * x5i;
847 x7i = W16_4R * x5i + W16_4I * x5r;
848 x5r = x7r + xr;
849 x5i = x7i + xi;
850 x7r -= xr;
851 x7i -= xi;
852 xr = x4r + x5r;
853 xi = x5i + x4i;
854
855 //tmp[1 * Constants.TerrainPatchSize + k] = C16_1R * xr - C16_1I * xi; //
856 ftmp = C16_1R * xr - C16_1I * xi;
857 indx = Constants.TerrainPatchSize + k;
858 itmp = (int)(ftmp * QuantizeTable16[indx]);
859 iout[CopyMatrix16[indx]] = itmp;
689 860
690 output.PackBits(NEGATIVE_VALUE, 3); 861 if (dowbits)
691 output.PackBits(temp, wbits); 862 {
692 } 863 if (itmp < 0) itmp *= -1;
693 else 864 while (itmp > wbitsMaxValue)
694 { 865 {
695 if (temp > maxwbitssize) temp = maxwbitssize; 866 wbits++;
696 867 wbitsMaxValue = 1 << wbits;
697 output.PackBits(POSITIVE_VALUE, 3); 868 if (wbits == maxwbits)
698 output.PackBits(temp, wbits); 869 {
870 dowbits = false;
871 break;
872 }
699 } 873 }
700 } 874 }
701 }
702 }
703 875
704 public static float[] DecompressPatch(int[] patches, TerrainPatch.Header header, TerrainPatch.GroupHeader group) 876 //tmp[15 * Constants.TerrainPatchSize + k] = C16_1R * xi + C16_1I * xr; //
705 { 877 ftmp = C16_1R * xi + C16_1I * xr;
706 float[] block = new float[group.PatchSize*group.PatchSize]; 878 indx = 15 * Constants.TerrainPatchSize + k;
707 float[] output = new float[group.PatchSize*group.PatchSize]; 879 itmp = (int)(ftmp * QuantizeTable16[indx]);
708 int prequant = (header.QuantWBits >> 4) + 2; 880 iout[CopyMatrix16[indx]] = itmp;
709 int quantize = 1 << prequant; 881
710 float ooq = 1.0f/quantize; 882 if (dowbits)
711 float mult = ooq*header.Range;
712 float addval = mult*(1 << (prequant - 1)) + header.DCOffset;
713
714 if (group.PatchSize == Constants.TerrainPatchSize)
715 {
716 for (int n = 0; n < Constants.TerrainPatchSize*Constants.TerrainPatchSize; n++)
717 { 883 {
718 block[n] = patches[CopyMatrix16[n]]*DequantizeTable16[n]; 884 if (itmp < 0) itmp *= -1;
885 while (itmp > wbitsMaxValue)
886 {
887 wbits++;
888 wbitsMaxValue = 1 << wbits;
889 if (wbits == maxwbits)
890 {
891 dowbits = false;
892 break;
893 }
894 }
719 } 895 }
720 896
721 float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 897 xr = x4r - x5r;
898 xi = x5i - x4i;
722 899
723 for (int o = 0; o < Constants.TerrainPatchSize; o++) 900 //tmp[7 * Constants.TerrainPatchSize + k] = C16_7R * xr - C16_7I * xi; //
724 IDCTColumn16(block, ftemp, o); 901 ftmp = C16_7R * xr - C16_7I * xi;
725 for (int o = 0; o < Constants.TerrainPatchSize; o++) 902 indx = 7 * Constants.TerrainPatchSize + k;
726 IDCTLine16(ftemp, block, o); 903 itmp = (int)(ftmp * QuantizeTable16[indx]);
727 } 904 iout[CopyMatrix16[indx]] = itmp;
728 else 905
729 { 906 if (dowbits)
730 for (int n = 0; n < Constants.TerrainPatchSize*2*Constants.TerrainPatchSize*2; n++)
731 { 907 {
732 block[n] = patches[CopyMatrix32[n]]*DequantizeTable32[n]; 908 if (itmp < 0) itmp *= -1;
909 while (itmp > wbitsMaxValue)
910 {
911 wbits++;
912 wbitsMaxValue = 1 << wbits;
913 if (wbits == maxwbits)
914 {
915 dowbits = false;
916 break;
917 }
918 }
733 } 919 }
734 920
735 Logger.Log("Implement IDCTPatchLarge", Helpers.LogLevel.Error); 921 //tmp[9 * Constants.TerrainPatchSize + k] = C16_7R * xi + C16_7I * xr; //
736 } 922 ftmp = C16_7R * xi + C16_7I * xr;
737 923 indx = 9 * Constants.TerrainPatchSize + k;
738 for (int j = 0; j < block.Length; j++) 924 itmp = (int)(ftmp * QuantizeTable16[indx]);
739 { 925 iout[CopyMatrix16[indx]] = itmp;
740 output[j] = block[j]*mult + addval;
741 }
742
743 return output;
744 }
745 926
746 private static int[] CompressPatch(float[] patchData, TerrainPatch.Header header, int prequant, out int wbits) 927 if (dowbits)
747 { 928 {
748 float[] block = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 929 if (itmp < 0) itmp *= -1;
749 int wordsize = (prequant - 2) & 0x0f; 930 while (itmp > wbitsMaxValue)
750 float oozrange = 1.0f/header.Range; 931 {
751 float range = (1 << prequant); 932 wbits++;
752 float premult = oozrange*range; 933 wbitsMaxValue = 1 << wbits;
753 float sub = (1 << (prequant - 1)) + header.DCOffset*premult; 934 if (wbits == maxwbits)
935 {
936 dowbits = false;
937 break;
938 }
939 }
940 }
754 941
755 header.QuantWBits = wordsize; 942 xr = x6r - x7i;
756 header.QuantWBits |= wordsize << 4; 943 xi = x7r + x6i;
757 944
758 int k = 0; 945 //tmp[5 * Constants.TerrainPatchSize + k] = C16_5R * xr - C16_5I * xi; //
759 for (int j = 0; j < Constants.TerrainPatchSize; j++) 946 ftmp = C16_5R * xr - C16_5I * xi;
760 { 947 indx = 5 * Constants.TerrainPatchSize + k;
761 for (int i = 0; i < Constants.TerrainPatchSize; i++) 948 itmp = (int)(ftmp * QuantizeTable16[indx]);
762 block[k++] = patchData[j*Constants.TerrainPatchSize + i]*premult - sub; 949 iout[CopyMatrix16[indx]] = itmp;
763 }
764 950
765 float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 951 if (dowbits)
766 int[] itemp = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 952 {
953 if (itmp < 0) itmp *= -1;
954 while (itmp > wbitsMaxValue)
955 {
956 wbits++;
957 wbitsMaxValue = 1 << wbits;
958 if (wbits == maxwbits)
959 {
960 dowbits = false;
961 break;
962 }
963 }
964 }
767 965
966 //tmp[11 * Constants.TerrainPatchSize + k] = C16_5R * xi + C16_5I * xr; //
967 ftmp = C16_5R * xi + C16_5I * xr;
968 indx = 11 * Constants.TerrainPatchSize + k;
969 itmp = (int)(ftmp * QuantizeTable16[indx]);
970 iout[CopyMatrix16[indx]] = itmp;
768 971
769 int maxWbits = prequant + 5; 972 if (dowbits)
770 wbits = (prequant >> 1); 973 {
974 if (itmp < 0) itmp *= -1;
975 while (itmp > wbitsMaxValue)
976 {
977 wbits++;
978 wbitsMaxValue = 1 << wbits;
979 if (wbits == maxwbits)
980 {
981 dowbits = false;
982 break;
983 }
984 }
985 }
771 986
772 for (int o = 0; o < Constants.TerrainPatchSize; o++) 987 xr = x6r + x7i;
773 DCTLine16(block, ftemp, o); 988 xi = x7r - x6i;
774 for (int o = 0; o < Constants.TerrainPatchSize; o++)
775 wbits = DCTColumn16Wbits(ftemp, itemp, o, wbits, maxWbits);
776 989
777 return itemp; 990 //tmp[3 * Constants.TerrainPatchSize + k] = C16_3R * xr - C16_3I * xi; //
778 } 991 ftmp = C16_3R * xr - C16_3I * xi;
992 indx = 3 * Constants.TerrainPatchSize + k;
993 itmp = (int)(ftmp * QuantizeTable16[indx]);
994 iout[CopyMatrix16[indx]] = itmp;
779 995
780 private static int[] CompressPatch(float[,] patchData, TerrainPatch.Header header, int prequant, out int wbits) 996 if (dowbits)
781 { 997 {
782 float[] block = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 998 if (itmp < 0) itmp *= -1;
783 float oozrange = 1.0f/header.Range; 999 while (itmp > wbitsMaxValue)
784 float range = (1 << prequant); 1000 {
785 float premult = oozrange*range; 1001 wbits++;
786 float sub = (1 << (prequant - 1)) + header.DCOffset*premult; 1002 wbitsMaxValue = 1 << wbits;
787 int wordsize = (prequant - 2) & 0x0f; 1003 if (wbits == maxwbits)
1004 {
1005 dowbits = false;
1006 break;
1007 }
1008 }
1009 }
788 1010
789 header.QuantWBits = wordsize; 1011 //tmp[13 * Constants.TerrainPatchSize + k] = C16_3R * xi + C16_3I * xr; //
790 header.QuantWBits |= wordsize << 4; 1012 ftmp = C16_3R * xi + C16_3I * xr;
1013 indx = 13 * Constants.TerrainPatchSize + k;
1014 itmp = (int)(ftmp * QuantizeTable16[indx]);
1015 iout[CopyMatrix16[indx]] = itmp;
791 1016
792 int k = 0; 1017 if (dowbits)
793 for (int j = 0; j < Constants.TerrainPatchSize; j++) 1018 {
794 { 1019 if (itmp < 0) itmp *= -1;
795 for (int i = 0; i < Constants.TerrainPatchSize; i++) 1020 while (itmp > wbitsMaxValue)
796 block[k++] = patchData[j, i]*premult - sub; 1021 {
1022 wbits++;
1023 wbitsMaxValue = 1 << wbits;
1024 if (wbits == maxwbits)
1025 {
1026 dowbits = false;
1027 break;
1028 }
1029 }
1030 }
797 } 1031 }
1032 }
798 1033
799 float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 1034 #endregion DCT
800 int[] itemp = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
801
802 int maxWbits = prequant + 5;
803 wbits = (prequant >> 1);
804 1035
805 for (int o = 0; o < Constants.TerrainPatchSize; o++) 1036 #region Decode
806 DCTLine16(block, ftemp, o); 1037 /*
807 for (int o = 0; o < Constants.TerrainPatchSize; o++) 1038 public static TerrainPatch.Header DecodePatchHeader(BitPack bitpack)
808 wbits = DCTColumn16Wbits(ftemp, itemp, o, wbits, maxWbits); 1039 {
1040 TerrainPatch.Header header = new TerrainPatch.Header { QuantWBits = bitpack.UnpackBits(8) };
809 1041
810 return itemp; 1042 // Quantized word bits
811 } 1043 if (header.QuantWBits == END_OF_PATCHES)
1044 return header;
812 1045
813 private static int[] CompressPatch(TerrainData terrData, int patchX, int patchY, TerrainPatch.Header header, 1046 // DC offset
814 int prequant, out int wbits) 1047 header.DCOffset = bitpack.UnpackFloat();
815 {
816 float[] block = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
817 int wordsize = prequant;
818 float oozrange = 1.0f/header.Range;
819 float range = (1 << prequant);
820 float premult = oozrange*range;
821 float sub = (1 << (prequant - 1)) + header.DCOffset*premult;
822 1048
823 header.QuantWBits = wordsize - 2; 1049 // Range
824 header.QuantWBits |= (prequant - 2) << 4; 1050 header.Range = bitpack.UnpackBits(16);
825 1051
826 int k = 0; 1052 // Patch IDs (10 bits)
1053 header.PatchIDs = bitpack.UnpackBits(10);
827 1054
828 int yPatchLimit = patchY >= (terrData.SizeY / Constants.TerrainPatchSize) ? 1055 // Word bits
829 (terrData.SizeY - Constants.TerrainPatchSize) / Constants.TerrainPatchSize : patchY; 1056 header.WordBits = (uint)((header.QuantWBits & 0x0f) + 2);
830 yPatchLimit = (yPatchLimit + 1) * Constants.TerrainPatchSize;
831 1057
832 int xPatchLimit = patchX >= (terrData.SizeX / Constants.TerrainPatchSize) ? 1058 return header;
833 (terrData.SizeX - Constants.TerrainPatchSize) / Constants.TerrainPatchSize : patchX; 1059 }
834 xPatchLimit = (xPatchLimit + 1) * Constants.TerrainPatchSize; 1060 */
835 1061
836 for (int yy = patchY * Constants.TerrainPatchSize; yy < yPatchLimit; yy++) 1062 /*
837 { 1063 public static void DecodePatch(int[] patches, BitPack bitpack, TerrainPatch.Header header, int size)
838 for (int xx = patchX * Constants.TerrainPatchSize; xx < xPatchLimit; xx++)
839 { 1064 {
840 block[k++] = terrData[xx, yy] * premult - sub; 1065 for (int n = 0; n < size * size; n++)
1066 {
1067 // ?
1068 int temp = bitpack.UnpackBits(1);
1069 if (temp != 0)
1070 {
1071 // Value or EOB
1072 temp = bitpack.UnpackBits(1);
1073 if (temp != 0)
1074 {
1075 // Value
1076 temp = bitpack.UnpackBits(1);
1077 if (temp != 0)
1078 {
1079 // Negative
1080 temp = bitpack.UnpackBits((int)header.WordBits);
1081 patches[n] = temp * -1;
1082 }
1083 else
1084 {
1085 // Positive
1086 temp = bitpack.UnpackBits((int)header.WordBits);
1087 patches[n] = temp;
1088 }
1089 }
1090 else
1091 {
1092 // Set the rest to zero
1093 // TODO: This might not be necessary
1094 for (int o = n; o < size * size; o++)
1095 {
1096 patches[o] = 0;
1097 }
1098 break;
1099 }
1100 }
1101 else
1102 {
1103 patches[n] = 0;
1104 }
1105 }
841 } 1106 }
842 } 1107 */
843 1108 #region IDCT
844 float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 1109 /* not in use
845 int[] itemp = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 1110 private static void IDCTColumn16(float[] linein, float[] lineout, int column)
846
847 int maxWbits = prequant + 5;
848 wbits = (prequant >> 1);
849
850 for (int o = 0; o < Constants.TerrainPatchSize; o++)
851 DCTLine16(block, ftemp, o);
852 for (int o = 0; o < Constants.TerrainPatchSize; o++)
853 wbits = DCTColumn16Wbits(ftemp, itemp, o, wbits, maxWbits);
854
855 return itemp;
856 }
857
858 #region Initialization
859
860 private static void BuildDequantizeTable16()
861 { 1111 {
862 for (int j = 0; j < Constants.TerrainPatchSize; j++) 1112 for (int n = 0; n < Constants.TerrainPatchSize; n++)
863 { 1113 {
864 for (int i = 0; i < Constants.TerrainPatchSize; i++) 1114 float total = OO_SQRT2 * linein[column];
1115
1116 for (int u = 1; u < Constants.TerrainPatchSize; u++)
865 { 1117 {
866 DequantizeTable16[j*Constants.TerrainPatchSize + i] = 1.0f + 2.0f*(i + j); 1118 int usize = u * Constants.TerrainPatchSize;
1119 total += linein[usize + column] * CosineTable16[usize + n];
867 } 1120 }
1121
1122 lineout[Constants.TerrainPatchSize * n + column] = total;
868 } 1123 }
869 } 1124 }
870 1125
871 private static void BuildQuantizeTable16() 1126 private static void IDCTLine16(float[] linein, float[] lineout, int line)
872 { 1127 {
873 const float oosob = 2.0f/Constants.TerrainPatchSize; 1128 const float oosob = 2.0f / Constants.TerrainPatchSize;
874 for (int j = 0; j < Constants.TerrainPatchSize; j++) 1129 int lineSize = line * Constants.TerrainPatchSize;
1130
1131 for (int n = 0; n < Constants.TerrainPatchSize; n++)
875 { 1132 {
876 for (int i = 0; i < Constants.TerrainPatchSize; i++) 1133 float total = OO_SQRT2 * linein[lineSize];
1134
1135 for (int u = 1; u < Constants.TerrainPatchSize; u++)
877 { 1136 {
878// QuantizeTable16[j * Constants.TerrainPatchSize + i] = 1.0f / (1.0f + 2.0f * ((float)i + (float)j)); 1137 total += linein[lineSize + u] * CosineTable16[u * Constants.TerrainPatchSize + n];
879 QuantizeTable16[j*Constants.TerrainPatchSize + i] = oosob/(1.0f + 2.0f*(i + (float) j));
880 } 1138 }
1139
1140 lineout[lineSize + n] = total * oosob;
881 } 1141 }
882 } 1142 }
883 1143
1144/*
884 private static void SetupCosines16() 1145 private static void SetupCosines16()
885 { 1146 {
886 const float hposz = (float) Math.PI*0.5f/Constants.TerrainPatchSize; 1147 const float hposz = (float)Math.PI * 0.5f / Constants.TerrainPatchSize;
887 1148
888 for (int u = 0; u < Constants.TerrainPatchSize; u++) 1149 for (int u = 0; u < Constants.TerrainPatchSize; u++)
889 { 1150 {
890 for (int n = 0; n < Constants.TerrainPatchSize; n++) 1151 for (int n = 0; n < Constants.TerrainPatchSize; n++)
891 { 1152 {
892 CosineTable16[u*Constants.TerrainPatchSize + n] = (float) Math.Cos((2.0f*n + 1.0f)*u*hposz); 1153 CosineTable16[u * Constants.TerrainPatchSize + n] = (float)Math.Cos((2.0f * n + 1.0f) * u * hposz);
893 } 1154 }
894 } 1155 }
895 } 1156 }
1157*/
1158 //not in use, and still not fixed
1159 /*
1160 static void idct16x16(float[] a)
1161 {
1162 int j;
1163 float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
1164 float x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i;
1165 float xr, xi;
896 1166
897 private static void BuildCopyMatrix16() 1167 int fullSize = Constants.TerrainPatchSize * Constants.TerrainPatchSize;
898 {
899 bool diag = false;
900 bool right = true;
901 int i = 0;
902 int j = 0;
903 int count = 0;
904
905 while (i < Constants.TerrainPatchSize && j < Constants.TerrainPatchSize)
906 {
907 CopyMatrix16[j*Constants.TerrainPatchSize + i] = count++;
908
909 if (!diag)
910 {
911 if (right)
912 {
913 if (i < Constants.TerrainPatchSize - 1) i++;
914 else j++;
915
916 right = false;
917 diag = true;
918 }
919 else
920 {
921 if (j < Constants.TerrainPatchSize - 1) j++;
922 else i++;
923 1168
924 right = true; 1169 for (j = 0; j < fullSize; j += Constants.TerrainPatchSize)
925 diag = true; 1170 {
926 } 1171 x5r = C16_1R * tmp[1 + j] + C16_1I * tmp[15 + j];
927 } 1172 x5i = C16_1R * tmp[15 + j] - C16_1I * tmp[1 + j];
928 else 1173 xr = C16_7R * tmp[7 + j] + C16_7I * tmp[9 + j];
929 { 1174 xi = C16_7R * tmp[9 + j] - C16_7I * tmp[7 + j];
930 if (right) 1175 x4r = x5r + xr;
931 { 1176 x4i = x5i - xi;
932 i++; 1177 x5r -= xr;
933 j--; 1178 x5i += xi;
934 if (i == Constants.TerrainPatchSize - 1 || j == 0) diag = false; 1179 x7r = C16_5R * tmp[5 + j] + C16_5I * tmp[11 + j];
935 } 1180 x7i = C16_5R * tmp[11 + j] - C16_5I * tmp[5 + j];
936 else 1181 xr = C16_3R * tmp[3 + j] + C16_3I * tmp[13 + j];
937 { 1182 xi = C16_3R * tmp[13 + j] - C16_3I * tmp[3 + j];
938 i--; 1183 x6r = x7r + xr;
939 j++; 1184 x6i = x7i - xi;
940 if (j == Constants.TerrainPatchSize - 1 || i == 0) diag = false; 1185 x7r -= xr;
941 } 1186 x7i += xi;
942 } 1187 xr = x4r - x6r;
943 } 1188 xi = x4i - x6i;
944 } 1189 x4r += x6r;
945 1190 x4i += x6i;
946 #endregion Initialization 1191 x6r = W16_8R * (xi + xr);
1192 x6i = W16_8R * (xi - xr);
1193 xr = x5r + x7i;
1194 xi = x5i - x7r;
1195 x5r -= x7i;
1196 x5i += x7r;
1197 x7r = W16_4I * x5r + W16_4R * x5i;
1198 x7i = W16_4I * x5i - W16_4R * x5r;
1199 x5r = W16_4R * xr + W16_4I * xi;
1200 x5i = W16_4R * xi - W16_4I * xr;
1201 xr = C16_4R * tmp[4 + j] + C16_4I * tmp[12 + j];
1202 xi = C16_4R * tmp[12 + j] - C16_4I * tmp[4 + j];
1203 x2r = C16_8R * (tmp[0 + j] + tmp[8 + j]);
1204 x3r = C16_8R * (tmp[0 + j] - tmp[8 + j]);
1205 x0r = x2r + xr;
1206 x1r = x3r + xi;
1207 x2r -= xr;
1208 x3r -= xi;
1209 x0i = C16_2R * tmp[2 + j] + C16_2I * tmp[14 + j];
1210 x2i = C16_2R * tmp[14 + j] - C16_2I * tmp[2 + j];
1211 x1i = C16_6R * tmp[6 + j] + C16_6I * tmp[10 + j];
1212 x3i = C16_6R * tmp[10 + j] - C16_6I * tmp[6 + j];
1213 xr = x0i - x1i;
1214 xi = x2i + x3i;
1215 x0i += x1i;
1216 x2i -= x3i;
1217 x1i = W16_8R * (xi + xr);
1218 x3i = W16_8R * (xi - xr);
1219 xr = x0r + x0i;
1220 xi = x0r - x0i;
1221 tmp[0 + j] = xr + x4r;
1222 tmp[15 + j] = xr - x4r;
1223 tmp[8 + j] = xi + x4i;
1224 tmp[7 + j] = xi - x4i;
1225 xr = x1r + x1i;
1226 xi = x1r - x1i;
1227 tmp[2 + j] = xr + x5r;
1228 tmp[13 + j] = xr - x5r;
1229 tmp[10 + j] = xi + x5i;
1230 tmp[5 + j] = xi - x5i;
1231 xr = x2r + x2i;
1232 xi = x2r - x2i;
1233 tmp[4 + j] = xr + x6r;
1234 tmp[11 + j] = xr - x6r;
1235 tmp[12 + j] = xi + x6i;
1236 tmp[3 + j] = xi - x6i;
1237 xr = x3r + x3i;
1238 xi = x3r - x3i;
1239 tmp[6 + j] = xr + x7r;
1240 tmp[9 + j] = xr - x7r;
1241 tmp[14 + j] = xi + x7i;
1242 tmp[1 + j] = xi - x7i;
1243 }
1244 for (j = 0; j < fullSize; j += Constants.TerrainPatchSize)
1245 {
1246 x5r = C16_1R * tmp[j + 1] + C16_1I * tmp[j + 15];
1247 x5i = C16_1R * tmp[j + 15] - C16_1I * tmp[j + 1];
1248 xr = C16_7R * tmp[j + 7] + C16_7I * tmp[j + 9];
1249 xi = C16_7R * tmp[j + 9] - C16_7I * tmp[j + 7];
1250 x4r = x5r + xr;
1251 x4i = x5i - xi;
1252 x5r -= xr;
1253 x5i += xi;
1254 x7r = C16_5R * tmp[j + 5] + C16_5I * tmp[j + 11];
1255 x7i = C16_5R * tmp[j + 11] - C16_5I * tmp[j + 5];
1256 xr = C16_3R * tmp[j + 3] + C16_3I * tmp[j + 13];
1257 xi = C16_3R * tmp[j + 13] - C16_3I * tmp[j + 3];
1258 x6r = x7r + xr;
1259 x6i = x7i - xi;
1260 x7r -= xr;
1261 x7i += xi;
1262 xr = x4r - x6r;
1263 xi = x4i - x6i;
1264 x4r += x6r;
1265 x4i += x6i;
1266 x6r = W16_8R * (xi + xr);
1267 x6i = W16_8R * (xi - xr);
1268 xr = x5r + x7i;
1269 xi = x5i - x7r;
1270 x5r -= x7i;
1271 x5i += x7r;
1272 x7r = W16_4I * x5r + W16_4R * x5i;
1273 x7i = W16_4I * x5i - W16_4R * x5r;
1274 x5r = W16_4R * xr + W16_4I * xi;
1275 x5i = W16_4R * xi - W16_4I * xr;
1276 xr = C16_4R * tmp[j + 4] + C16_4I * tmp[j + 12];
1277 xi = C16_4R * tmp[j + 12] - C16_4I * tmp[j + 4];
1278 x2r = C16_8R * (tmp[j + 0] + tmp[j + 8]);
1279 x3r = C16_8R * (tmp[j + 0] - tmp[j + 8]);
1280 x0r = x2r + xr;
1281 x1r = x3r + xi;
1282 x2r -= xr;
1283 x3r -= xi;
1284 x0i = C16_2R * tmp[j + 2] + C16_2I * tmp[j + 14];
1285 x2i = C16_2R * tmp[j + 14] - C16_2I * tmp[j + 2];
1286 x1i = C16_6R * tmp[j + 6] + C16_6I * tmp[j + 10];
1287 x3i = C16_6R * tmp[j + 10] - C16_6I * tmp[j + 6];
1288 xr = x0i - x1i;
1289 xi = x2i + x3i;
1290 x0i += x1i;
1291 x2i -= x3i;
1292 x1i = W16_8R * (xi + xr);
1293 x3i = W16_8R * (xi - xr);
1294 xr = x0r + x0i;
1295 xi = x0r - x0i;
1296 tmp[j + 0] = xr + x4r;
1297 tmp[j + 15] = xr - x4r;
1298 tmp[j + 8] = xi + x4i;
1299 tmp[j + 7] = xi - x4i;
1300 xr = x1r + x1i;
1301 xi = x1r - x1i;
1302 tmp[j + 2] = xr + x5r;
1303 tmp[j + 13] = xr - x5r;
1304 tmp[j + 10] = xi + x5i;
1305 tmp[j + 5] = xi - x5i;
1306 xr = x2r + x2i;
1307 xi = x2r - x2i;
1308 tmp[j + 4] = xr + x6r;
1309 tmp[j + 11] = xr - x6r;
1310 tmp[j + 12] = xi + x6i;
1311 tmp[j + 3] = xi - x6i;
1312 xr = x3r + x3i;
1313 xi = x3r - x3i;
1314 tmp[j + 6] = xr + x7r;
1315 tmp[j + 9] = xr - x7r;
1316 tmp[j + 14] = xi + x7i;
1317 tmp[j + 1] = xi - x7i;
1318 }
1319 }
1320 */
1321 #endregion IDCT
1322 #endregion Decode
947 } 1323 }
1324
948} 1325}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/BorderTests.cs b/OpenSim/Region/Framework/Scenes/Tests/BorderTests.cs
deleted file mode 100644
index e209221..0000000
--- a/OpenSim/Region/Framework/Scenes/Tests/BorderTests.cs
+++ /dev/null
@@ -1,340 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.IO;
31using System.Text;
32using NUnit.Framework;
33using OpenMetaverse;
34using OpenSim.Region.Framework.Scenes;
35using OpenSim.Tests.Common;
36
37namespace OpenSim.Region.Framework.Scenes.Tests
38{
39 [TestFixture]
40 public class BorderTests : OpenSimTestCase
41 {
42 [Test]
43 public void TestCross()
44 {
45 TestHelpers.InMethod();
46
47 List<Border> testborders = new List<Border>();
48
49 Border NorthBorder = new Border();
50 NorthBorder.BorderLine = new Vector3(0, 256, 256); //<---
51 NorthBorder.CrossDirection = Cardinals.N;
52 testborders.Add(NorthBorder);
53
54 Border SouthBorder = new Border();
55 SouthBorder.BorderLine = new Vector3(0, 256, 0); //--->
56 SouthBorder.CrossDirection = Cardinals.S;
57 testborders.Add(SouthBorder);
58
59 Border EastBorder = new Border();
60 EastBorder.BorderLine = new Vector3(0, 256, 256); //<---
61 EastBorder.CrossDirection = Cardinals.E;
62 testborders.Add(EastBorder);
63
64 Border WestBorder = new Border();
65 WestBorder.BorderLine = new Vector3(0, 256, 0); //--->
66 WestBorder.CrossDirection = Cardinals.W;
67 testborders.Add(WestBorder);
68
69 Vector3 position = new Vector3(200,200,21);
70
71 foreach (Border b in testborders)
72 Assert.That(!b.TestCross(position));
73
74 position = new Vector3(200,280,21);
75 Assert.That(NorthBorder.TestCross(position));
76
77 // Test automatic border crossing
78 // by setting the border crossing aabb to be the whole region
79 position = new Vector3(25,25,21); // safely within one 256m region
80
81 // The Z value of the BorderLine is reversed, making all positions within the region
82 // trigger bordercross
83
84 SouthBorder.BorderLine = new Vector3(0,256,256); // automatic border cross in the region
85 Assert.That(SouthBorder.TestCross(position));
86
87 NorthBorder.BorderLine = new Vector3(0, 256, 0); // automatic border cross in the region
88 Assert.That(NorthBorder.TestCross(position));
89
90 EastBorder.BorderLine = new Vector3(0, 256, 0); // automatic border cross in the region
91 Assert.That(EastBorder.TestCross(position));
92
93 WestBorder.BorderLine = new Vector3(0, 256, 255); // automatic border cross in the region
94 Assert.That(WestBorder.TestCross(position));
95 }
96
97 [Test]
98 public void TestCrossSquare512()
99 {
100 TestHelpers.InMethod();
101
102 List<Border> testborders = new List<Border>();
103
104 Border NorthBorder = new Border();
105 NorthBorder.BorderLine = new Vector3(0, 512, 512);
106 NorthBorder.CrossDirection = Cardinals.N;
107 testborders.Add(NorthBorder);
108
109 Border SouthBorder = new Border();
110 SouthBorder.BorderLine = new Vector3(0, 512, 0);
111 SouthBorder.CrossDirection = Cardinals.S;
112 testborders.Add(SouthBorder);
113
114 Border EastBorder = new Border();
115 EastBorder.BorderLine = new Vector3(0, 512, 512);
116 EastBorder.CrossDirection = Cardinals.E;
117 testborders.Add(EastBorder);
118
119 Border WestBorder = new Border();
120 WestBorder.BorderLine = new Vector3(0, 512, 0);
121 WestBorder.CrossDirection = Cardinals.W;
122 testborders.Add(WestBorder);
123
124 Vector3 position = new Vector3(450,220,21);
125
126 foreach (Border b in testborders)
127 {
128 Assert.That(!b.TestCross(position));
129
130 }
131
132 //Trigger east border
133 position = new Vector3(513,220,21);
134 foreach (Border b in testborders)
135 {
136 if (b.CrossDirection == Cardinals.E)
137 Assert.That(b.TestCross(position));
138 else
139 Assert.That(!b.TestCross(position));
140
141 }
142
143 //Trigger west border
144 position = new Vector3(-1, 220, 21);
145 foreach (Border b in testborders)
146 {
147 if (b.CrossDirection == Cardinals.W)
148 Assert.That(b.TestCross(position));
149 else
150 Assert.That(!b.TestCross(position));
151
152 }
153
154 //Trigger north border
155 position = new Vector3(220, 513, 21);
156 foreach (Border b in testborders)
157 {
158 if (b.CrossDirection == Cardinals.N)
159 Assert.That(b.TestCross(position));
160 else
161 Assert.That(!b.TestCross(position));
162
163 }
164
165 //Trigger south border
166 position = new Vector3(220, -1, 21);
167 foreach (Border b in testborders)
168 {
169 if (b.CrossDirection == Cardinals.S)
170 Assert.That(b.TestCross(position));
171 else
172 Assert.That(!b.TestCross(position));
173
174 }
175 }
176
177 [Test]
178 public void TestCrossRectangle512x256()
179 {
180 TestHelpers.InMethod();
181
182 List<Border> testborders = new List<Border>();
183
184 Border NorthBorder = new Border();
185 NorthBorder.BorderLine = new Vector3(0, 512, 256);
186 NorthBorder.CrossDirection = Cardinals.N;
187 testborders.Add(NorthBorder);
188
189 Border SouthBorder = new Border();
190 SouthBorder.BorderLine = new Vector3(0, 512, 0);
191 SouthBorder.CrossDirection = Cardinals.S;
192 testborders.Add(SouthBorder);
193
194 Border EastBorder = new Border();
195 EastBorder.BorderLine = new Vector3(0, 256, 512);
196 EastBorder.CrossDirection = Cardinals.E;
197 testborders.Add(EastBorder);
198
199 Border WestBorder = new Border();
200 WestBorder.BorderLine = new Vector3(0, 256, 0);
201 WestBorder.CrossDirection = Cardinals.W;
202 testborders.Add(WestBorder);
203
204 Vector3 position = new Vector3(450, 220, 21);
205
206 foreach (Border b in testborders)
207 {
208 Assert.That(!b.TestCross(position));
209
210 }
211
212 //Trigger east border
213 position = new Vector3(513, 220, 21);
214 foreach (Border b in testborders)
215 {
216 if (b.CrossDirection == Cardinals.E)
217 Assert.That(b.TestCross(position));
218 else
219 Assert.That(!b.TestCross(position));
220
221 }
222
223 //Trigger west border
224 position = new Vector3(-1, 220, 21);
225 foreach (Border b in testborders)
226 {
227 if (b.CrossDirection == Cardinals.W)
228 Assert.That(b.TestCross(position));
229 else
230 Assert.That(!b.TestCross(position));
231
232 }
233
234 //Trigger north border
235 position = new Vector3(220, 257, 21);
236 foreach (Border b in testborders)
237 {
238 if (b.CrossDirection == Cardinals.N)
239 Assert.That(b.TestCross(position));
240 else
241 Assert.That(!b.TestCross(position));
242
243 }
244
245 //Trigger south border
246 position = new Vector3(220, -1, 21);
247 foreach (Border b in testborders)
248 {
249 if (b.CrossDirection == Cardinals.S)
250 Assert.That(b.TestCross(position));
251 else
252 Assert.That(!b.TestCross(position));
253
254 }
255 }
256
257 [Test]
258 public void TestCrossOdd512x512w256hole()
259 {
260 TestHelpers.InMethod();
261
262 List<Border> testborders = new List<Border>();
263 // 512____
264 // | |
265 // 256__| |___
266 // | |
267 // |______|
268 // 0 | 512
269 // 256
270
271 // Compound North border since the hole is at the top
272 Border NorthBorder1 = new Border();
273 NorthBorder1.BorderLine = new Vector3(0, 256, 512);
274 NorthBorder1.CrossDirection = Cardinals.N;
275 testborders.Add(NorthBorder1);
276
277 Border NorthBorder2 = new Border();
278 NorthBorder2.BorderLine = new Vector3(256, 512, 256);
279 NorthBorder2.CrossDirection = Cardinals.N;
280 testborders.Add(NorthBorder2);
281
282 Border SouthBorder = new Border();
283 SouthBorder.BorderLine = new Vector3(0, 512, 0);
284 SouthBorder.CrossDirection = Cardinals.S;
285 testborders.Add(SouthBorder);
286
287 //Compound East border
288 Border EastBorder1 = new Border();
289 EastBorder1.BorderLine = new Vector3(0, 256, 512);
290 EastBorder1.CrossDirection = Cardinals.E;
291 testborders.Add(EastBorder1);
292
293 Border EastBorder2 = new Border();
294 EastBorder2.BorderLine = new Vector3(257, 512, 256);
295 EastBorder2.CrossDirection = Cardinals.E;
296 testborders.Add(EastBorder2);
297
298
299
300 Border WestBorder = new Border();
301 WestBorder.BorderLine = new Vector3(0, 512, 0);
302 WestBorder.CrossDirection = Cardinals.W;
303 testborders.Add(WestBorder);
304
305 Vector3 position = new Vector3(450, 220, 21);
306
307 foreach (Border b in testborders)
308 {
309 Assert.That(!b.TestCross(position));
310
311 }
312
313 position = new Vector3(220, 450, 21);
314
315 foreach (Border b in testborders)
316 {
317 Assert.That(!b.TestCross(position));
318
319 }
320
321 bool result = false;
322 int bordersTriggered = 0;
323
324 position = new Vector3(450, 450, 21);
325
326 foreach (Border b in testborders)
327 {
328 if (b.TestCross(position))
329 {
330 bordersTriggered++;
331 result = true;
332 }
333 }
334
335 Assert.That(result);
336 Assert.That(bordersTriggered == 2);
337
338 }
339 }
340}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs b/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs
index da18941..fa698a9 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs
@@ -50,7 +50,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
50 public void T010_AddObjects() 50 public void T010_AddObjects()
51 { 51 {
52 TestHelpers.InMethod(); 52 TestHelpers.InMethod();
53 53
54 random = new Random(); 54 random = new Random();
55 SceneObjectGroup found; 55 SceneObjectGroup found;
56 EntityManager entman = new EntityManager(); 56 EntityManager entman = new EntityManager();
@@ -62,7 +62,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
62 UUID obj2 = sog.UUID; 62 UUID obj2 = sog.UUID;
63 uint li2 = sog.LocalId; 63 uint li2 = sog.LocalId;
64 entman.Add(sog); 64 entman.Add(sog);
65 65
66 found = (SceneObjectGroup)entman[obj1]; 66 found = (SceneObjectGroup)entman[obj1];
67 Assert.That(found.UUID ,Is.EqualTo(obj1)); 67 Assert.That(found.UUID ,Is.EqualTo(obj1));
68 found = (SceneObjectGroup)entman[li1]; 68 found = (SceneObjectGroup)entman[li1];
@@ -85,15 +85,15 @@ namespace OpenSim.Region.Framework.Scenes.Tests
85 public void T011_ThreadAddRemoveTest() 85 public void T011_ThreadAddRemoveTest()
86 { 86 {
87 TestHelpers.InMethod(); 87 TestHelpers.InMethod();
88 88
89 // This test adds and removes with mutiple threads, attempting to break the 89 // This test adds and removes with mutiple threads, attempting to break the
90 // uuid and localid dictionary coherence. 90 // uuid and localid dictionary coherence.
91 EntityManager entman = new EntityManager(); 91 EntityManager entman = new EntityManager();
92 SceneObjectGroup sog = NewSOG(); 92 SceneObjectGroup sog = NewSOG();
93 for (int j=0; j<20; j++) 93 for (int j=0; j<20; j++)
94 { 94 {
95 List<Thread> trdlist = new List<Thread>(); 95 List<Thread> trdlist = new List<Thread>();
96 96
97 for (int i=0; i<4; i++) 97 for (int i=0; i<4; i++)
98 { 98 {
99 // Adds scene object 99 // Adds scene object
@@ -101,14 +101,14 @@ namespace OpenSim.Region.Framework.Scenes.Tests
101 Thread start = new Thread(new ThreadStart(test.TestAddSceneObject)); 101 Thread start = new Thread(new ThreadStart(test.TestAddSceneObject));
102 start.Start(); 102 start.Start();
103 trdlist.Add(start); 103 trdlist.Add(start);
104 104
105 // Removes it 105 // Removes it
106 test = new NewTestThreads(entman,sog); 106 test = new NewTestThreads(entman,sog);
107 start = new Thread(new ThreadStart(test.TestRemoveSceneObject)); 107 start = new Thread(new ThreadStart(test.TestRemoveSceneObject));
108 start.Start(); 108 start.Start();
109 trdlist.Add(start); 109 trdlist.Add(start);
110 } 110 }
111 foreach (Thread thread in trdlist) 111 foreach (Thread thread in trdlist)
112 { 112 {
113 thread.Join(); 113 thread.Join();
114 } 114 }
@@ -133,14 +133,14 @@ namespace OpenSim.Region.Framework.Scenes.Tests
133 133
134 SceneObjectGroup sog = new SceneObjectGroup(sop); 134 SceneObjectGroup sog = new SceneObjectGroup(sop);
135 scene.AddNewSceneObject(sog, false); 135 scene.AddNewSceneObject(sog, false);
136 136
137 return sog; 137 return sog;
138 } 138 }
139 139
140 private static string RandomName() 140 private static string RandomName()
141 { 141 {
142 StringBuilder name = new StringBuilder(); 142 StringBuilder name = new StringBuilder();
143 int size = random.Next(40,80); 143 int size = random.Next(40,80);
144 char ch ; 144 char ch ;
145 for (int i=0; i<size; i++) 145 for (int i=0; i<size; i++)
146 { 146 {
@@ -156,7 +156,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
156 private EntityManager entman; 156 private EntityManager entman;
157 private SceneObjectGroup sog; 157 private SceneObjectGroup sog;
158 private Random random; 158 private Random random;
159 159
160 public NewTestThreads(EntityManager entman, SceneObjectGroup sog) 160 public NewTestThreads(EntityManager entman, SceneObjectGroup sog)
161 { 161 {
162 this.entman = entman; 162 this.entman = entman;
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs
index ee7c8a9..4d2eb3f 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs
@@ -55,29 +55,29 @@ namespace OpenSim.Region.Framework.Scenes.Tests
55 UUID part2Id = new UUID("00000000-0000-0000-0000-000000000002"); 55 UUID part2Id = new UUID("00000000-0000-0000-0000-000000000002");
56 56
57 SceneObjectPart part1 57 SceneObjectPart part1
58 = new SceneObjectPart(ownerId, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero) 58 = new SceneObjectPart(ownerId, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero)
59 { Name = part1Name, UUID = part1Id }; 59 { Name = part1Name, UUID = part1Id };
60 SceneObjectGroup so = new SceneObjectGroup(part1); 60 SceneObjectGroup so = new SceneObjectGroup(part1);
61 SceneObjectPart part2 61 SceneObjectPart part2
62 = new SceneObjectPart(ownerId, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero) 62 = new SceneObjectPart(ownerId, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero)
63 { Name = part2Name, UUID = part2Id }; 63 { Name = part2Name, UUID = part2Id };
64 so.AddPart(part2); 64 so.AddPart(part2);
65 65
66 scene.AddNewSceneObject(so, false); 66 scene.AddNewSceneObject(so, false);
67 67
68 SceneObjectGroup dupeSo 68 SceneObjectGroup dupeSo
69 = scene.SceneGraph.DuplicateObject( 69 = scene.SceneGraph.DuplicateObject(
70 part1.LocalId, new Vector3(10, 0, 0), 0, ownerId, UUID.Zero, Quaternion.Identity); 70 part1.LocalId, new Vector3(10, 0, 0), ownerId, UUID.Zero, Quaternion.Identity, false);
71 Assert.That(dupeSo.Parts.Length, Is.EqualTo(2)); 71 Assert.That(dupeSo.Parts.Length, Is.EqualTo(2));
72 72
73 SceneObjectPart dupePart1 = dupeSo.GetLinkNumPart(1); 73 SceneObjectPart dupePart1 = dupeSo.GetLinkNumPart(1);
74 SceneObjectPart dupePart2 = dupeSo.GetLinkNumPart(2); 74 SceneObjectPart dupePart2 = dupeSo.GetLinkNumPart(2);
75 Assert.That(dupePart1.LocalId, Is.Not.EqualTo(part1.LocalId)); 75 Assert.That(dupePart1.LocalId, Is.Not.EqualTo(part1.LocalId));
76 Assert.That(dupePart2.LocalId, Is.Not.EqualTo(part2.LocalId)); 76 Assert.That(dupePart2.LocalId, Is.Not.EqualTo(part2.LocalId));
77 77
78 Assert.That(dupePart1.Flags, Is.EqualTo(part1.Flags)); 78 Assert.That(dupePart1.Flags, Is.EqualTo(part1.Flags));
79 Assert.That(dupePart2.Flags, Is.EqualTo(part2.Flags)); 79 Assert.That(dupePart2.Flags, Is.EqualTo(part2.Flags));
80 80
81 /* 81 /*
82 Assert.That(part1.PhysActor, Is.Not.Null); 82 Assert.That(part1.PhysActor, Is.Not.Null);
83 Assert.That(part2.PhysActor, Is.Not.Null); 83 Assert.That(part2.PhysActor, Is.Not.Null);
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs
index 098f1b4..8961a26 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs
@@ -99,7 +99,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
99 Assert.That(scene.AddNewSceneObject(so, false), Is.True); 99 Assert.That(scene.AddNewSceneObject(so, false), Is.True);
100 SceneObjectGroup retrievedSo = scene.GetSceneObjectGroup(so.UUID); 100 SceneObjectGroup retrievedSo = scene.GetSceneObjectGroup(so.UUID);
101 SceneObjectPart[] retrievedParts = retrievedSo.Parts; 101 SceneObjectPart[] retrievedParts = retrievedSo.Parts;
102 102
103 //m_log.Debug("retrievedPart : {0}", retrievedPart); 103 //m_log.Debug("retrievedPart : {0}", retrievedPart);
104 // If the parts have the same UUID then we will consider them as one and the same 104 // If the parts have the same UUID then we will consider them as one and the same
105 Assert.That(retrievedSo.PrimCount, Is.EqualTo(partsToTestCount)); 105 Assert.That(retrievedSo.PrimCount, Is.EqualTo(partsToTestCount));
@@ -126,19 +126,19 @@ namespace OpenSim.Region.Framework.Scenes.Tests
126 UUID objUuid = new UUID("00000000-0000-0000-0000-000000000001"); 126 UUID objUuid = new UUID("00000000-0000-0000-0000-000000000001");
127 127
128 SceneObjectPart part1 128 SceneObjectPart part1
129 = new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero) 129 = new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero)
130 { Name = obj1Name, UUID = objUuid }; 130 { Name = obj1Name, UUID = objUuid };
131 131
132 Assert.That(scene.AddNewSceneObject(new SceneObjectGroup(part1), false), Is.True); 132 Assert.That(scene.AddNewSceneObject(new SceneObjectGroup(part1), false), Is.True);
133 133
134 SceneObjectPart part2 134 SceneObjectPart part2
135 = new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero) 135 = new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero)
136 { Name = obj2Name, UUID = objUuid }; 136 { Name = obj2Name, UUID = objUuid };
137 137
138 Assert.That(scene.AddNewSceneObject(new SceneObjectGroup(part2), false), Is.False); 138 Assert.That(scene.AddNewSceneObject(new SceneObjectGroup(part2), false), Is.False);
139 139
140 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(objUuid); 140 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(objUuid);
141 141
142 //m_log.Debug("retrievedPart : {0}", retrievedPart); 142 //m_log.Debug("retrievedPart : {0}", retrievedPart);
143 // If the parts have the same UUID then we will consider them as one and the same 143 // If the parts have the same UUID then we will consider them as one and the same
144 Assert.That(retrievedPart.Name, Is.EqualTo(obj1Name)); 144 Assert.That(retrievedPart.Name, Is.EqualTo(obj1Name));
@@ -171,13 +171,16 @@ namespace OpenSim.Region.Framework.Scenes.Tests
171 // Test that we don't get back an object for a local id that doesn't exist 171 // Test that we don't get back an object for a local id that doesn't exist
172 Assert.That(scene.GetGroupByPrim(999), Is.Null); 172 Assert.That(scene.GetGroupByPrim(999), Is.Null);
173 173
174 uint soid = so.LocalId;
175 uint spid = parts[partsToTestCount - 1].LocalId;
176
174 // Now delete the scene object and check again 177 // Now delete the scene object and check again
175 scene.DeleteSceneObject(so, false); 178 scene.DeleteSceneObject(so, false);
176 179
177 Assert.That(scene.GetGroupByPrim(so.LocalId), Is.Null); 180 Assert.That(scene.GetGroupByPrim(soid), Is.Null);
178 Assert.That(scene.GetGroupByPrim(parts[partsToTestCount - 1].LocalId), Is.Null); 181 Assert.That(scene.GetGroupByPrim(spid), Is.Null);
179 } 182 }
180 183
181 /// <summary> 184 /// <summary>
182 /// Test deleting an object from a scene. 185 /// Test deleting an object from a scene.
183 /// </summary> 186 /// </summary>
@@ -194,18 +197,18 @@ namespace OpenSim.Region.Framework.Scenes.Tests
194 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene); 197 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene);
195 198
196 Assert.That(so.IsDeleted, Is.False); 199 Assert.That(so.IsDeleted, Is.False);
200 uint retrievedPartID = so.LocalId;
197 201
198 scene.DeleteSceneObject(so, false); 202 scene.DeleteSceneObject(so, false);
199 203
200 Assert.That(so.IsDeleted, Is.True); 204 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(retrievedPartID);
201 205
202 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(so.LocalId);
203 Assert.That(retrievedPart, Is.Null); 206 Assert.That(retrievedPart, Is.Null);
204 } 207 }
205 208
206 /// <summary> 209 /// <summary>
207 /// Changing a scene object uuid changes the root part uuid. This is a valid operation if the object is not 210 /// Changing a scene object uuid changes the root part uuid. This is a valid operation if the object is not
208 /// in a scene and is useful if one wants to supply a UUID directly rather than use the one generated by 211 /// in a scene and is useful if one wants to supply a UUID directly rather than use the one generated by
209 /// OpenSim. 212 /// OpenSim.
210 /// </summary> 213 /// </summary>
211 [Test] 214 [Test]
@@ -215,24 +218,24 @@ namespace OpenSim.Region.Framework.Scenes.Tests
215 UUID rootPartUuid = new UUID("00000000-0000-0000-0000-000000000001"); 218 UUID rootPartUuid = new UUID("00000000-0000-0000-0000-000000000001");
216 string childPartName = "childPart"; 219 string childPartName = "childPart";
217 UUID childPartUuid = new UUID("00000000-0000-0000-0001-000000000000"); 220 UUID childPartUuid = new UUID("00000000-0000-0000-0001-000000000000");
218 221
219 SceneObjectPart rootPart 222 SceneObjectPart rootPart
220 = new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero) 223 = new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero)
221 { Name = rootPartName, UUID = rootPartUuid }; 224 { Name = rootPartName, UUID = rootPartUuid };
222 SceneObjectPart linkPart 225 SceneObjectPart linkPart
223 = new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero) 226 = new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero)
224 { Name = childPartName, UUID = childPartUuid }; 227 { Name = childPartName, UUID = childPartUuid };
225 228
226 SceneObjectGroup sog = new SceneObjectGroup(rootPart); 229 SceneObjectGroup sog = new SceneObjectGroup(rootPart);
227 sog.AddPart(linkPart); 230 sog.AddPart(linkPart);
228 231
229 Assert.That(sog.UUID, Is.EqualTo(rootPartUuid)); 232 Assert.That(sog.UUID, Is.EqualTo(rootPartUuid));
230 Assert.That(sog.RootPart.UUID, Is.EqualTo(rootPartUuid)); 233 Assert.That(sog.RootPart.UUID, Is.EqualTo(rootPartUuid));
231 Assert.That(sog.Parts.Length, Is.EqualTo(2)); 234 Assert.That(sog.Parts.Length, Is.EqualTo(2));
232 235
233 UUID newRootPartUuid = new UUID("00000000-0000-0000-0000-000000000002"); 236 UUID newRootPartUuid = new UUID("00000000-0000-0000-0000-000000000002");
234 sog.UUID = newRootPartUuid; 237 sog.UUID = newRootPartUuid;
235 238
236 Assert.That(sog.UUID, Is.EqualTo(newRootPartUuid)); 239 Assert.That(sog.UUID, Is.EqualTo(newRootPartUuid));
237 Assert.That(sog.RootPart.UUID, Is.EqualTo(newRootPartUuid)); 240 Assert.That(sog.RootPart.UUID, Is.EqualTo(newRootPartUuid));
238 Assert.That(sog.Parts.Length, Is.EqualTo(2)); 241 Assert.That(sog.Parts.Length, Is.EqualTo(2));
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectCopyTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectCopyTests.cs
index 0b196c1..c27bc1a 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>
@@ -86,7 +87,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
86 87
87 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test. 88 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test.
88 AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter; 89 AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter;
89 sogd.Enabled = false; 90 sogd.Enabled = false;
90 91
91 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, "so1", ua.PrincipalID); 92 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, "so1", ua.PrincipalID);
92 uint soLocalId = so.LocalId; 93 uint soLocalId = so.LocalId;
@@ -118,11 +119,11 @@ namespace OpenSim.Region.Framework.Scenes.Tests
118 119
119 // Check that object is still there. 120 // Check that object is still there.
120 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId); 121 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId);
121 Assert.That(retrievedPart2, Is.Not.Null); 122 Assert.That(retrievedPart2, Is.Not.Null);
122 Assert.That(client.ReceivedKills.Count, Is.EqualTo(0)); 123 Assert.That(client.ReceivedKills.Count, Is.EqualTo(0));
123 124
124 // Check that we have a copy in inventory 125 // Check that we have a copy in inventory
125 InventoryItemBase item 126 InventoryItemBase item
126 = UserInventoryHelpers.GetInventoryItem(scene.InventoryService, ua.PrincipalID, "Lost And Found/so1"); 127 = UserInventoryHelpers.GetInventoryItem(scene.InventoryService, ua.PrincipalID, "Lost And Found/so1");
127 Assert.That(item, Is.Not.Null); 128 Assert.That(item, Is.Not.Null);
128 } 129 }
@@ -144,7 +145,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
144 145
145 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test. 146 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test.
146 AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter; 147 AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter;
147 sogd.Enabled = false; 148 sogd.Enabled = false;
148 149
149 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, "so1", ua.PrincipalID); 150 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, "so1", ua.PrincipalID);
150 uint soLocalId = so.LocalId; 151 uint soLocalId = so.LocalId;
@@ -167,11 +168,11 @@ namespace OpenSim.Region.Framework.Scenes.Tests
167 168
168 // Check that object is still there. 169 // Check that object is still there.
169 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId); 170 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId);
170 Assert.That(retrievedPart2, Is.Not.Null); 171 Assert.That(retrievedPart2, Is.Not.Null);
171 Assert.That(client.ReceivedKills.Count, Is.EqualTo(0)); 172 Assert.That(client.ReceivedKills.Count, Is.EqualTo(0));
172 173
173 // Check that we do not have a copy in inventory 174 // Check that we do not have a copy in inventory
174 InventoryItemBase item 175 InventoryItemBase item
175 = UserInventoryHelpers.GetInventoryItem(scene.InventoryService, ua.PrincipalID, "Lost And Found/so1"); 176 = UserInventoryHelpers.GetInventoryItem(scene.InventoryService, ua.PrincipalID, "Lost And Found/so1");
176 Assert.That(item, Is.Null); 177 Assert.That(item, Is.Null);
177 } 178 }
@@ -193,7 +194,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
193 194
194 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test. 195 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test.
195 AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter; 196 AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter;
196 sogd.Enabled = false; 197 sogd.Enabled = false;
197 198
198 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, "so1", TestHelpers.ParseTail(0x2)); 199 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, "so1", TestHelpers.ParseTail(0x2));
199 uint soLocalId = so.LocalId; 200 uint soLocalId = so.LocalId;
@@ -218,11 +219,11 @@ namespace OpenSim.Region.Framework.Scenes.Tests
218 219
219 // Check that object is still there. 220 // Check that object is still there.
220 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId); 221 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId);
221 Assert.That(retrievedPart2, Is.Not.Null); 222 Assert.That(retrievedPart2, Is.Not.Null);
222 Assert.That(client.ReceivedKills.Count, Is.EqualTo(0)); 223 Assert.That(client.ReceivedKills.Count, Is.EqualTo(0));
223 224
224 // Check that we have a copy in inventory 225 // Check that we have a copy in inventory
225 InventoryItemBase item 226 InventoryItemBase item
226 = UserInventoryHelpers.GetInventoryItem(scene.InventoryService, ua.PrincipalID, "Objects/so1"); 227 = UserInventoryHelpers.GetInventoryItem(scene.InventoryService, ua.PrincipalID, "Objects/so1");
227 Assert.That(item, Is.Not.Null); 228 Assert.That(item, Is.Not.Null);
228 } 229 }
@@ -244,7 +245,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
244 245
245 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test. 246 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test.
246 AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter; 247 AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter;
247 sogd.Enabled = false; 248 sogd.Enabled = false;
248 249
249 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, "so1", TestHelpers.ParseTail(0x2)); 250 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, "so1", TestHelpers.ParseTail(0x2));
250 uint soLocalId = so.LocalId; 251 uint soLocalId = so.LocalId;
@@ -271,11 +272,11 @@ namespace OpenSim.Region.Framework.Scenes.Tests
271 sogd.InventoryDeQueueAndDelete(); 272 sogd.InventoryDeQueueAndDelete();
272 // Check that object is still there. 273 // Check that object is still there.
273 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId); 274 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId);
274 Assert.That(retrievedPart2, Is.Not.Null); 275 Assert.That(retrievedPart2, Is.Not.Null);
275 Assert.That(client.ReceivedKills.Count, Is.EqualTo(0)); 276 Assert.That(client.ReceivedKills.Count, Is.EqualTo(0));
276 277
277 // Check that we have a copy in inventory 278 // Check that we have a copy in inventory
278 InventoryItemBase item 279 InventoryItemBase item
279 = UserInventoryHelpers.GetInventoryItem(scene.InventoryService, ua.PrincipalID, "Objects/so1"); 280 = UserInventoryHelpers.GetInventoryItem(scene.InventoryService, ua.PrincipalID, "Objects/so1");
280 Assert.That(item, Is.Null); 281 Assert.That(item, Is.Null);
281 } 282 }
@@ -302,11 +303,11 @@ namespace OpenSim.Region.Framework.Scenes.Tests
302 sogd.InventoryDeQueueAndDelete(); 303 sogd.InventoryDeQueueAndDelete();
303 // Check that object is still there. 304 // Check that object is still there.
304 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId); 305 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId);
305 Assert.That(retrievedPart2, Is.Not.Null); 306 Assert.That(retrievedPart2, Is.Not.Null);
306 Assert.That(client.ReceivedKills.Count, Is.EqualTo(0)); 307 Assert.That(client.ReceivedKills.Count, Is.EqualTo(0));
307 308
308 // Check that we have a copy in inventory 309 // Check that we have a copy in inventory
309 InventoryItemBase item 310 InventoryItemBase item
310 = UserInventoryHelpers.GetInventoryItem(scene.InventoryService, ua.PrincipalID, "Objects/so1"); 311 = UserInventoryHelpers.GetInventoryItem(scene.InventoryService, ua.PrincipalID, "Objects/so1");
311 Assert.That(item, Is.Null); 312 Assert.That(item, Is.Null);
312 } 313 }
@@ -333,14 +334,15 @@ namespace OpenSim.Region.Framework.Scenes.Tests
333 sogd.InventoryDeQueueAndDelete(); 334 sogd.InventoryDeQueueAndDelete();
334 // Check that object is still there. 335 // Check that object is still there.
335 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId); 336 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId);
336 Assert.That(retrievedPart2, Is.Not.Null); 337 Assert.That(retrievedPart2, Is.Not.Null);
337 Assert.That(client.ReceivedKills.Count, Is.EqualTo(0)); 338 Assert.That(client.ReceivedKills.Count, Is.EqualTo(0));
338 339
339 // Check that we have a copy in inventory 340 // Check that we have a copy in inventory
340 InventoryItemBase item 341 InventoryItemBase item
341 = UserInventoryHelpers.GetInventoryItem(scene.InventoryService, ua.PrincipalID, "Objects/so1"); 342 = UserInventoryHelpers.GetInventoryItem(scene.InventoryService, ua.PrincipalID, "Objects/so1");
342 Assert.That(item, Is.Null); 343 Assert.That(item, Is.Null);
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/SceneObjectCrossingTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectCrossingTests.cs
index 5635c20..abf8c48 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectCrossingTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectCrossingTests.cs
@@ -37,6 +37,7 @@ using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation;
37using OpenSim.Region.CoreModules.World.Land; 37using OpenSim.Region.CoreModules.World.Land;
38using OpenSim.Region.OptionalModules; 38using OpenSim.Region.OptionalModules;
39using OpenSim.Tests.Common; 39using OpenSim.Tests.Common;
40using System.Threading;
40 41
41namespace OpenSim.Region.Framework.Scenes.Tests 42namespace OpenSim.Region.Framework.Scenes.Tests
42{ 43{
@@ -64,6 +65,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
64 [Test] 65 [Test]
65 public void TestCrossOnSameSimulator() 66 public void TestCrossOnSameSimulator()
66 { 67 {
68
67 TestHelpers.InMethod(); 69 TestHelpers.InMethod();
68// TestHelpers.EnableLogging(); 70// TestHelpers.EnableLogging();
69 71
@@ -94,6 +96,9 @@ namespace OpenSim.Region.Framework.Scenes.Tests
94 // Cross with a negative value 96 // Cross with a negative value
95 so1.AbsolutePosition = new Vector3(128, -10, 20); 97 so1.AbsolutePosition = new Vector3(128, -10, 20);
96 98
99 // crossing is async
100 Thread.Sleep(500);
101
97 Assert.IsNull(sceneA.GetSceneObjectGroup(so1Id)); 102 Assert.IsNull(sceneA.GetSceneObjectGroup(so1Id));
98 Assert.NotNull(sceneB.GetSceneObjectGroup(so1Id)); 103 Assert.NotNull(sceneB.GetSceneObjectGroup(so1Id));
99 } 104 }
@@ -152,26 +157,28 @@ namespace OpenSim.Region.Framework.Scenes.Tests
152 157
153 // Cross 158 // Cross
154 sceneA.SceneGraph.UpdatePrimGroupPosition( 159 sceneA.SceneGraph.UpdatePrimGroupPosition(
155 so1.LocalId, new Vector3(so1StartPos.X, so1StartPos.Y - 20, so1StartPos.Z), userId); 160 so1.LocalId, new Vector3(so1StartPos.X, so1StartPos.Y - 20, so1StartPos.Z), sp1SceneA.ControllingClient);
161
162 // crossing is async
163 Thread.Sleep(500);
156 164
157 SceneObjectGroup so1PostCross; 165 SceneObjectGroup so1PostCross;
158 166
159 { 167 ScenePresence sp1SceneAPostCross = sceneA.GetScenePresence(userId);
160 ScenePresence sp1SceneAPostCross = sceneA.GetScenePresence(userId); 168 Assert.IsTrue(sp1SceneAPostCross.IsChildAgent, "sp1SceneAPostCross.IsChildAgent unexpectedly false");
161 Assert.IsTrue(sp1SceneAPostCross.IsChildAgent, "sp1SceneAPostCross.IsChildAgent unexpectedly false");
162 169
163 ScenePresence sp1SceneBPostCross = sceneB.GetScenePresence(userId); 170 ScenePresence sp1SceneBPostCross = sceneB.GetScenePresence(userId);
164 TestClient sceneBTc = ((TestClient)sp1SceneBPostCross.ControllingClient); 171 TestClient sceneBTc = ((TestClient)sp1SceneBPostCross.ControllingClient);
165 sceneBTc.CompleteMovement(); 172 sceneBTc.CompleteMovement();
166 173
167 Assert.IsFalse(sp1SceneBPostCross.IsChildAgent, "sp1SceneAPostCross.IsChildAgent unexpectedly true"); 174 Assert.IsFalse(sp1SceneBPostCross.IsChildAgent, "sp1SceneAPostCross.IsChildAgent unexpectedly true");
168 Assert.IsTrue(sp1SceneBPostCross.IsSatOnObject); 175 Assert.IsTrue(sp1SceneBPostCross.IsSatOnObject);
176
177 Assert.IsNull(sceneA.GetSceneObjectGroup(so1Id), "uck");
178 so1PostCross = sceneB.GetSceneObjectGroup(so1Id);
179 Assert.NotNull(so1PostCross);
180 Assert.AreEqual(1, so1PostCross.GetSittingAvatarsCount());
169 181
170 Assert.IsNull(sceneA.GetSceneObjectGroup(so1Id), "uck");
171 so1PostCross = sceneB.GetSceneObjectGroup(so1Id);
172 Assert.NotNull(so1PostCross);
173 Assert.AreEqual(1, so1PostCross.GetSittingAvatarsCount());
174 }
175 182
176 Vector3 so1PostCrossPos = so1PostCross.AbsolutePosition; 183 Vector3 so1PostCrossPos = so1PostCross.AbsolutePosition;
177 184
@@ -179,7 +186,10 @@ namespace OpenSim.Region.Framework.Scenes.Tests
179 186
180 // Recross 187 // Recross
181 sceneB.SceneGraph.UpdatePrimGroupPosition( 188 sceneB.SceneGraph.UpdatePrimGroupPosition(
182 so1PostCross.LocalId, new Vector3(so1PostCrossPos.X, so1PostCrossPos.Y + 20, so1PostCrossPos.Z), userId); 189 so1PostCross.LocalId, new Vector3(so1PostCrossPos.X, so1PostCrossPos.Y + 20, so1PostCrossPos.Z), sp1SceneBPostCross.ControllingClient);
190
191 // crossing is async
192 Thread.Sleep(500);
183 193
184 { 194 {
185 ScenePresence sp1SceneBPostReCross = sceneB.GetScenePresence(userId); 195 ScenePresence sp1SceneBPostReCross = sceneB.GetScenePresence(userId);
@@ -244,13 +254,22 @@ namespace OpenSim.Region.Framework.Scenes.Tests
244 lmmA.EventManagerOnNoLandDataFromStorage(); 254 lmmA.EventManagerOnNoLandDataFromStorage();
245 lmmB.EventManagerOnNoLandDataFromStorage(); 255 lmmB.EventManagerOnNoLandDataFromStorage();
246 256
257 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
258 TestClient tc = new TestClient(acd, sceneA);
259 List<TestClient> destinationTestClients = new List<TestClient>();
260 EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(tc, destinationTestClients);
261 ScenePresence sp1SceneA = SceneHelpers.AddScenePresence(sceneA, tc, acd);
262
247 SceneObjectGroup so1 = SceneHelpers.AddSceneObject(sceneA, 1, userId, "", sceneObjectIdTail); 263 SceneObjectGroup so1 = SceneHelpers.AddSceneObject(sceneA, 1, userId, "", sceneObjectIdTail);
248 UUID so1Id = so1.UUID; 264 UUID so1Id = so1.UUID;
249 so1.AbsolutePosition = new Vector3(128, 10, 20); 265 so1.AbsolutePosition = new Vector3(128, 10, 20);
250 266
251 // Cross with a negative value. We must make this call rather than setting AbsolutePosition directly 267 // Cross with a negative value. We must make this call rather than setting AbsolutePosition directly
252 // because only this will execute permission checks in the source region. 268 // because only this will execute permission checks in the source region.
253 sceneA.SceneGraph.UpdatePrimGroupPosition(so1.LocalId, new Vector3(128, -10, 20), userId); 269 sceneA.SceneGraph.UpdatePrimGroupPosition(so1.LocalId, new Vector3(128, -10, 20), sp1SceneA.ControllingClient);
270
271 // crossing is async
272 Thread.Sleep(500);
254 273
255 Assert.IsNull(sceneA.GetSceneObjectGroup(so1Id)); 274 Assert.IsNull(sceneA.GetSceneObjectGroup(so1Id));
256 Assert.NotNull(sceneB.GetSceneObjectGroup(so1Id)); 275 Assert.NotNull(sceneB.GetSceneObjectGroup(so1Id));
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs
index 1c396ac..b84ecac 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs
@@ -77,16 +77,19 @@ namespace OpenSim.Region.Framework.Scenes.Tests
77 public void TestDeRezSceneObject() 77 public void TestDeRezSceneObject()
78 { 78 {
79 TestHelpers.InMethod(); 79 TestHelpers.InMethod();
80 80
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 86 config.Set("serverside_object_permissions", true);
87 SceneHelpers.SetupSceneModules(scene, configSource, new object[] { new DefaultPermissionsModule() });
88 IClientAPI client = SceneHelpers.AddScenePresence(scene, userId).ControllingClient;
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;
89 sogd.Enabled = false; 92 sogd.Enabled = false;
90 93
91 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, "so1", userId); 94 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, "so1", userId);
92 uint soLocalId = so.LocalId; 95 uint soLocalId = so.LocalId;
@@ -97,16 +100,13 @@ namespace OpenSim.Region.Framework.Scenes.Tests
97 100
98 // Check that object isn't deleted until we crank the sogd handle. 101 // Check that object isn't deleted until we crank the sogd handle.
99 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(so.LocalId); 102 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(so.LocalId);
100 Assert.That(retrievedPart, Is.Not.Null); 103// Assert.That(retrievedPart, Is.Not.Null);
101 Assert.That(retrievedPart.ParentGroup.IsDeleted, Is.False); 104// Assert.That(retrievedPart.ParentGroup.IsDeleted, Is.False);
102 105
103 sogd.InventoryDeQueueAndDelete(); 106 sogd.InventoryDeQueueAndDelete();
104
105 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId);
106 Assert.That(retrievedPart2, Is.Null);
107 107
108 Assert.That(client.ReceivedKills.Count, Is.EqualTo(1)); 108// SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId);
109 Assert.That(client.ReceivedKills[0], Is.EqualTo(soLocalId)); 109 Assert.That(retrievedPart, Is.Null);
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,52 +153,49 @@ 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>
165 /// Test deleting an object from a scene where the deleter is not the owner 159 /// Test deleting an object from a scene where the deleter is not the owner
166 /// </summary> 160 /// </summary>
167 /// <remarks> 161 /// <remarks>
168 /// This test assumes that the deleter is not a god. 162 /// This test assumes that the deleter is not a god.
169 /// </remarks> 163 /// </remarks>
170 [Test] 164 [Test]
171 public void TestDeRezSceneObjectNotOwner() 165 public void TestDeRezSceneObjectNotOwner()
172 { 166 {
173 TestHelpers.InMethod(); 167 TestHelpers.InMethod();
174// log4net.Config.XmlConfigurator.Configure(); 168// log4net.Config.XmlConfigurator.Configure();
175 169
176 UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001"); 170 UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001");
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.
184 AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter; 181 AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter;
185 sogd.Enabled = false; 182 sogd.Enabled = false;
186 183
187 SceneObjectPart part 184 SceneObjectPart part
188 = new SceneObjectPart(objectOwnerId, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero); 185 = new SceneObjectPart(objectOwnerId, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero);
189 part.Name = "obj1"; 186 part.Name = "obj1";
190 scene.AddNewSceneObject(new SceneObjectGroup(part), false); 187 scene.AddNewSceneObject(new SceneObjectGroup(part), false);
191 List<uint> localIds = new List<uint>(); 188 List<uint> localIds = new List<uint>();
192 localIds.Add(part.LocalId); 189 localIds.Add(part.LocalId);
193 190
194 scene.DeRezObjects(client, localIds, UUID.Zero, DeRezAction.Delete, UUID.Zero); 191 scene.DeRezObjects(client, localIds, UUID.Zero, DeRezAction.Delete, UUID.Zero);
195 sogd.InventoryDeQueueAndDelete(); 192 sogd.InventoryDeQueueAndDelete();
196 193
197 // Object should still be in the scene. 194 // Object should still be in the scene.
198 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId); 195 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId);
199 Assert.That(retrievedPart.UUID, Is.EqualTo(part.UUID)); 196 Assert.That(retrievedPart.UUID, Is.EqualTo(part.UUID));
200 } 197 }
201 198
202 /// <summary> 199 /// <summary>
203 /// Test deleting an object asynchronously to user inventory. 200 /// Test deleting an object asynchronously to user inventory.
204 /// </summary> 201 /// </summary>
@@ -214,7 +211,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
214 TestScene scene = new SceneHelpers().SetupScene(); 211 TestScene scene = new SceneHelpers().SetupScene();
215 212
216 IConfigSource configSource = new IniConfigSource(); 213 IConfigSource configSource = new IniConfigSource();
217 IConfig config = configSource.AddConfig("Modules"); 214 IConfig config = configSource.AddConfig("Modules");
218 config.Set("InventoryAccessModule", "BasicInventoryAccessModule"); 215 config.Set("InventoryAccessModule", "BasicInventoryAccessModule");
219 SceneHelpers.SetupSceneModules( 216 SceneHelpers.SetupSceneModules(
220 scene, configSource, new object[] { new BasicInventoryAccessModule() }); 217 scene, configSource, new object[] { new BasicInventoryAccessModule() });
@@ -234,10 +231,10 @@ namespace OpenSim.Region.Framework.Scenes.Tests
234 IClientAPI client = SceneHelpers.AddScenePresence(scene, agentId).ControllingClient; 231 IClientAPI client = SceneHelpers.AddScenePresence(scene, agentId).ControllingClient;
235 scene.DeRezObjects(client, new List<uint>() { so.LocalId }, UUID.Zero, DeRezAction.Take, folder1.ID); 232 scene.DeRezObjects(client, new List<uint>() { so.LocalId }, UUID.Zero, DeRezAction.Take, folder1.ID);
236 233
237 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(so.LocalId); 234// SceneObjectPart retrievedPart = scene.GetSceneObjectPart(so.LocalId);
238 235
239 Assert.That(retrievedPart, Is.Not.Null); 236// Assert.That(retrievedPart, Is.Not.Null);
240 Assert.That(so.IsDeleted, Is.False); 237// Assert.That(so.IsDeleted, Is.False);
241 238
242 sogd.InventoryDeQueueAndDelete(); 239 sogd.InventoryDeQueueAndDelete();
243 240
@@ -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/SceneObjectLinkingTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs
index e6d5a2f..41f61ac 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs
@@ -66,8 +66,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
66 public void TestLinkDelink2SceneObjects() 66 public void TestLinkDelink2SceneObjects()
67 { 67 {
68 TestHelpers.InMethod(); 68 TestHelpers.InMethod();
69 69
70 bool debugtest = false; 70 bool debugtest = false;
71 71
72 Scene scene = new SceneHelpers().SetupScene(); 72 Scene scene = new SceneHelpers().SetupScene();
73 SceneObjectGroup grp1 = SceneHelpers.AddSceneObject(scene); 73 SceneObjectGroup grp1 = SceneHelpers.AddSceneObject(scene);
@@ -83,7 +83,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
83 83
84 // <180,0,0> 84 // <180,0,0>
85 grp2.UpdateGroupRotationR(Quaternion.CreateFromEulers(180 * Utils.DEG_TO_RAD, 0, 0)); 85 grp2.UpdateGroupRotationR(Quaternion.CreateFromEulers(180 * Utils.DEG_TO_RAD, 0, 0));
86 86
87 // Required for linking 87 // Required for linking
88 grp1.RootPart.ClearUpdateSchedule(); 88 grp1.RootPart.ClearUpdateSchedule();
89 grp2.RootPart.ClearUpdateSchedule(); 89 grp2.RootPart.ClearUpdateSchedule();
@@ -111,7 +111,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
111 } 111 }
112 112
113 // root part should have no offset position or rotation 113 // root part should have no offset position or rotation
114 Assert.That(part1.OffsetPosition == Vector3.Zero && part1.RotationOffset == Quaternion.Identity, 114 Assert.That(part1.OffsetPosition == Vector3.Zero && part1.RotationOffset == Quaternion.Identity,
115 "root part should have no offset position or rotation"); 115 "root part should have no offset position or rotation");
116 116
117 // offset position should be root part position - part2.absolute position. 117 // offset position should be root part position - part2.absolute position.
@@ -125,13 +125,13 @@ namespace OpenSim.Region.Framework.Scenes.Tests
125 // There's a euler anomoly at 180, 0, 0 so expect 180 to turn into -180. 125 // There's a euler anomoly at 180, 0, 0 so expect 180 to turn into -180.
126 part1.RotationOffset.GetEulerAngles(out roll, out pitch, out yaw); 126 part1.RotationOffset.GetEulerAngles(out roll, out pitch, out yaw);
127 Vector3 rotEuler1 = new Vector3(roll * Utils.RAD_TO_DEG, pitch * Utils.RAD_TO_DEG, yaw * Utils.RAD_TO_DEG); 127 Vector3 rotEuler1 = new Vector3(roll * Utils.RAD_TO_DEG, pitch * Utils.RAD_TO_DEG, yaw * Utils.RAD_TO_DEG);
128 128
129 if (debugtest) 129 if (debugtest)
130 m_log.Debug(rotEuler1); 130 m_log.Debug(rotEuler1);
131 131
132 part2.RotationOffset.GetEulerAngles(out roll, out pitch, out yaw); 132 part2.RotationOffset.GetEulerAngles(out roll, out pitch, out yaw);
133 Vector3 rotEuler2 = new Vector3(roll * Utils.RAD_TO_DEG, pitch * Utils.RAD_TO_DEG, yaw * Utils.RAD_TO_DEG); 133 Vector3 rotEuler2 = new Vector3(roll * Utils.RAD_TO_DEG, pitch * Utils.RAD_TO_DEG, yaw * Utils.RAD_TO_DEG);
134 134
135 if (debugtest) 135 if (debugtest)
136 m_log.Debug(rotEuler2); 136 m_log.Debug(rotEuler2);
137 137
@@ -153,7 +153,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
153 public void TestLinkDelink2groups4SceneObjects() 153 public void TestLinkDelink2groups4SceneObjects()
154 { 154 {
155 TestHelpers.InMethod(); 155 TestHelpers.InMethod();
156 156
157 bool debugtest = false; 157 bool debugtest = false;
158 158
159 Scene scene = new SceneHelpers().SetupScene(); 159 Scene scene = new SceneHelpers().SetupScene();
@@ -194,7 +194,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
194 194
195 // Link grp4 to grp3. 195 // Link grp4 to grp3.
196 grp3.LinkToGroup(grp4); 196 grp3.LinkToGroup(grp4);
197 197
198 // At this point we should have 4 parts total in two groups. 198 // At this point we should have 4 parts total in two groups.
199 Assert.That(grp1.Parts.Length == 2, "Group1 children count should be 2"); 199 Assert.That(grp1.Parts.Length == 2, "Group1 children count should be 2");
200 Assert.That(grp2.IsDeleted, "Group 2 was not registered as deleted after link."); 200 Assert.That(grp2.IsDeleted, "Group 2 was not registered as deleted after link.");
@@ -202,7 +202,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
202 Assert.That(grp3.Parts.Length == 2, "Group3 children count should be 2"); 202 Assert.That(grp3.Parts.Length == 2, "Group3 children count should be 2");
203 Assert.That(grp4.IsDeleted, "Group 4 was not registered as deleted after link."); 203 Assert.That(grp4.IsDeleted, "Group 4 was not registered as deleted after link.");
204 Assert.That(grp4.Parts.Length, Is.EqualTo(0), "Group 4 still contained parts after delink."); 204 Assert.That(grp4.Parts.Length, Is.EqualTo(0), "Group 4 still contained parts after delink.");
205 205
206 if (debugtest) 206 if (debugtest)
207 { 207 {
208 m_log.Debug("--------After Link-------"); 208 m_log.Debug("--------After Link-------");
@@ -273,13 +273,13 @@ namespace OpenSim.Region.Framework.Scenes.Tests
273 Assert.That(part2.AbsolutePosition == Vector3.Zero, "Badness 1"); 273 Assert.That(part2.AbsolutePosition == Vector3.Zero, "Badness 1");
274 Assert.That(part4.OffsetPosition == new Vector3(20, 20, 20), "Badness 2"); 274 Assert.That(part4.OffsetPosition == new Vector3(20, 20, 20), "Badness 2");
275 Quaternion compareQuaternion = new Quaternion(0, 0.7071068f, 0, 0.7071068f); 275 Quaternion compareQuaternion = new Quaternion(0, 0.7071068f, 0, 0.7071068f);
276 Assert.That((part4.RotationOffset.X - compareQuaternion.X < 0.00003) 276 Assert.That((part4.RotationOffset.X - compareQuaternion.X < 0.00003)
277 && (part4.RotationOffset.Y - compareQuaternion.Y < 0.00003) 277 && (part4.RotationOffset.Y - compareQuaternion.Y < 0.00003)
278 && (part4.RotationOffset.Z - compareQuaternion.Z < 0.00003) 278 && (part4.RotationOffset.Z - compareQuaternion.Z < 0.00003)
279 && (part4.RotationOffset.W - compareQuaternion.W < 0.00003), 279 && (part4.RotationOffset.W - compareQuaternion.W < 0.00003),
280 "Badness 3"); 280 "Badness 3");
281 } 281 }
282 282
283 /// <summary> 283 /// <summary>
284 /// Test that a new scene object which is already linked is correctly persisted to the persistence layer. 284 /// Test that a new scene object which is already linked is correctly persisted to the persistence layer.
285 /// </summary> 285 /// </summary>
@@ -288,37 +288,37 @@ namespace OpenSim.Region.Framework.Scenes.Tests
288 { 288 {
289 TestHelpers.InMethod(); 289 TestHelpers.InMethod();
290 //log4net.Config.XmlConfigurator.Configure(); 290 //log4net.Config.XmlConfigurator.Configure();
291 291
292 TestScene scene = new SceneHelpers().SetupScene(); 292 TestScene scene = new SceneHelpers().SetupScene();
293 293
294 string rootPartName = "rootpart"; 294 string rootPartName = "rootpart";
295 UUID rootPartUuid = new UUID("00000000-0000-0000-0000-000000000001"); 295 UUID rootPartUuid = new UUID("00000000-0000-0000-0000-000000000001");
296 string linkPartName = "linkpart"; 296 string linkPartName = "linkpart";
297 UUID linkPartUuid = new UUID("00000000-0000-0000-0001-000000000000"); 297 UUID linkPartUuid = new UUID("00000000-0000-0000-0001-000000000000");
298 298
299 SceneObjectPart rootPart 299 SceneObjectPart rootPart
300 = new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero) 300 = new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero)
301 { Name = rootPartName, UUID = rootPartUuid }; 301 { Name = rootPartName, UUID = rootPartUuid };
302 SceneObjectPart linkPart 302 SceneObjectPart linkPart
303 = new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero) 303 = new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero)
304 { Name = linkPartName, UUID = linkPartUuid }; 304 { Name = linkPartName, UUID = linkPartUuid };
305 305
306 SceneObjectGroup sog = new SceneObjectGroup(rootPart); 306 SceneObjectGroup sog = new SceneObjectGroup(rootPart);
307 sog.AddPart(linkPart); 307 sog.AddPart(linkPart);
308 scene.AddNewSceneObject(sog, true); 308 scene.AddNewSceneObject(sog, true);
309 309
310 // In a test, we have to crank the backup handle manually. Normally this would be done by the timer invoked 310 // In a test, we have to crank the backup handle manually. Normally this would be done by the timer invoked
311 // scene backup thread. 311 // scene backup thread.
312 scene.Backup(true); 312 scene.Backup(true);
313 313
314 List<SceneObjectGroup> storedObjects = scene.SimulationDataService.LoadObjects(scene.RegionInfo.RegionID); 314 List<SceneObjectGroup> storedObjects = scene.SimulationDataService.LoadObjects(scene.RegionInfo.RegionID);
315 315
316 Assert.That(storedObjects.Count, Is.EqualTo(1)); 316 Assert.That(storedObjects.Count, Is.EqualTo(1));
317 Assert.That(storedObjects[0].Parts.Length, Is.EqualTo(2)); 317 Assert.That(storedObjects[0].Parts.Length, Is.EqualTo(2));
318 Assert.That(storedObjects[0].ContainsPart(rootPartUuid)); 318 Assert.That(storedObjects[0].ContainsPart(rootPartUuid));
319 Assert.That(storedObjects[0].ContainsPart(linkPartUuid)); 319 Assert.That(storedObjects[0].ContainsPart(linkPartUuid));
320 } 320 }
321 321
322 /// <summary> 322 /// <summary>
323 /// Test that a delink of a previously linked object is correctly persisted to the database 323 /// Test that a delink of a previously linked object is correctly persisted to the database
324 /// </summary> 324 /// </summary>
@@ -327,20 +327,20 @@ namespace OpenSim.Region.Framework.Scenes.Tests
327 { 327 {
328 TestHelpers.InMethod(); 328 TestHelpers.InMethod();
329 //log4net.Config.XmlConfigurator.Configure(); 329 //log4net.Config.XmlConfigurator.Configure();
330 330
331 TestScene scene = new SceneHelpers().SetupScene(); 331 TestScene scene = new SceneHelpers().SetupScene();
332 332
333 string rootPartName = "rootpart"; 333 string rootPartName = "rootpart";
334 UUID rootPartUuid = new UUID("00000000-0000-0000-0000-000000000001"); 334 UUID rootPartUuid = new UUID("00000000-0000-0000-0000-000000000001");
335 string linkPartName = "linkpart"; 335 string linkPartName = "linkpart";
336 UUID linkPartUuid = new UUID("00000000-0000-0000-0001-000000000000"); 336 UUID linkPartUuid = new UUID("00000000-0000-0000-0001-000000000000");
337 337
338 SceneObjectPart rootPart 338 SceneObjectPart rootPart
339 = new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero) 339 = new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero)
340 { Name = rootPartName, UUID = rootPartUuid }; 340 { Name = rootPartName, UUID = rootPartUuid };
341 341
342 SceneObjectPart linkPart 342 SceneObjectPart linkPart
343 = new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero) 343 = new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero)
344 { Name = linkPartName, UUID = linkPartUuid }; 344 { Name = linkPartName, UUID = linkPartUuid };
345 SceneObjectGroup linkGroup = new SceneObjectGroup(linkPart); 345 SceneObjectGroup linkGroup = new SceneObjectGroup(linkPart);
346 scene.AddNewSceneObject(linkGroup, true); 346 scene.AddNewSceneObject(linkGroup, true);
@@ -359,13 +359,15 @@ namespace OpenSim.Region.Framework.Scenes.Tests
359 SceneObjectGroup groupToDelete = sog.DelinkFromGroup(linkPart, false); 359 SceneObjectGroup groupToDelete = sog.DelinkFromGroup(linkPart, false);
360 Assert.IsFalse(groupToDelete.GroupContainsForeignPrims); 360 Assert.IsFalse(groupToDelete.GroupContainsForeignPrims);
361 361
362/* backup is async
362 scene.DeleteSceneObject(groupToDelete, false); 363 scene.DeleteSceneObject(groupToDelete, false);
363 364
364 List<SceneObjectGroup> storedObjects = scene.SimulationDataService.LoadObjects(scene.RegionInfo.RegionID); 365 List<SceneObjectGroup> storedObjects = scene.SimulationDataService.LoadObjects(scene.RegionInfo.RegionID);
365 366
366 Assert.AreEqual(1, storedObjects.Count); 367 Assert.AreEqual(1, storedObjects.Count);
367 Assert.AreEqual(1, storedObjects[0].Parts.Length); 368 Assert.AreEqual(1, storedObjects[0].Parts.Length);
368 Assert.IsTrue(storedObjects[0].ContainsPart(rootPartUuid)); 369 Assert.IsTrue(storedObjects[0].ContainsPart(rootPartUuid));
370*/
369 } 371 }
370 } 372 }
371} 373}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs
index 975c4d9..8b3a7e9 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>
@@ -72,8 +74,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
72 //log4net.Config.XmlConfigurator.Configure(); 74 //log4net.Config.XmlConfigurator.Configure();
73 75
74 Scene scene = new SceneHelpers().SetupScene(); 76 Scene scene = new SceneHelpers().SetupScene();
75 77 UUID owner = UUID.Random();
76 SceneObjectGroup g1 = SceneHelpers.CreateSceneObject(2, UUID.Zero); 78 SceneObjectGroup g1 = SceneHelpers.CreateSceneObject(2, owner);
77 g1.RootPart.Scale = new Vector3(2, 3, 4); 79 g1.RootPart.Scale = new Vector3(2, 3, 4);
78 g1.Parts[1].Scale = new Vector3(5, 6, 7); 80 g1.Parts[1].Scale = new Vector3(5, 6, 7);
79 81
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSpatialTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSpatialTests.cs
index e00defd..c2c7822 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSpatialTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSpatialTests.cs
@@ -138,8 +138,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
138 138
139 SceneObjectPart childPart = so.Parts[1]; 139 SceneObjectPart childPart = so.Parts[1];
140 140
141 // FIXME: Should be childPosition after rotation? 141 Assert.That(childPart.AbsolutePosition, Is.EqualTo(childPosition));
142 Assert.That(childPart.AbsolutePosition, Is.EqualTo(rootPartPosition + childOffsetPosition));
143 142
144 Assert.That(childPart.GroupPosition, Is.EqualTo(rootPartPosition)); 143 Assert.That(childPart.GroupPosition, Is.EqualTo(rootPartPosition));
145 Assert.That(childPart.GetWorldPosition(), Is.EqualTo(childPosition)); 144 Assert.That(childPart.GetWorldPosition(), Is.EqualTo(childPosition));
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectStatusTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectStatusTests.cs
index 1737e3c..8d88083 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectStatusTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectStatusTests.cs
@@ -71,7 +71,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
71 m_so1.ScriptSetTemporaryStatus(false); 71 m_so1.ScriptSetTemporaryStatus(false);
72 72
73 Assert.That(m_so1.RootPart.Flags, Is.EqualTo(PrimFlags.None)); 73 Assert.That(m_so1.RootPart.Flags, Is.EqualTo(PrimFlags.None));
74 Assert.That(m_so1.Backup, Is.True); 74 Assert.That(m_so1.Backup, Is.True);
75 } 75 }
76 76
77 [Test] 77 [Test]
@@ -91,7 +91,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
91 91
92 m_so1.ScriptSetPhantomStatus(false); 92 m_so1.ScriptSetPhantomStatus(false);
93 93
94 Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.None)); 94 Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.None));
95 } 95 }
96 96
97 [Test] 97 [Test]
@@ -107,11 +107,12 @@ namespace OpenSim.Region.Framework.Scenes.Tests
107 m_so1.ScriptSetVolumeDetect(true); 107 m_so1.ScriptSetVolumeDetect(true);
108 108
109// Console.WriteLine("so.RootPart.Flags [{0}]", so.RootPart.Flags); 109// Console.WriteLine("so.RootPart.Flags [{0}]", so.RootPart.Flags);
110 Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.Phantom)); 110 // PrimFlags.JointLP2P is incorrect it now means VolumeDetect (as defined by viewers)
111 Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.Phantom | PrimFlags.JointLP2P));
111 112
112 m_so1.ScriptSetVolumeDetect(false); 113 m_so1.ScriptSetVolumeDetect(false);
113 114
114 Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.None)); 115 Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.None));
115 } 116 }
116 117
117 [Test] 118 [Test]
@@ -146,13 +147,14 @@ namespace OpenSim.Region.Framework.Scenes.Tests
146 m_so1.ScriptSetPhysicsStatus(true); 147 m_so1.ScriptSetPhysicsStatus(true);
147 m_so1.ScriptSetVolumeDetect(true); 148 m_so1.ScriptSetVolumeDetect(true);
148 149
149 Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.Phantom | PrimFlags.Physics)); 150 // PrimFlags.JointLP2P is incorrect it now means VolumeDetect (as defined by viewers)
151 Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.Phantom | PrimFlags.Physics | PrimFlags.JointLP2P));
150 152
151 m_so1.ScriptSetVolumeDetect(false); 153 m_so1.ScriptSetVolumeDetect(false);
152 154
153 Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.Physics)); 155 Assert.That(rootPart.Flags, Is.EqualTo(PrimFlags.Physics));
154 } 156 }
155 157
156 [Test] 158 [Test]
157 public void TestSetPhysicsLinkset() 159 public void TestSetPhysicsLinkset()
158 { 160 {
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUndoRedoTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUndoRedoTests.cs
index af3ce8e..340da9c 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUndoRedoTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUndoRedoTests.cs
@@ -25,6 +25,7 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28/* undo has changed, this tests dont apply without large changes
28using System; 29using System;
29using System.Reflection; 30using System.Reflection;
30using NUnit.Framework; 31using NUnit.Framework;
@@ -179,4 +180,5 @@ namespace OpenSim.Region.Framework.Scenes.Tests
179 Assert.That(g1.GroupScale, Is.EqualTo(newSize)); 180 Assert.That(g1.GroupScale, Is.EqualTo(newSize));
180 } 181 }
181 } 182 }
182} \ No newline at end of file 183}
184*/ \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs
index aadf7c6..4ec69cd 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,31 +52,32 @@ namespace OpenSim.Region.Framework.Scenes.Tests
52 public void TestShareWithGroup() 52 public void TestShareWithGroup()
53 { 53 {
54 TestHelpers.InMethod(); 54 TestHelpers.InMethod();
55 55// log4net.Config.XmlConfigurator.Configure();
56
56 UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001"); 57 UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001");
57 58
58 TestScene scene = new SceneHelpers().SetupScene(); 59 TestScene scene = new SceneHelpers().SetupScene();
59 IConfigSource configSource = new IniConfigSource(); 60 IConfigSource configSource = new IniConfigSource();
60 61
61 IConfig startupConfig = configSource.AddConfig("Startup"); 62 IConfig startupConfig = configSource.AddConfig("Startup");
62 startupConfig.Set("serverside_object_permissions", true); 63 startupConfig.Set("serverside_object_permissions", true);
63 64
64 IConfig groupsConfig = configSource.AddConfig("Groups"); 65 IConfig groupsConfig = configSource.AddConfig("Groups");
65 groupsConfig.Set("Enabled", true); 66 groupsConfig.Set("Enabled", true);
66 groupsConfig.Set("Module", "GroupsModule"); 67 groupsConfig.Set("Module", "GroupsModule");
67 groupsConfig.Set("DebugEnabled", true); 68 groupsConfig.Set("DebugEnabled", true);
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
75 IClientAPI client = SceneHelpers.AddScenePresence(scene, userId).ControllingClient; 76 IClientAPI client = SceneHelpers.AddScenePresence(scene, userId).ControllingClient;
76 77
77 IGroupsModule groupsModule = scene.RequestModuleInterface<IGroupsModule>(); 78 IGroupsModule groupsModule = scene.RequestModuleInterface<IGroupsModule>();
78 79
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/ScenePresenceAgentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
index 96d112d..0f386bc 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
@@ -44,6 +44,7 @@ using OpenSim.Region.CoreModules.World.Serialiser;
44using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; 44using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation;
45using OpenSim.Tests.Common; 45using OpenSim.Tests.Common;
46using GridRegion = OpenSim.Services.Interfaces.GridRegion; 46using GridRegion = OpenSim.Services.Interfaces.GridRegion;
47using OpenSim.Services.Interfaces;
47 48
48namespace OpenSim.Region.Framework.Scenes.Tests 49namespace OpenSim.Region.Framework.Scenes.Tests
49{ 50{
@@ -141,7 +142,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
141 // Check rest of exepcted parameters. 142 // Check rest of exepcted parameters.
142 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(spUuid), Is.Not.Null); 143 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(spUuid), Is.Not.Null);
143 Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1)); 144 Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1));
144 145
145 Assert.That(sp.IsChildAgent, Is.False); 146 Assert.That(sp.IsChildAgent, Is.False);
146 Assert.That(sp.UUID, Is.EqualTo(spUuid)); 147 Assert.That(sp.UUID, Is.EqualTo(spUuid));
147 148
@@ -226,7 +227,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
226 // *** This is the first stage, when a neighbouring region is told that a viewer is about to try and 227 // *** This is the first stage, when a neighbouring region is told that a viewer is about to try and
227 // establish a child scene presence. We pass in the circuit code that the client has to connect with *** 228 // establish a child scene presence. We pass in the circuit code that the client has to connect with ***
228 // XXX: ViaLogin may not be correct here. 229 // XXX: ViaLogin may not be correct here.
229 scene.SimulationService.CreateAgent(null, region, acd, (uint)TeleportFlags.ViaLogin, out reason); 230 EntityTransferContext ctx = new EntityTransferContext();
231 scene.SimulationService.CreateAgent(null, region, acd, (uint)TeleportFlags.ViaLogin, ctx, out reason);
230 232
231 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(agentId), Is.Not.Null); 233 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(agentId), Is.Not.Null);
232 Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1)); 234 Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1));
@@ -260,16 +262,15 @@ namespace OpenSim.Region.Framework.Scenes.Tests
260 { 262 {
261 TestHelpers.InMethod(); 263 TestHelpers.InMethod();
262// log4net.Config.XmlConfigurator.Configure(); 264// log4net.Config.XmlConfigurator.Configure();
263 265
264// UUID agent1Id = UUID.Parse("00000000-0000-0000-0000-000000000001"); 266// UUID agent1Id = UUID.Parse("00000000-0000-0000-0000-000000000001");
265 267
266 TestScene myScene1 = new SceneHelpers().SetupScene("Neighbour y", UUID.Random(), 1000, 1000); 268 TestScene myScene1 = new SceneHelpers().SetupScene("Neighbour y", UUID.Random(), 1000, 1000);
267 TestScene myScene2 = new SceneHelpers().SetupScene("Neighbour y + 1", UUID.Random(), 1001, 1000); 269 TestScene myScene2 = new SceneHelpers().SetupScene("Neighbour y + 1", UUID.Random(), 1001, 1000);
268 270
269 IConfigSource configSource = new IniConfigSource(); 271 IConfigSource configSource = new IniConfigSource();
270 IConfig config = configSource.AddConfig("Startup"); 272 IConfig config = configSource.AddConfig("Startup");
271 config.Set("serverside_object_permissions", true); 273 config.Set("serverside_object_permissions", true);
272 config.Set("EventQueue", true);
273 274
274 EntityTransferModule etm = new EntityTransferModule(); 275 EntityTransferModule etm = new EntityTransferModule();
275 276
@@ -278,7 +279,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
278 279
279 EventQueueGetModule eqgm2 = new EventQueueGetModule(); 280 EventQueueGetModule eqgm2 = new EventQueueGetModule();
280 SceneHelpers.SetupSceneModules(myScene2, configSource, etm, eqgm2); 281 SceneHelpers.SetupSceneModules(myScene2, configSource, etm, eqgm2);
281 282
282// SceneHelpers.AddScenePresence(myScene1, agent1Id); 283// SceneHelpers.AddScenePresence(myScene1, agent1Id);
283// ScenePresence childPresence = myScene2.GetScenePresence(agent1); 284// ScenePresence childPresence = myScene2.GetScenePresence(agent1);
284// 285//
@@ -287,4 +288,4 @@ namespace OpenSim.Region.Framework.Scenes.Tests
287// Assert.That(childPresence.IsChildAgent, Is.True); 288// Assert.That(childPresence.IsChildAgent, Is.True);
288 } 289 }
289 } 290 }
290} \ No newline at end of file 291}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAnimationTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAnimationTests.cs
index 42d91b9..d650c43 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAnimationTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAnimationTests.cs
@@ -60,7 +60,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
60 TestScene scene = new SceneHelpers().SetupScene(); 60 TestScene scene = new SceneHelpers().SetupScene();
61 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); 61 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1));
62 sp.Flying = true; 62 sp.Flying = true;
63 sp.PhysicsCollisionUpdate(new CollisionEventUpdate()); 63 sp.Animator.UpdateMovementAnimations();
64 64
65 Assert.That(sp.Animator.CurrentMovementAnimation, Is.EqualTo("HOVER")); 65 Assert.That(sp.Animator.CurrentMovementAnimation, Is.EqualTo("HOVER"));
66 } 66 }
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs
index e5c847e..90c5197 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs
@@ -97,7 +97,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
97 Assert.That(sp.AbsolutePosition.Z, Is.EqualTo(startPos.Z)); 97 Assert.That(sp.AbsolutePosition.Z, Is.EqualTo(startPos.Z));
98 Assert.That(sp.AbsolutePosition.Z, Is.LessThan(targetPos.X)); 98 Assert.That(sp.AbsolutePosition.Z, Is.LessThan(targetPos.X));
99 99
100 m_scene.Update(10); 100 m_scene.Update(50);
101 101
102 double distanceToTarget = Util.GetDistanceTo(sp.AbsolutePosition, targetPos); 102 double distanceToTarget = Util.GetDistanceTo(sp.AbsolutePosition, targetPos);
103 Assert.That(distanceToTarget, Is.LessThan(1), "Avatar not within 1 unit of target position on first move"); 103 Assert.That(distanceToTarget, Is.LessThan(1), "Avatar not within 1 unit of target position on first move");
@@ -121,7 +121,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
121 Assert.That(sp.AbsolutePosition.Y, Is.EqualTo(startPos.Y)); 121 Assert.That(sp.AbsolutePosition.Y, Is.EqualTo(startPos.Y));
122 Assert.That(sp.AbsolutePosition.Z, Is.EqualTo(startPos.Z)); 122 Assert.That(sp.AbsolutePosition.Z, Is.EqualTo(startPos.Z));
123 123
124 m_scene.Update(10); 124 m_scene.Update(50);
125 125
126 distanceToTarget = Util.GetDistanceTo(sp.AbsolutePosition, targetPos); 126 distanceToTarget = Util.GetDistanceTo(sp.AbsolutePosition, targetPos);
127 Assert.That(distanceToTarget, Is.LessThan(1), "Avatar not within 1 unit of target position on second move"); 127 Assert.That(distanceToTarget, Is.LessThan(1), "Avatar not within 1 unit of target position on second move");
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..3d51a63 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs
@@ -39,6 +39,8 @@ using OpenSim.Region.CoreModules.Framework.EntityTransfer;
39using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; 39using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation;
40using OpenSim.Region.CoreModules.World.Permissions; 40using OpenSim.Region.CoreModules.World.Permissions;
41using OpenSim.Tests.Common; 41using OpenSim.Tests.Common;
42using OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups;
43using System.Threading;
42 44
43namespace OpenSim.Region.Framework.Scenes.Tests 45namespace OpenSim.Region.Framework.Scenes.Tests
44{ 46{
@@ -190,7 +192,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 192 // 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 193 // QueryAccess won't succeed anyway because administrators are always allowed in and the default
192 // IsAdministrator if no permissions module is present is true. 194 // IsAdministrator if no permissions module is present is true.
193 SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), new PermissionsModule(), etmB); 195 SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), new DefaultPermissionsModule(), etmB);
194 196
195 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId); 197 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
196 TestClient tc = new TestClient(acd, sceneA); 198 TestClient tc = new TestClient(acd, sceneA);
@@ -229,7 +231,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
229 231
230 ScenePresence spAfterCrossSceneB = sceneB.GetScenePresence(originalSp.UUID); 232 ScenePresence spAfterCrossSceneB = sceneB.GetScenePresence(originalSp.UUID);
231 233
232 // sceneB agent should also still be root 234 // sceneB agent should still be child
233 Assert.That(spAfterCrossSceneB.IsChildAgent, Is.True); 235 Assert.That(spAfterCrossSceneB.IsChildAgent, Is.True);
234 236
235 // sceneB should ignore unauthorized attempt to upgrade agent to root 237 // sceneB should ignore unauthorized attempt to upgrade agent to root
@@ -244,4 +246,4 @@ namespace OpenSim.Region.Framework.Scenes.Tests
244 Assert.That(spAfterCrossSceneB.IsChildAgent, Is.True); 246 Assert.That(spAfterCrossSceneB.IsChildAgent, Is.True);
245 } 247 }
246 } 248 }
247} \ No newline at end of file 249}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
index b232a44..e3ebf36 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
@@ -166,6 +166,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
166 [Test] 166 [Test]
167 public void TestSitAndStandWithSitTarget() 167 public void TestSitAndStandWithSitTarget()
168 { 168 {
169/* sit position math as changed, this needs to be fixed later
169 TestHelpers.InMethod(); 170 TestHelpers.InMethod();
170// log4net.Config.XmlConfigurator.Configure(); 171// log4net.Config.XmlConfigurator.Configure();
171 172
@@ -223,6 +224,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
223 Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero)); 224 Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero));
224 Assert.That(part.GetSittingAvatarsCount(), Is.EqualTo(0)); 225 Assert.That(part.GetSittingAvatarsCount(), Is.EqualTo(0));
225 Assert.That(part.GetSittingAvatars(), Is.Null); 226 Assert.That(part.GetSittingAvatars(), Is.Null);
227*/
226 } 228 }
227 229
228 [Test] 230 [Test]
@@ -246,4 +248,4 @@ namespace OpenSim.Region.Framework.Scenes.Tests
246 Assert.That(m_sp.PhysicsActor, Is.Not.Null); 248 Assert.That(m_sp.PhysicsActor, Is.Not.Null);
247 } 249 }
248 } 250 }
249} \ No newline at end of file 251}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
index 443ec51..86500c7 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
@@ -282,7 +282,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
282 // We need to set up the permisions module on scene B so that our later use of agent limit to deny 282 // We need to set up the permisions module on scene B so that our later use of agent limit to deny
283 // QueryAccess won't succeed anyway because administrators are always allowed in and the default 283 // QueryAccess won't succeed anyway because administrators are always allowed in and the default
284 // IsAdministrator if no permissions module is present is true. 284 // IsAdministrator if no permissions module is present is true.
285 SceneHelpers.SetupSceneModules(sceneB, config, new object[] { new PermissionsModule(), etmB }); 285 SceneHelpers.SetupSceneModules(sceneB, config, new object[] { new DefaultPermissionsModule(), etmB });
286 286
287 // Shared scene modules 287 // Shared scene modules
288 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm); 288 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
@@ -447,7 +447,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
447 // We need to set up the permisions module on scene B so that our later use of agent limit to deny 447 // We need to set up the permisions module on scene B so that our later use of agent limit to deny
448 // QueryAccess won't succeed anyway because administrators are always allowed in and the default 448 // QueryAccess won't succeed anyway because administrators are always allowed in and the default
449 // IsAdministrator if no permissions module is present is true. 449 // IsAdministrator if no permissions module is present is true.
450 SceneHelpers.SetupSceneModules(sceneB, config, new object[] { new PermissionsModule(), etmB }); 450 SceneHelpers.SetupSceneModules(sceneB, config, new object[] { new DefaultPermissionsModule(), etmB });
451 451
452 // Shared scene modules 452 // Shared scene modules
453 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm); 453 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
@@ -465,7 +465,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
465 teleportLookAt, 465 teleportLookAt,
466 (uint)TeleportFlags.ViaLocation); 466 (uint)TeleportFlags.ViaLocation);
467 467
468 // FIXME: Not setting up InformClientOfNeighbour on the TestClient means that it does not initiate 468 // FIXME: Not setting up InformClientOfNeighbour on the TestClient means that it does not initiate
469 // communication with the destination region. But this is a very non-obvious way of doing it - really we 469 // communication with the destination region. But this is a very non-obvious way of doing it - really we
470 // should be forced to expicitly set this up. 470 // should be forced to expicitly set this up.
471 471
@@ -627,8 +627,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
627 // Both these operations will occur on different threads and will wait for each other. 627 // Both these operations will occur on different threads and will wait for each other.
628 // We have to do this via ThreadPool directly since FireAndForget has been switched to sync for the V1 628 // We have to do this via ThreadPool directly since FireAndForget has been switched to sync for the V1
629 // test protocol, where we are trying to avoid unpredictable async operations in regression tests. 629 // test protocol, where we are trying to avoid unpredictable async operations in regression tests.
630 tc.OnTestClientSendRegionTeleport 630 tc.OnTestClientSendRegionTeleport
631 += (regionHandle, simAccess, regionExternalEndPoint, locationID, flags, capsURL) 631 += (regionHandle, simAccess, regionExternalEndPoint, locationID, flags, capsURL)
632 => ThreadPool.UnsafeQueueUserWorkItem(o => destinationTestClients[0].CompleteMovement(), null); 632 => ThreadPool.UnsafeQueueUserWorkItem(o => destinationTestClients[0].CompleteMovement(), null);
633 633
634 sceneA.RequestTeleportLocation( 634 sceneA.RequestTeleportLocation(
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneStatisticsTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneStatisticsTests.cs
index 045fd3c..4ce6a95 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneStatisticsTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneStatisticsTests.cs
@@ -54,8 +54,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
54 54
55 UUID ownerId = TestHelpers.ParseTail(0x1); 55 UUID ownerId = TestHelpers.ParseTail(0x1);
56 SceneObjectGroup so1 = SceneHelpers.CreateSceneObject(3, ownerId, "so1", 0x10); 56 SceneObjectGroup so1 = SceneHelpers.CreateSceneObject(3, ownerId, "so1", 0x10);
57 so1.ScriptSetPhysicsStatus(true);
58 m_scene.AddSceneObject(so1); 57 m_scene.AddSceneObject(so1);
58 so1.ScriptSetPhysicsStatus(true);
59 59
60 Assert.That(m_scene.SceneGraph.GetTotalObjectsCount(), Is.EqualTo(3)); 60 Assert.That(m_scene.SceneGraph.GetTotalObjectsCount(), Is.EqualTo(3));
61 Assert.That(m_scene.SceneGraph.GetActiveObjectsCount(), Is.EqualTo(3)); 61 Assert.That(m_scene.SceneGraph.GetActiveObjectsCount(), Is.EqualTo(3));
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneTelehubTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneTelehubTests.cs
index 584a03c..dbb6a37 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneTelehubTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneTelehubTests.cs
@@ -70,7 +70,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
70 // Must still be possible to successfully log in 70 // Must still be possible to successfully log in
71 UUID loggingInUserId = TestHelpers.ParseTail(0x2); 71 UUID loggingInUserId = TestHelpers.ParseTail(0x2);
72 72
73 UserAccount ua 73 UserAccount ua
74 = UserAccountHelpers.CreateUserWithInventory(scene, "Test", "User", loggingInUserId, "password"); 74 = UserAccountHelpers.CreateUserWithInventory(scene, "Test", "User", loggingInUserId, "password");
75 75
76 SceneHelpers.AddScenePresence(scene, ua); 76 SceneHelpers.AddScenePresence(scene, ua);
@@ -107,7 +107,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
107 // Must still be possible to successfully log in 107 // Must still be possible to successfully log in
108 UUID loggingInUserId = TestHelpers.ParseTail(0x2); 108 UUID loggingInUserId = TestHelpers.ParseTail(0x2);
109 109
110 UserAccount ua 110 UserAccount ua
111 = UserAccountHelpers.CreateUserWithInventory(scene, "Test", "User", loggingInUserId, "password"); 111 = UserAccountHelpers.CreateUserWithInventory(scene, "Test", "User", loggingInUserId, "password");
112 112
113 SceneHelpers.AddScenePresence(scene, ua); 113 SceneHelpers.AddScenePresence(scene, ua);
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs
index 517faf1..6c0af8f 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs
@@ -66,7 +66,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
66 uint sizeX = 512; 66 uint sizeX = 512;
67 uint sizeY = 512; 67 uint sizeY = 512;
68 68
69 Scene scene 69 Scene scene
70 = new SceneHelpers().SetupScene("scene", regionUuid, 1000, 1000, sizeX, sizeY, new IniConfigSource()); 70 = new SceneHelpers().SetupScene("scene", regionUuid, 1000, 1000, sizeX, sizeY, new IniConfigSource());
71 71
72 Assert.AreEqual(sizeX, scene.RegionInfo.RegionSizeX); 72 Assert.AreEqual(sizeX, scene.RegionInfo.RegionSizeX);
@@ -83,7 +83,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
83 83
84 Scene scene = new SceneHelpers().SetupScene(); 84 Scene scene = new SceneHelpers().SetupScene();
85 scene.Update(1); 85 scene.Update(1);
86 86
87 Assert.That(scene.Frame, Is.EqualTo(1)); 87 Assert.That(scene.Frame, Is.EqualTo(1));
88 } 88 }
89 89
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SharedRegionModuleTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SharedRegionModuleTests.cs
index eeda84f..c74c83f 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SharedRegionModuleTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SharedRegionModuleTests.cs
@@ -105,7 +105,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
105// rmcp.LoadModulesFromAddins = false; 105// rmcp.LoadModulesFromAddins = false;
106//// reg.RegisterInterface<IRegionModulesController>(rmcp); 106//// reg.RegisterInterface<IRegionModulesController>(rmcp);
107// rmcp.Initialise(sim); 107// rmcp.Initialise(sim);
108// rmcp.PostInitialise(); 108// rmcp.PostInitialise();
109// TypeExtensionNode node = new TypeExtensionNode(); 109// TypeExtensionNode node = new TypeExtensionNode();
110// node. 110// node.
111// rmcp.AddNode(node, configSource.Configs["Modules"], new Dictionary<RuntimeAddin, IList<int>>()); 111// rmcp.AddNode(node, configSource.Configs["Modules"], new Dictionary<RuntimeAddin, IList<int>>());
@@ -120,9 +120,9 @@ namespace OpenSim.Region.Framework.Scenes.Tests
120 int expectedEventCount = 6; 120 int expectedEventCount = 6;
121 121
122 Assert.AreEqual( 122 Assert.AreEqual(
123 expectedEventCount, 123 expectedEventCount,
124 co.Count, 124 co.Count,
125 "Expected {0} events but only got {1} ({2})", 125 "Expected {0} events but only got {1} ({2})",
126 expectedEventCount, co.Count, string.Join(",", co)); 126 expectedEventCount, co.Count, string.Join(",", co));
127 Assert.AreEqual("Initialise", co[0]); 127 Assert.AreEqual("Initialise", co[0]);
128 Assert.AreEqual("PostInitialise", co[1]); 128 Assert.AreEqual("PostInitialise", co[1]);
@@ -137,7 +137,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
137 { 137 {
138 // FIXME: Should really use MethodInfo 138 // FIXME: Should really use MethodInfo
139 public List<string> CallOrder = new List<string>(); 139 public List<string> CallOrder = new List<string>();
140 140
141 public string Name { get { return "TestSharedRegion"; } } 141 public string Name { get { return "TestSharedRegion"; } }
142 142
143 public Type ReplaceableInterface { get { return null; } } 143 public Type ReplaceableInterface { get { return null; } }
@@ -186,13 +186,13 @@ namespace OpenSim.Region.Framework.Scenes.Tests
186 186
187 public void Initialise() {} 187 public void Initialise() {}
188 188
189 public void Initialise(OpenSimBase sim) 189 public void Initialise(OpenSimBase sim)
190 { 190 {
191 m_openSim = sim; 191 m_openSim = sim;
192 } 192 }
193 193
194 /// <summary> 194 /// <summary>
195 /// Called when the application loading is completed 195 /// Called when the application loading is completed
196 /// </summary> 196 /// </summary>
197 public void PostInitialise() 197 public void PostInitialise()
198 { 198 {
@@ -228,8 +228,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
228 } 228 }
229 229
230 scene.RegionModules.Clear(); 230 scene.RegionModules.Clear();
231 } 231 }
232 232
233 public void AddNode(ISharedRegionModule module) 233 public void AddNode(ISharedRegionModule module)
234 { 234 {
235 m_sharedInstances.Add(module); 235 m_sharedInstances.Add(module);
diff --git a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs
index b01088d..8273e32 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs
@@ -55,7 +55,7 @@ namespace OpenSim.Region.Framework.Tests
55 { 55 {
56 TestHelpers.InMethod(); 56 TestHelpers.InMethod();
57// log4net.Config.XmlConfigurator.Configure(); 57// log4net.Config.XmlConfigurator.Configure();
58 58
59 Scene scene = new SceneHelpers().SetupScene(); 59 Scene scene = new SceneHelpers().SetupScene();
60 UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene); 60 UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene);
61 SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, user1.PrincipalID); 61 SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, user1.PrincipalID);
@@ -78,7 +78,7 @@ namespace OpenSim.Region.Framework.Tests
78 { 78 {
79 TestHelpers.InMethod(); 79 TestHelpers.InMethod();
80// log4net.Config.XmlConfigurator.Configure(); 80// log4net.Config.XmlConfigurator.Configure();
81 81
82 Scene scene = new SceneHelpers().SetupScene(); 82 Scene scene = new SceneHelpers().SetupScene();
83 UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene); 83 UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene);
84 SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, user1.PrincipalID); 84 SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, user1.PrincipalID);
@@ -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
@@ -121,7 +121,7 @@ namespace OpenSim.Region.Framework.Tests
121 { 121 {
122 TestHelpers.InMethod(); 122 TestHelpers.InMethod();
123// log4net.Config.XmlConfigurator.Configure(); 123// log4net.Config.XmlConfigurator.Configure();
124 124
125 Scene scene = new SceneHelpers().SetupScene(); 125 Scene scene = new SceneHelpers().SetupScene();
126 UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene); 126 UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene);
127 SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, user1.PrincipalID); 127 SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, user1.PrincipalID);
@@ -130,18 +130,18 @@ namespace OpenSim.Region.Framework.Tests
130 = TaskInventoryHelpers.AddNotecard( 130 = TaskInventoryHelpers.AddNotecard(
131 scene.AssetService, sop1, "ncItem", TestHelpers.ParseTail(0x800), TestHelpers.ParseTail(0x900), "Hello World!"); 131 scene.AssetService, sop1, "ncItem", TestHelpers.ParseTail(0x800), TestHelpers.ParseTail(0x900), "Hello World!");
132 132
133 InventoryFolderBase folder 133 InventoryFolderBase folder
134 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, user1.PrincipalID, "Objects")[0]; 134 = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, user1.PrincipalID, "Objects")[0];
135 135
136 // Perform test 136 // Perform test
137 string message; 137 string message;
138 scene.MoveTaskInventoryItem(user1.PrincipalID, folder.ID, sop1, sopItem1.ItemID, out message); 138 scene.MoveTaskInventoryItem(user1.PrincipalID, folder.ID, sop1, sopItem1.ItemID, out message);
139 139
140 InventoryItemBase ncUserItem 140 InventoryItemBase ncUserItem
141 = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, user1.PrincipalID, "Objects/ncItem"); 141 = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, user1.PrincipalID, "Objects/ncItem");
142 Assert.That(ncUserItem, Is.Not.Null, "Objects/ncItem was not found"); 142 Assert.That(ncUserItem, Is.Not.Null, "Objects/ncItem was not found");
143 } 143 }
144 144
145 /// <summary> 145 /// <summary>
146 /// Test MoveTaskInventoryItem from a part inventory to a user inventory where the item has no parent folder assigned. 146 /// Test MoveTaskInventoryItem from a part inventory to a user inventory where the item has no parent folder assigned.
147 /// </summary> 147 /// </summary>
@@ -153,7 +153,7 @@ namespace OpenSim.Region.Framework.Tests
153 { 153 {
154 TestHelpers.InMethod(); 154 TestHelpers.InMethod();
155// log4net.Config.XmlConfigurator.Configure(); 155// log4net.Config.XmlConfigurator.Configure();
156 156
157 Scene scene = new SceneHelpers().SetupScene(); 157 Scene scene = new SceneHelpers().SetupScene();
158 UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene); 158 UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene);
159 SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, user1.PrincipalID); 159 SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, user1.PrincipalID);
@@ -162,11 +162,11 @@ namespace OpenSim.Region.Framework.Tests
162 TaskInventoryItem sopItem1 162 TaskInventoryItem sopItem1
163 = TaskInventoryHelpers.AddNotecard( 163 = TaskInventoryHelpers.AddNotecard(
164 scene.AssetService, sop1, "ncItem", TestHelpers.ParseTail(0x800), TestHelpers.ParseTail(0x900), "Hello World!"); 164 scene.AssetService, sop1, "ncItem", TestHelpers.ParseTail(0x800), TestHelpers.ParseTail(0x900), "Hello World!");
165 165
166 // Perform test 166 // Perform test
167 string message; 167 string message;
168 scene.MoveTaskInventoryItem(user1.PrincipalID, UUID.Zero, sop1, sopItem1.ItemID, out message); 168 scene.MoveTaskInventoryItem(user1.PrincipalID, UUID.Zero, sop1, sopItem1.ItemID, out message);
169 169
170 InventoryItemBase ncUserItem 170 InventoryItemBase ncUserItem
171 = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, user1.PrincipalID, "Notecards/ncItem"); 171 = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, user1.PrincipalID, "Notecards/ncItem");
172 Assert.That(ncUserItem, Is.Not.Null, "Notecards/ncItem was not found"); 172 Assert.That(ncUserItem, Is.Not.Null, "Notecards/ncItem was not found");
diff --git a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs
index 8250e6c..58e157c 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs
@@ -38,10 +38,7 @@ using OpenMetaverse;
38using OpenMetaverse.Assets; 38using OpenMetaverse.Assets;
39using OpenSim.Framework; 39using OpenSim.Framework;
40using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
41using OpenSim.Region.Framework.Interfaces; 41using OpenSim.Region.CoreModules.Framework.InventoryAccess;
42using OpenSim.Region.CoreModules.Avatar.Inventory.Archiver;
43using OpenSim.Region.CoreModules.World.Serialiser;
44using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation;
45using OpenSim.Services.Interfaces; 42using OpenSim.Services.Interfaces;
46using OpenSim.Tests.Common; 43using OpenSim.Tests.Common;
47 44
@@ -116,7 +113,7 @@ namespace OpenSim.Region.Framework.Tests
116 { 113 {
117 TestHelpers.InMethod(); 114 TestHelpers.InMethod();
118// TestHelpers.EnableLogging(); 115// TestHelpers.EnableLogging();
119 116
120 Scene scene = new SceneHelpers().SetupScene(); 117 Scene scene = new SceneHelpers().SetupScene();
121 UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001)); 118 UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001));
122 UserAccount user2 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1002)); 119 UserAccount user2 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1002));
@@ -138,5 +135,66 @@ namespace OpenSim.Region.Framework.Tests
138 135
139 Assert.That(reretrievedFolders.Count, Is.EqualTo(2)); 136 Assert.That(reretrievedFolders.Count, Is.EqualTo(2));
140 } 137 }
138
139 // Work in Progress test. All Assertions pertaining permissions are commented for now.
140 [Test]
141 public void TestGiveInventoryItemFullPerms()
142 {
143 TestHelpers.InMethod();
144
145 List<Object> modules = new List<object>();
146 IConfigSource config = DefaultConfig(modules);
147 Scene scene = new SceneHelpers().SetupScene("Inventory Permissions", UUID.Random(), 1000, 1000, config);
148 SceneHelpers.SetupSceneModules(scene, config, modules.ToArray());
149
150 UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001));
151 UserAccount user2 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1002));
152 ScenePresence sp1 = SceneHelpers.AddScenePresence(scene, user1.PrincipalID);
153 ScenePresence sp2 = SceneHelpers.AddScenePresence(scene, user2.PrincipalID);
154
155 InventoryItemBase item1 = UserInventoryHelpers.CreateInventoryItem(scene, "SomeObject", user1.PrincipalID, InventoryType.Object);
156 // Set All perms in inventory
157 item1.NextPermissions = (uint)OpenMetaverse.PermissionMask.All;
158 scene.UpdateInventoryItemAsset(sp1.ControllingClient, UUID.Zero, item1.ID, item1);
159 //Assert.That((item1.NextPermissions & (uint)OpenMetaverse.PermissionMask.All) == (uint)OpenMetaverse.PermissionMask.All);
160
161 string message;
162
163 InventoryItemBase retrievedItem1 = scene.GiveInventoryItem(user2.PrincipalID, user1.PrincipalID, item1.ID, out message);
164 Assert.That(retrievedItem1, Is.Not.Null);
165 //Assert.That((retrievedItem1.CurrentPermissions & (uint)OpenMetaverse.PermissionMask.All) == (uint)OpenMetaverse.PermissionMask.All);
166
167 retrievedItem1
168 = UserInventoryHelpers.GetInventoryItem(scene.InventoryService, user2.PrincipalID, "Objects/SomeObject");
169 Assert.That(retrievedItem1, Is.Not.Null);
170 //Assert.That((retrievedItem1.BasePermissions & (uint)OpenMetaverse.PermissionMask.All) == (uint)OpenMetaverse.PermissionMask.All);
171 //Assert.That((retrievedItem1.CurrentPermissions & (uint)OpenMetaverse.PermissionMask.All) == (uint)OpenMetaverse.PermissionMask.All);
172
173 // Rez the object
174 scene.RezObject(sp2.ControllingClient, retrievedItem1.ID, UUID.Zero, Vector3.Zero, Vector3.Zero, UUID.Zero, 0, false, false, false, UUID.Zero);
175 SceneObjectGroup sog = scene.GetSceneObjectGroup("SomeObject");
176 Assert.That(sog, Is.Not.Null);
177
178 // This is failing for all sorts of reasons. We'll fix it after perms are fixed.
179 //Console.WriteLine("Item Perms " + retrievedItem1.CurrentPermissions + " Obj Owner Perms " + sog.RootPart.OwnerMask + " Base Perms " + sog.RootPart.BaseMask + "\n");
180 //Assert.True((sog.RootPart.OwnerMask & (uint)OpenMetaverse.PermissionMask.All) == (uint)OpenMetaverse.PermissionMask.All);
181
182 }
183
184 public static IConfigSource DefaultConfig(List<object> modules)
185 {
186 IConfigSource config = new IniConfigSource();
187 config.AddConfig("Modules");
188 config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule");
189
190 config.AddConfig("Permissions");
191 config.Configs["Permissions"].Set("permissionmodules", "DefaultPermissionsModule");
192 config.Configs["Permissions"].Set("serverside_object_permissions", true);
193 config.Configs["Permissions"].Set("propagate_permissions", true);
194
195 modules.Add(new BasicInventoryAccessModule());
196 return config;
197 }
198
141 } 199 }
142} \ No newline at end of file 200} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
index 937c414..4ceebc1 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
@@ -41,7 +41,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
41 { 41 {
42 protected IAssetService m_assetService; 42 protected IAssetService m_assetService;
43 protected UuidGatherer m_uuidGatherer; 43 protected UuidGatherer m_uuidGatherer;
44 44
45 [SetUp] 45 [SetUp]
46 public void Init() 46 public void Init()
47 { 47 {
@@ -55,9 +55,9 @@ namespace OpenSim.Region.Framework.Scenes.Tests
55 public void TestCorruptAsset() 55 public void TestCorruptAsset()
56 { 56 {
57 TestHelpers.InMethod(); 57 TestHelpers.InMethod();
58 58
59 UUID corruptAssetUuid = UUID.Parse("00000000-0000-0000-0000-000000000666"); 59 UUID corruptAssetUuid = UUID.Parse("00000000-0000-0000-0000-000000000666");
60 AssetBase corruptAsset 60 AssetBase corruptAsset
61 = AssetHelpers.CreateAsset(corruptAssetUuid, AssetType.Notecard, "CORRUPT ASSET", UUID.Zero); 61 = AssetHelpers.CreateAsset(corruptAssetUuid, AssetType.Notecard, "CORRUPT ASSET", UUID.Zero);
62 m_assetService.Store(corruptAsset); 62 m_assetService.Store(corruptAsset);
63 63
@@ -67,7 +67,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
67 // We count the uuid as gathered even if the asset itself is corrupt. 67 // We count the uuid as gathered even if the asset itself is corrupt.
68 Assert.That(m_uuidGatherer.GatheredUuids.Count, Is.EqualTo(1)); 68 Assert.That(m_uuidGatherer.GatheredUuids.Count, Is.EqualTo(1));
69 } 69 }
70 70
71 /// <summary> 71 /// <summary>
72 /// Test requests made for non-existent assets while we're gathering 72 /// Test requests made for non-existent assets while we're gathering
73 /// </summary> 73 /// </summary>
@@ -75,7 +75,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
75 public void TestMissingAsset() 75 public void TestMissingAsset()
76 { 76 {
77 TestHelpers.InMethod(); 77 TestHelpers.InMethod();
78 78
79 UUID missingAssetUuid = UUID.Parse("00000000-0000-0000-0000-000000000666"); 79 UUID missingAssetUuid = UUID.Parse("00000000-0000-0000-0000-000000000666");
80 80
81 m_uuidGatherer.AddForInspection(missingAssetUuid); 81 m_uuidGatherer.AddForInspection(missingAssetUuid);
@@ -89,23 +89,23 @@ namespace OpenSim.Region.Framework.Scenes.Tests
89 { 89 {
90 TestHelpers.InMethod(); 90 TestHelpers.InMethod();
91// TestHelpers.EnableLogging(); 91// TestHelpers.EnableLogging();
92 92
93 UUID ownerId = TestHelpers.ParseTail(0x10); 93 UUID ownerId = TestHelpers.ParseTail(0x10);
94 UUID embeddedId = TestHelpers.ParseTail(0x20); 94 UUID embeddedId = TestHelpers.ParseTail(0x20);
95 UUID secondLevelEmbeddedId = TestHelpers.ParseTail(0x21); 95 UUID secondLevelEmbeddedId = TestHelpers.ParseTail(0x21);
96 UUID missingEmbeddedId = TestHelpers.ParseTail(0x22); 96 UUID missingEmbeddedId = TestHelpers.ParseTail(0x22);
97 UUID ncAssetId = TestHelpers.ParseTail(0x30); 97 UUID ncAssetId = TestHelpers.ParseTail(0x30);
98 98
99 AssetBase ncAsset 99 AssetBase ncAsset
100 = AssetHelpers.CreateNotecardAsset( 100 = AssetHelpers.CreateNotecardAsset(
101 ncAssetId, string.Format("Hello{0}World{1}", embeddedId, missingEmbeddedId)); 101 ncAssetId, string.Format("Hello{0}World{1}", embeddedId, missingEmbeddedId));
102 m_assetService.Store(ncAsset); 102 m_assetService.Store(ncAsset);
103 103
104 AssetBase embeddedAsset 104 AssetBase embeddedAsset
105 = AssetHelpers.CreateNotecardAsset(embeddedId, string.Format("{0} We'll meet again.", secondLevelEmbeddedId)); 105 = AssetHelpers.CreateNotecardAsset(embeddedId, string.Format("{0} We'll meet again.", secondLevelEmbeddedId));
106 m_assetService.Store(embeddedAsset); 106 m_assetService.Store(embeddedAsset);
107 107
108 AssetBase secondLevelEmbeddedAsset 108 AssetBase secondLevelEmbeddedAsset
109 = AssetHelpers.CreateNotecardAsset(secondLevelEmbeddedId, "Don't know where, don't know when."); 109 = AssetHelpers.CreateNotecardAsset(secondLevelEmbeddedId, "Don't know where, don't know when.");
110 m_assetService.Store(secondLevelEmbeddedAsset); 110 m_assetService.Store(secondLevelEmbeddedAsset);
111 111
diff --git a/OpenSim/Region/Framework/Scenes/UndoState.cs b/OpenSim/Region/Framework/Scenes/UndoState.cs
index 860172c..8fff38f 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 2070ce5..80d3f62 100644
--- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
+++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
@@ -65,7 +65,10 @@ namespace OpenSim.Region.Framework.Scenes
65 /// </summary> 65 /// </summary>
66 /// <value>The gathered uuids.</value> 66 /// <value>The gathered uuids.</value>
67 public IDictionary<UUID, sbyte> GatheredUuids { get; private set; } 67 public IDictionary<UUID, sbyte> GatheredUuids { get; private set; }
68 68 public HashSet<UUID> FailedUUIDs { get; private set; }
69 public HashSet<UUID> UncertainAssetsUUIDs { get; private set; }
70 public int possibleNotAssetCount { get; set; }
71 public int ErrorCount { get; private set; }
69 /// <summary> 72 /// <summary>
70 /// Gets the next UUID to inspect. 73 /// Gets the next UUID to inspect.
71 /// </summary> 74 /// </summary>
@@ -92,7 +95,10 @@ namespace OpenSim.Region.Framework.Scenes
92 /// <param name="assetService"> 95 /// <param name="assetService">
93 /// Asset service. 96 /// Asset service.
94 /// </param> 97 /// </param>
95 public UuidGatherer(IAssetService assetService) : this(assetService, new Dictionary<UUID, sbyte>()) {} 98 public UuidGatherer(IAssetService assetService) : this(assetService, new Dictionary<UUID, sbyte>(),
99 new HashSet <UUID>(),new HashSet <UUID>()) {}
100 public UuidGatherer(IAssetService assetService, IDictionary<UUID, sbyte> collector) : this(assetService, collector,
101 new HashSet <UUID>(), new HashSet <UUID>()) {}
96 102
97 /// <summary> 103 /// <summary>
98 /// Initializes a new instance of the <see cref="OpenSim.Region.Framework.Scenes.UuidGatherer"/> class. 104 /// Initializes a new instance of the <see cref="OpenSim.Region.Framework.Scenes.UuidGatherer"/> class.
@@ -101,16 +107,20 @@ namespace OpenSim.Region.Framework.Scenes
101 /// Asset service. 107 /// Asset service.
102 /// </param> 108 /// </param>
103 /// <param name="collector"> 109 /// <param name="collector">
104 /// Gathered UUIDs will be collected in this dictinaory. 110 /// Gathered UUIDs will be collected in this dictionary.
105 /// It can be pre-populated if you want to stop the gatherer from analyzing assets that have already been fetched and inspected. 111 /// It can be pre-populated if you want to stop the gatherer from analyzing assets that have already been fetched and inspected.
106 /// </param> 112 /// </param>
107 public UuidGatherer(IAssetService assetService, IDictionary<UUID, sbyte> collector) 113 public UuidGatherer(IAssetService assetService, IDictionary<UUID, sbyte> collector, HashSet <UUID> failedIDs, HashSet <UUID> uncertainAssetsUUIDs)
108 { 114 {
109 m_assetService = assetService; 115 m_assetService = assetService;
110 GatheredUuids = collector; 116 GatheredUuids = collector;
111 117
112 // FIXME: Not efficient for searching, can improve. 118 // FIXME: Not efficient for searching, can improve.
113 m_assetUuidsToInspect = new Queue<UUID>(); 119 m_assetUuidsToInspect = new Queue<UUID>();
120 FailedUUIDs = failedIDs;
121 UncertainAssetsUUIDs = uncertainAssetsUUIDs;
122 ErrorCount = 0;
123 possibleNotAssetCount = 0;
114 } 124 }
115 125
116 /// <summary> 126 /// <summary>
@@ -120,16 +130,28 @@ namespace OpenSim.Region.Framework.Scenes
120 /// <param name="uuid">UUID.</param> 130 /// <param name="uuid">UUID.</param>
121 public bool AddForInspection(UUID uuid) 131 public bool AddForInspection(UUID uuid)
122 { 132 {
133 if(uuid == UUID.Zero)
134 return false;
135
136 if(FailedUUIDs.Contains(uuid))
137 {
138 if(UncertainAssetsUUIDs.Contains(uuid))
139 possibleNotAssetCount++;
140 else
141 ErrorCount++;
142 return false;
143 }
144 if(GatheredUuids.ContainsKey(uuid))
145 return false;
123 if (m_assetUuidsToInspect.Contains(uuid)) 146 if (m_assetUuidsToInspect.Contains(uuid))
124 return false; 147 return false;
125 148
126// m_log.DebugFormat("[UUID GATHERER]: Adding asset {0} for inspection", uuid); 149// m_log.DebugFormat("[UUID GATHERER]: Adding asset {0} for inspection", uuid);
127 150
128 m_assetUuidsToInspect.Enqueue(uuid); 151 m_assetUuidsToInspect.Enqueue(uuid);
129
130 return true; 152 return true;
131 } 153 }
132 154
133 /// <summary> 155 /// <summary>
134 /// Gather all the asset uuids associated with a given object. 156 /// Gather all the asset uuids associated with a given object.
135 /// </summary> 157 /// </summary>
@@ -142,7 +164,9 @@ namespace OpenSim.Region.Framework.Scenes
142 public void AddForInspection(SceneObjectGroup sceneObject) 164 public void AddForInspection(SceneObjectGroup sceneObject)
143 { 165 {
144 // m_log.DebugFormat( 166 // m_log.DebugFormat(
145 // "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID); 167 // "[UUID GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID);
168 if(sceneObject.IsDeleted)
169 return;
146 170
147 SceneObjectPart[] parts = sceneObject.Parts; 171 SceneObjectPart[] parts = sceneObject.Parts;
148 for (int i = 0; i < parts.Length; i++) 172 for (int i = 0; i < parts.Length; i++)
@@ -150,7 +174,7 @@ namespace OpenSim.Region.Framework.Scenes
150 SceneObjectPart part = parts[i]; 174 SceneObjectPart part = parts[i];
151 175
152 // m_log.DebugFormat( 176 // m_log.DebugFormat(
153 // "[ARCHIVER]: Getting part {0}, {1} for object {2}", part.Name, part.UUID, sceneObject.UUID); 177 // "[UUID GATHERER]: Getting part {0}, {1} for object {2}", part.Name, part.UUID, sceneObject.UUID);
154 178
155 try 179 try
156 { 180 {
@@ -179,8 +203,10 @@ namespace OpenSim.Region.Framework.Scenes
179 if (part.Shape.ProjectionTextureUUID != UUID.Zero) 203 if (part.Shape.ProjectionTextureUUID != UUID.Zero)
180 GatheredUuids[part.Shape.ProjectionTextureUUID] = (sbyte)AssetType.Texture; 204 GatheredUuids[part.Shape.ProjectionTextureUUID] = (sbyte)AssetType.Texture;
181 205
182 if (part.CollisionSound != UUID.Zero) 206 UUID collisionSound = part.CollisionSound;
183 GatheredUuids[part.CollisionSound] = (sbyte)AssetType.Sound; 207 if ( collisionSound != UUID.Zero &&
208 collisionSound != part.invalidCollisionSoundUUID)
209 GatheredUuids[collisionSound] = (sbyte)AssetType.Sound;
184 210
185 if (part.ParticleSystem.Length > 0) 211 if (part.ParticleSystem.Length > 0)
186 { 212 {
@@ -193,7 +219,7 @@ namespace OpenSim.Region.Framework.Scenes
193 catch (Exception) 219 catch (Exception)
194 { 220 {
195 m_log.WarnFormat( 221 m_log.WarnFormat(
196 "[UUID GATHERER]: Could not check particle system for part {0} {1} in object {2} {3} since it is corrupt. Continuing.", 222 "[UUID GATHERER]: Could not check particle system for part {0} {1} in object {2} {3} since it is corrupt. Continuing.",
197 part.Name, part.UUID, sceneObject.Name, sceneObject.UUID); 223 part.Name, part.UUID, sceneObject.Name, sceneObject.UUID);
198 } 224 }
199 } 225 }
@@ -204,29 +230,24 @@ namespace OpenSim.Region.Framework.Scenes
204 foreach (TaskInventoryItem tii in taskDictionary.Values) 230 foreach (TaskInventoryItem tii in taskDictionary.Values)
205 { 231 {
206 // m_log.DebugFormat( 232 // m_log.DebugFormat(
207 // "[ARCHIVER]: Analysing item {0} asset type {1} in {2} {3}", 233 // "[ARCHIVER]: Analysing item {0} asset type {1} in {2} {3}",
208 // tii.Name, tii.Type, part.Name, part.UUID); 234 // tii.Name, tii.Type, part.Name, part.UUID);
209 235 AddForInspection(tii.AssetID, (sbyte)tii.Type);
210 if (!GatheredUuids.ContainsKey(tii.AssetID))
211 AddForInspection(tii.AssetID, (sbyte)tii.Type);
212 } 236 }
213 237
214 // FIXME: We need to make gathering modular but we cannot yet, since gatherers are not guaranteed 238 // FIXME: We need to make gathering modular but we cannot yet, since gatherers are not guaranteed
215 // to be called with scene objects that are in a scene (e.g. in the case of hg asset mapping and 239 // to be called with scene objects that are in a scene (e.g. in the case of hg asset mapping and
216 // inventory transfer. There needs to be a way for a module to register a method without assuming a 240 // inventory transfer. There needs to be a way for a module to register a method without assuming a
217 // Scene.EventManager is present. 241 // Scene.EventManager is present.
218 // part.ParentGroup.Scene.EventManager.TriggerGatherUuids(part, assetUuids); 242 // part.ParentGroup.Scene.EventManager.TriggerGatherUuids(part, assetUuids);
219 243
220 244
221 // still needed to retrieve textures used as materials for any parts containing legacy materials stored in DynAttrs 245 // still needed to retrieve textures used as materials for any parts containing legacy materials stored in DynAttrs
222 RecordMaterialsUuids(part); 246 RecordMaterialsUuids(part);
223 } 247 }
224 catch (Exception e) 248 catch (Exception e)
225 { 249 {
226 m_log.ErrorFormat("[UUID GATHERER]: Failed to get part - {0}", e); 250 m_log.ErrorFormat("[UUID GATHERER]: Failed to get part - {0}", e);
227 m_log.DebugFormat(
228 "[UUID GATHERER]: Texture entry length for prim was {0} (min is 46)",
229 part.Shape.TextureEntry.Length);
230 } 251 }
231 } 252 }
232 } 253 }
@@ -277,58 +298,115 @@ namespace OpenSim.Region.Framework.Scenes
277 /// <param name="assetUuid">The uuid of the asset for which to gather referenced assets</param> 298 /// <param name="assetUuid">The uuid of the asset for which to gather referenced assets</param>
278 private void GetAssetUuids(UUID assetUuid) 299 private void GetAssetUuids(UUID assetUuid)
279 { 300 {
301 if(assetUuid == UUID.Zero)
302 return;
303
304 if(FailedUUIDs.Contains(assetUuid))
305 {
306 if(UncertainAssetsUUIDs.Contains(assetUuid))
307 possibleNotAssetCount++;
308 else
309 ErrorCount++;
310 return;
311 }
312
280 // avoid infinite loops 313 // avoid infinite loops
281 if (GatheredUuids.ContainsKey(assetUuid)) 314 if (GatheredUuids.ContainsKey(assetUuid))
282 return; 315 return;
283 316
317 AssetBase assetBase;
284 try 318 try
285 { 319 {
286 AssetBase assetBase = GetAsset(assetUuid); 320 assetBase = GetAsset(assetUuid);
321 }
322 catch (Exception e)
323 {
324 m_log.ErrorFormat("[UUID GATHERER]: Failed to get asset {0} : {1}", assetUuid, e.Message);
325 ErrorCount++;
326 FailedUUIDs.Add(assetUuid);
327 return;
328 }
287 329
288 if (null != assetBase) 330 if(assetBase == null)
289 { 331 {
290 sbyte assetType = assetBase.Type; 332// m_log.ErrorFormat("[UUID GATHERER]: asset {0} not found", assetUuid);
291 GatheredUuids[assetUuid] = assetType; 333 FailedUUIDs.Add(assetUuid);
334 if(UncertainAssetsUUIDs.Contains(assetUuid))
335 possibleNotAssetCount++;
336 else
337 ErrorCount++;
338 return;
339 }
292 340
293 if ((sbyte)AssetType.Bodypart == assetType || (sbyte)AssetType.Clothing == assetType) 341 if(UncertainAssetsUUIDs.Contains(assetUuid))
294 { 342 UncertainAssetsUUIDs.Remove(assetUuid);
295 RecordWearableAssetUuids(assetBase); 343
296 } 344 sbyte assetType = assetBase.Type;
297 else if ((sbyte)AssetType.Gesture == assetType) 345
298 { 346 if(assetBase.Data == null || assetBase.Data.Length == 0)
299 RecordGestureAssetUuids(assetBase); 347 {
300 } 348// m_log.ErrorFormat("[UUID GATHERER]: asset {0}, type {1} has no data", assetUuid, assetType);
301 else if ((sbyte)AssetType.Notecard == assetType) 349 ErrorCount++;
302 { 350 FailedUUIDs.Add(assetUuid);
303 RecordTextEmbeddedAssetUuids(assetBase); 351 return;
304 } 352 }
305 else if ((sbyte)AssetType.LSLText == assetType) 353
306 { 354 GatheredUuids[assetUuid] = assetType;
307 RecordTextEmbeddedAssetUuids(assetBase); 355 try
308 } 356 {
309 else if ((sbyte)OpenSimAssetType.Material == assetType) 357 if ((sbyte)AssetType.Bodypart == assetType || (sbyte)AssetType.Clothing == assetType)
310 { 358 {
311 RecordMaterialAssetUuids(assetBase); 359 RecordWearableAssetUuids(assetBase);
312 } 360 }
313 else if ((sbyte)AssetType.Object == assetType) 361 else if ((sbyte)AssetType.Gesture == assetType)
314 { 362 {
315 RecordSceneObjectAssetUuids(assetBase); 363 RecordGestureAssetUuids(assetBase);
316 } 364 }
365 else if ((sbyte)AssetType.Notecard == assetType)
366 {
367 RecordTextEmbeddedAssetUuids(assetBase);
368 }
369 else if ((sbyte)AssetType.LSLText == assetType)
370 {
371 RecordTextEmbeddedAssetUuids(assetBase);
372 }
373 else if ((sbyte)OpenSimAssetType.Material == assetType)
374 {
375 RecordMaterialAssetUuids(assetBase);
376 }
377 else if ((sbyte)AssetType.Object == assetType)
378 {
379 RecordSceneObjectAssetUuids(assetBase);
317 } 380 }
318 } 381 }
319 catch (Exception) 382 catch (Exception e)
320 { 383 {
321 m_log.ErrorFormat("[UUID GATHERER]: Failed to gather uuids for asset id {0}", assetUuid); 384 m_log.ErrorFormat("[UUID GATHERER]: Failed to gather uuids for asset with id {0} type {1}: {2}", assetUuid, assetType, e.Message);
322 throw; 385 GatheredUuids.Remove(assetUuid);
386 ErrorCount++;
387 FailedUUIDs.Add(assetUuid);
323 } 388 }
324 } 389 }
325 390
326 private void AddForInspection(UUID assetUuid, sbyte assetType) 391 private void AddForInspection(UUID assetUuid, sbyte assetType)
327 { 392 {
393 if(assetUuid == UUID.Zero)
394 return;
395
328 // Here, we want to collect uuids which require further asset fetches but mark the others as gathered 396 // Here, we want to collect uuids which require further asset fetches but mark the others as gathered
397 if(FailedUUIDs.Contains(assetUuid))
398 {
399 if(UncertainAssetsUUIDs.Contains(assetUuid))
400 possibleNotAssetCount++;
401 else
402 ErrorCount++;
403 return;
404 }
405 if(GatheredUuids.ContainsKey(assetUuid))
406 return;
329 try 407 try
330 { 408 {
331 if ((sbyte)AssetType.Bodypart == assetType 409 if ((sbyte)AssetType.Bodypart == assetType
332 || (sbyte)AssetType.Clothing == assetType 410 || (sbyte)AssetType.Clothing == assetType
333 || (sbyte)AssetType.Gesture == assetType 411 || (sbyte)AssetType.Gesture == assetType
334 || (sbyte)AssetType.Notecard == assetType 412 || (sbyte)AssetType.Notecard == assetType
@@ -346,7 +424,7 @@ namespace OpenSim.Region.Framework.Scenes
346 catch (Exception) 424 catch (Exception)
347 { 425 {
348 m_log.ErrorFormat( 426 m_log.ErrorFormat(
349 "[UUID GATHERER]: Failed to gather uuids for asset id {0}, type {1}", 427 "[UUID GATHERER]: Failed to gather uuids for asset id {0}, type {1}",
350 assetUuid, assetType); 428 assetUuid, assetType);
351 throw; 429 throw;
352 } 430 }
@@ -457,8 +535,11 @@ namespace OpenSim.Region.Framework.Scenes
457 foreach (Match uuidMatch in uuidMatches) 535 foreach (Match uuidMatch in uuidMatches)
458 { 536 {
459 UUID uuid = new UUID(uuidMatch.Value); 537 UUID uuid = new UUID(uuidMatch.Value);
538 if(uuid == UUID.Zero)
539 continue;
460// m_log.DebugFormat("[UUID GATHERER]: Recording {0} in text", uuid); 540// m_log.DebugFormat("[UUID GATHERER]: Recording {0} in text", uuid);
461 541 if(!UncertainAssetsUUIDs.Contains(uuid))
542 UncertainAssetsUUIDs.Add(uuid);
462 AddForInspection(uuid); 543 AddForInspection(uuid);
463 } 544 }
464 } 545 }
@@ -490,23 +571,18 @@ namespace OpenSim.Region.Framework.Scenes
490 { 571 {
491 string xml = Utils.BytesToString(sceneObjectAsset.Data); 572 string xml = Utils.BytesToString(sceneObjectAsset.Data);
492 573
493 if (String.IsNullOrEmpty(xml)) 574 CoalescedSceneObjects coa;
494 m_log.ErrorFormat("[UUIDGatherer]: Asset {0} - {1} has a zero length XML blob!", sceneObjectAsset.Name, sceneObjectAsset.ID); 575 if (CoalescedSceneObjectsSerializer.TryFromXml(xml, out coa))
576 {
577 foreach (SceneObjectGroup sog in coa.Objects)
578 AddForInspection(sog);
579 }
495 else 580 else
496 { 581 {
497 CoalescedSceneObjects coa; 582 SceneObjectGroup sog = SceneObjectSerializer.FromOriginalXmlFormat(xml);
498 if (CoalescedSceneObjectsSerializer.TryFromXml(xml, out coa))
499 {
500 foreach (SceneObjectGroup sog in coa.Objects)
501 AddForInspection(sog);
502 }
503 else
504 {
505 SceneObjectGroup sog = SceneObjectSerializer.FromOriginalXmlFormat(xml);
506 583
507 if (null != sog) 584 if (null != sog)
508 AddForInspection(sog); 585 AddForInspection(sog);
509 }
510 } 586 }
511 } 587 }
512 588
@@ -554,7 +630,16 @@ namespace OpenSim.Region.Framework.Scenes
554 /// </summary> 630 /// </summary>
555 private void RecordMaterialAssetUuids(AssetBase materialAsset) 631 private void RecordMaterialAssetUuids(AssetBase materialAsset)
556 { 632 {
557 OSDMap mat = (OSDMap)OSDParser.DeserializeLLSDXml(materialAsset.Data); 633 OSDMap mat;
634 try
635 {
636 mat = (OSDMap)OSDParser.DeserializeLLSDXml(materialAsset.Data);
637 }
638 catch (Exception e)
639 {
640 m_log.WarnFormat("[Materials]: cannot decode material asset {0}: {1}", materialAsset.ID, e.Message);
641 return;
642 }
558 643
559 UUID normMap = mat["NormMap"].AsUUID(); 644 UUID normMap = mat["NormMap"].AsUUID();
560 if (normMap != UUID.Zero) 645 if (normMap != UUID.Zero)