aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
authorteravus2012-11-15 10:05:16 -0500
committerteravus2012-11-15 10:05:16 -0500
commite9153e1d1aae50024d8cd05fe14a9bce34343a0e (patch)
treebc111d34f95a26b99c7e34d9e495dc14d1802cc3 /OpenSim
parentMerge master into teravuswork (diff)
downloadopensim-SC_OLD-e9153e1d1aae50024d8cd05fe14a9bce34343a0e.zip
opensim-SC_OLD-e9153e1d1aae50024d8cd05fe14a9bce34343a0e.tar.gz
opensim-SC_OLD-e9153e1d1aae50024d8cd05fe14a9bce34343a0e.tar.bz2
opensim-SC_OLD-e9153e1d1aae50024d8cd05fe14a9bce34343a0e.tar.xz
Revert "Merge master into teravuswork", it should have been avination, not master.
This reverts commit dfac269032300872c4d0dc507f4f9062d102b0f4, reversing changes made to 619c39e5144f15aca129d6d999bcc5c34133ee64.
Diffstat (limited to '')
-rw-r--r--OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs91
-rw-r--r--OpenSim/ApplicationPlugins/Rest/Inventory/RestHandler.cs30
-rw-r--r--OpenSim/ApplicationPlugins/Rest/RestPlugin.cs14
-rw-r--r--OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs18
-rw-r--r--OpenSim/Data/IRegionData.cs15
-rw-r--r--OpenSim/Data/IXInventoryData.cs10
-rw-r--r--OpenSim/Data/MSSQL/MSSQLRegionData.cs1
-rw-r--r--OpenSim/Data/MySQL/MySQLRegionData.cs4
-rw-r--r--OpenSim/Data/MySQL/MySQLSimulationData.cs457
-rw-r--r--OpenSim/Data/MySQL/Resources/GridUserStore.migrations5
-rw-r--r--OpenSim/Data/Null/NullRegionData.cs1
-rw-r--r--OpenSim/Data/SQLite/SQLiteSimulationData.cs25
-rw-r--r--OpenSim/Framework/AssetPermissions.cs84
-rw-r--r--OpenSim/Framework/AvatarAppearance.cs3
-rw-r--r--OpenSim/Framework/Cache.cs83
-rw-r--r--OpenSim/Framework/Client/IClientChat.cs7
-rw-r--r--OpenSim/Framework/Console/ConsoleUtil.cs228
-rw-r--r--OpenSim/Framework/Constants.cs1
-rw-r--r--OpenSim/Framework/EstateSettings.cs10
-rw-r--r--OpenSim/Framework/GridInstantMessage.cs9
-rw-r--r--OpenSim/Framework/IClientAPI.cs46
-rw-r--r--OpenSim/Framework/InventoryFolderBase.cs18
-rw-r--r--OpenSim/Framework/LandData.cs385
-rw-r--r--OpenSim/Framework/Monitoring/BaseStatsCollector.cs23
-rw-r--r--OpenSim/Framework/Monitoring/MemoryWatchdog.cs10
-rw-r--r--OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs19
-rw-r--r--OpenSim/Framework/Monitoring/StatsManager.cs360
-rw-r--r--OpenSim/Framework/Monitoring/Watchdog.cs35
-rw-r--r--OpenSim/Framework/PacketPool.cs (renamed from OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs)97
-rw-r--r--OpenSim/Framework/Pool.cs91
-rw-r--r--OpenSim/Framework/RegionFlags.cs53
-rw-r--r--OpenSim/Framework/RegionInfo.cs72
-rw-r--r--OpenSim/Framework/Serialization/ArchiveConstants.cs5
-rw-r--r--OpenSim/Framework/Serialization/External/OspResolver.cs14
-rw-r--r--OpenSim/Framework/Servers/BaseOpenSimServer.cs43
-rw-r--r--OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs274
-rw-r--r--OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs22
-rw-r--r--OpenSim/Framework/Servers/MainServer.cs148
-rw-r--r--OpenSim/Framework/Servers/VersionInfo.cs2
-rw-r--r--OpenSim/Framework/TaskInventoryDictionary.cs4
-rw-r--r--OpenSim/Framework/TaskInventoryItem.cs19
-rw-r--r--OpenSim/Framework/Util.cs51
-rw-r--r--OpenSim/Framework/WebUtil.cs81
-rw-r--r--OpenSim/Region/Application/OpenSim.cs74
-rw-r--r--OpenSim/Region/Application/OpenSimBase.cs74
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs9
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs21
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs7
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs169
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs338
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs116
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs7
-rw-r--r--OpenSim/Region/ClientStack/RegionApplicationBase.cs2
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs138
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs11
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs222
-rw-r--r--OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs39
-rw-r--r--OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs1
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs36
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs76
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs1
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs36
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs59
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs15
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs26
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs68
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs196
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs76
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs224
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs79
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs15
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/HGUuidGatherer.cs (renamed from OpenSim/Region/ScriptEngine/Shared/ScriptException.cs)33
-rw-r--r--OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs4
-rwxr-xr-xOpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs331
-rw-r--r--OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs3
-rw-r--r--OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs8
-rw-r--r--OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml1
-rw-r--r--OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs61
-rw-r--r--OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs277
-rw-r--r--OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs17
-rw-r--r--OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs49
-rw-r--r--OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs281
-rw-r--r--OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs159
-rw-r--r--OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs133
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs23
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs7
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs136
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs10
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs19
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs46
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs6
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs434
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs176
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs634
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs153
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs438
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs25
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs10
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs232
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs404
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs1
-rw-r--r--OpenSim/Region/CoreModules/World/Land/DwellModule.cs110
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs1
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandObject.cs1
-rw-r--r--OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs522
-rw-r--r--OpenSim/Region/CoreModules/World/Sound/SoundModule.cs313
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs61
-rw-r--r--OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs7
-rw-r--r--OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs9
-rw-r--r--OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs69
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityInventory.cs27
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEstateModule.cs4
-rw-r--r--OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs71
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISoundModule.cs93
-rw-r--r--OpenSim/Region/Framework/Interfaces/IUrlModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IUserManagement.cs29
-rw-r--r--OpenSim/Region/Framework/Interfaces/IWorldComm.cs26
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs13
-rw-r--r--OpenSim/Region/Framework/Scenes/EventManager.cs521
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs7
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs24
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs685
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs35
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneManager.cs6
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs106
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs300
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs58
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs56
-rw-r--r--OpenSim/Region/Framework/Scenes/SimStatsReporter.cs35
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs17
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs36
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs138
-rw-r--r--OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs7
-rw-r--r--OpenSim/Region/OptionalModules/Asset/AssetInfoModule.cs3
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs18
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs6
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs5
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs84
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs29
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs14
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs7
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs (renamed from OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs)81
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs18
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs11
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs (renamed from OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs)67
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs689
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs51
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs4
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs1051
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs (renamed from OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs)112
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs431
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs273
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs327
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs248
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs4
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs1364
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs978
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs1000
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs479
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs739
-rw-r--r--OpenSim/Region/Physics/Manager/PhysicsActor.cs6
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODECharacter.cs4
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODEPrim.cs25
-rw-r--r--OpenSim/Region/Physics/OdePlugin/OdeScene.cs17
-rw-r--r--OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs23
-rw-r--r--OpenSim/Region/RegionCombinerModule/RegionCourseLocation.cs2
-rw-r--r--OpenSim/Region/RegionCombinerModule/Resources/RegionCombinerModule.addin.xml14
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs1602
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs8
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs40
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs439
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs13
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs4
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs139
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs64
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs56
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Helpers.cs28
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs77
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs134
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs70
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs184
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/EventManager.cs29
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs10
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs57
-rw-r--r--OpenSim/Region/UserStatistics/WebStatsModule.cs56
-rw-r--r--OpenSim/Server/Base/ServicesServerBase.cs41
-rw-r--r--OpenSim/Server/Handlers/Asset/AssetServerConnector.cs20
-rw-r--r--OpenSim/Server/Handlers/Asset/AssetServerDeleteHandler.cs47
-rw-r--r--OpenSim/Server/Handlers/Avatar/AvatarServerPostHandler.cs18
-rw-r--r--OpenSim/Server/ServerMain.cs22
-rw-r--r--OpenSim/Services/AssetService/AssetService.cs17
-rw-r--r--OpenSim/Services/AssetService/AssetServiceBase.cs4
-rw-r--r--OpenSim/Services/AssetService/XAssetService.cs18
-rw-r--r--OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs8
-rw-r--r--OpenSim/Services/Connectors/Friends/FriendsSimConnector.cs6
-rw-r--r--OpenSim/Services/Connectors/GridUser/GridUserServicesConnector.cs9
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs8
-rw-r--r--OpenSim/Services/GridService/GridService.cs99
-rw-r--r--OpenSim/Services/GridService/HypergridLinker.cs6
-rw-r--r--OpenSim/Services/HypergridService/GatekeeperService.cs93
-rw-r--r--OpenSim/Services/HypergridService/HGAssetService.cs26
-rw-r--r--OpenSim/Services/HypergridService/HGFriendsService.cs2
-rw-r--r--OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs76
-rw-r--r--OpenSim/Services/HypergridService/UserAgentService.cs105
-rw-r--r--OpenSim/Services/Interfaces/IAssetService.cs6
-rw-r--r--OpenSim/Services/Interfaces/IGridService.cs13
-rw-r--r--OpenSim/Services/Interfaces/IGridUserService.cs3
-rw-r--r--OpenSim/Services/Interfaces/IPresenceService.cs38
-rw-r--r--OpenSim/Services/InventoryService/XInventoryService.cs65
-rw-r--r--OpenSim/Services/LLLoginService/LLLoginService.cs2
-rw-r--r--OpenSim/Services/UserAccountService/GridUserService.cs13
-rw-r--r--OpenSim/Tests/Common/Helpers/SceneHelpers.cs2
-rw-r--r--OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs4
-rw-r--r--OpenSim/Tests/Common/Mock/TestClient.cs16
-rw-r--r--OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs131
-rw-r--r--OpenSim/Tests/Common/TestHelpers.cs1
-rw-r--r--OpenSim/Tests/Stress/VectorRenderModuleStressTests.cs132
-rw-r--r--OpenSim/Tests/Torture/NPCTortureTests.cs (renamed from OpenSim/Tests/Performance/NPCPerformanceTests.cs)6
-rw-r--r--OpenSim/Tests/Torture/ObjectTortureTests.cs (renamed from OpenSim/Tests/Performance/ObjectPerformanceTests.cs)6
-rw-r--r--OpenSim/Tests/Torture/ScriptTortureTests.cs (renamed from OpenSim/Tests/Performance/ScriptPerformanceTests.cs)6
236 files changed, 6954 insertions, 17948 deletions
diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
index 9c933ee..437d150 100644
--- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
+++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
@@ -696,7 +696,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
696 696
697 region.ExternalHostName = (string) requestData["external_address"]; 697 region.ExternalHostName = (string) requestData["external_address"];
698 698
699 bool persist = Convert.ToBoolean(requestData["persist"]); 699 bool persist = Convert.ToBoolean((string) requestData["persist"]);
700 if (persist) 700 if (persist)
701 { 701 {
702 // default place for region configuration files is in the 702 // default place for region configuration files is in the
@@ -852,6 +852,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
852 responseData["success"] = true; 852 responseData["success"] = true;
853 responseData["region_name"] = region.RegionName; 853 responseData["region_name"] = region.RegionName;
854 responseData["region_id"] = region.RegionID.ToString(); 854 responseData["region_id"] = region.RegionID.ToString();
855 responseData["region_uuid"] = region.RegionID.ToString(); //Deprecate July 2012
855 856
856 m_log.Info("[RADMIN]: CreateRegion: request complete"); 857 m_log.Info("[RADMIN]: CreateRegion: request complete");
857 } 858 }
@@ -1105,8 +1106,8 @@ namespace OpenSim.ApplicationPlugins.RemoteController
1105 string lastName = (string) requestData["user_lastname"]; 1106 string lastName = (string) requestData["user_lastname"];
1106 string password = (string) requestData["user_password"]; 1107 string password = (string) requestData["user_password"];
1107 1108
1108 uint regionXLocation = Convert.ToUInt32(requestData["start_region_x"]); 1109 uint regionXLocation = Convert.ToUInt32((Int32) requestData["start_region_x"]);
1109 uint regionYLocation = Convert.ToUInt32(requestData["start_region_y"]); 1110 uint regionYLocation = Convert.ToUInt32((Int32) requestData["start_region_y"]);
1110 1111
1111 string email = ""; // empty string for email 1112 string email = ""; // empty string for email
1112 if (requestData.Contains("user_email")) 1113 if (requestData.Contains("user_email"))
@@ -1303,9 +1304,9 @@ namespace OpenSim.ApplicationPlugins.RemoteController
1303 1304
1304 if (requestData.ContainsKey("user_password")) password = (string) requestData["user_password"]; 1305 if (requestData.ContainsKey("user_password")) password = (string) requestData["user_password"];
1305 if (requestData.ContainsKey("start_region_x")) 1306 if (requestData.ContainsKey("start_region_x"))
1306 regionXLocation = Convert.ToUInt32(requestData["start_region_x"]); 1307 regionXLocation = Convert.ToUInt32((Int32) requestData["start_region_x"]);
1307 if (requestData.ContainsKey("start_region_y")) 1308 if (requestData.ContainsKey("start_region_y"))
1308 regionYLocation = Convert.ToUInt32(requestData["start_region_y"]); 1309 regionYLocation = Convert.ToUInt32((Int32) requestData["start_region_y"]);
1309 1310
1310 // if (requestData.ContainsKey("start_lookat_x")) 1311 // if (requestData.ContainsKey("start_lookat_x"))
1311 // ulaX = Convert.ToUInt32((Int32) requestData["start_lookat_x"]); 1312 // ulaX = Convert.ToUInt32((Int32) requestData["start_lookat_x"]);
@@ -1492,8 +1493,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController
1492 /// <description>profile url</description></item> 1493 /// <description>profile url</description></item>
1493 /// <item><term>noassets</term> 1494 /// <item><term>noassets</term>
1494 /// <description>true if no assets should be saved</description></item> 1495 /// <description>true if no assets should be saved</description></item>
1495 /// <item><term>all</term>
1496 /// <description>true to save all the regions in the simulator</description></item>
1497 /// <item><term>perm</term> 1496 /// <item><term>perm</term>
1498 /// <description>C and/or T</description></item> 1497 /// <description>C and/or T</description></item>
1499 /// </list> 1498 /// </list>
@@ -1550,11 +1549,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController
1550 options["checkPermissions"] = (string)requestData["perm"]; 1549 options["checkPermissions"] = (string)requestData["perm"];
1551 } 1550 }
1552 1551
1553 if ((string)requestData["all"] == "true")
1554 {
1555 options["all"] = (string)requestData["all"];
1556 }
1557
1558 IRegionArchiverModule archiver = scene.RequestModuleInterface<IRegionArchiverModule>(); 1552 IRegionArchiverModule archiver = scene.RequestModuleInterface<IRegionArchiverModule>();
1559 1553
1560 if (archiver != null) 1554 if (archiver != null)
@@ -2014,6 +2008,29 @@ namespace OpenSim.ApplicationPlugins.RemoteController
2014 { 2008 {
2015 return; 2009 return;
2016 } 2010 }
2011 #region Deprecate July 2012
2012 //region_ID, regionid, region_uuid will be deprecated in July 2012!!!!!!
2013 else if (requestData.ContainsKey("regionid") &&
2014 !String.IsNullOrEmpty((string)requestData["regionid"]))
2015 {
2016 m_log.WarnFormat("[RADMIN]: Use of parameter regionid will be deprecated as of July 2012. Use region_id instead");
2017 }
2018 else if (requestData.ContainsKey("region_ID") &&
2019 !String.IsNullOrEmpty((string)requestData["region_ID"]))
2020 {
2021 m_log.WarnFormat("[RADMIN]: Use of parameter region_ID will be deprecated as of July 2012. Use region_id instead");
2022 }
2023 else if (requestData.ContainsKey("regionID") &&
2024 !String.IsNullOrEmpty((string)requestData["regionID"]))
2025 {
2026 m_log.WarnFormat("[RADMIN]: Use of parameter regionID will be deprecated as of July 2012. Use region_id instead");
2027 }
2028 else if (requestData.ContainsKey("region_uuid") &&
2029 !String.IsNullOrEmpty((string)requestData["region_uuid"]))
2030 {
2031 m_log.WarnFormat("[RADMIN]: Use of parameter region_uuid will be deprecated as of July 2012. Use region_id instead");
2032 }
2033 #endregion
2017 else 2034 else
2018 { 2035 {
2019 responseData["accepted"] = false; 2036 responseData["accepted"] = false;
@@ -2035,6 +2052,56 @@ namespace OpenSim.ApplicationPlugins.RemoteController
2035 throw new Exception(String.Format("Region ID {0} not found", regionID)); 2052 throw new Exception(String.Format("Region ID {0} not found", regionID));
2036 } 2053 }
2037 } 2054 }
2055 #region Deprecate July 2012
2056 else if (requestData.ContainsKey("regionid") &&
2057 !String.IsNullOrEmpty((string)requestData["regionid"]))
2058 {
2059 m_log.WarnFormat("[RADMIN]: Use of parameter regionid will be deprecated as of July 2012. Use region_id instead");
2060
2061 UUID regionID = (UUID)(string)requestData["regionid"];
2062 if (!m_application.SceneManager.TryGetScene(regionID, out scene))
2063 {
2064 responseData["error"] = String.Format("Region ID {0} not found", regionID);
2065 throw new Exception(String.Format("Region ID {0} not found", regionID));
2066 }
2067 }
2068 else if (requestData.ContainsKey("region_ID") &&
2069 !String.IsNullOrEmpty((string)requestData["region_ID"]))
2070 {
2071 m_log.WarnFormat("[RADMIN]: Use of parameter region_ID will be deprecated as of July 2012. Use region_id instead");
2072
2073 UUID regionID = (UUID)(string)requestData["region_ID"];
2074 if (!m_application.SceneManager.TryGetScene(regionID, out scene))
2075 {
2076 responseData["error"] = String.Format("Region ID {0} not found", regionID);
2077 throw new Exception(String.Format("Region ID {0} not found", regionID));
2078 }
2079 }
2080 else if (requestData.ContainsKey("regionID") &&
2081 !String.IsNullOrEmpty((string)requestData["regionID"]))
2082 {
2083 m_log.WarnFormat("[RADMIN]: Use of parameter regionID will be deprecated as of July 2012. Use region_id instead");
2084
2085 UUID regionID = (UUID)(string)requestData["regionID"];
2086 if (!m_application.SceneManager.TryGetScene(regionID, out scene))
2087 {
2088 responseData["error"] = String.Format("Region ID {0} not found", regionID);
2089 throw new Exception(String.Format("Region ID {0} not found", regionID));
2090 }
2091 }
2092 else if (requestData.ContainsKey("region_uuid") &&
2093 !String.IsNullOrEmpty((string)requestData["region_uuid"]))
2094 {
2095 m_log.WarnFormat("[RADMIN]: Use of parameter region_uuid will be deprecated as of July 2012. Use region_id instead");
2096
2097 UUID regionID = (UUID)(string)requestData["region_uuid"];
2098 if (!m_application.SceneManager.TryGetScene(regionID, out scene))
2099 {
2100 responseData["error"] = String.Format("Region ID {0} not found", regionID);
2101 throw new Exception(String.Format("Region ID {0} not found", regionID));
2102 }
2103 }
2104 #endregion
2038 else if (requestData.ContainsKey("region_name") && 2105 else if (requestData.ContainsKey("region_name") &&
2039 !String.IsNullOrEmpty((string)requestData["region_name"])) 2106 !String.IsNullOrEmpty((string)requestData["region_name"]))
2040 { 2107 {
diff --git a/OpenSim/ApplicationPlugins/Rest/Inventory/RestHandler.cs b/OpenSim/ApplicationPlugins/Rest/Inventory/RestHandler.cs
index 072bd6f..cb88695 100644
--- a/OpenSim/ApplicationPlugins/Rest/Inventory/RestHandler.cs
+++ b/OpenSim/ApplicationPlugins/Rest/Inventory/RestHandler.cs
@@ -312,16 +312,14 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
312 // Now that everything is setup we can proceed to 312 // Now that everything is setup we can proceed to
313 // add THIS agent to the HTTP server's handler list 313 // add THIS agent to the HTTP server's handler list
314 314
315 // FIXME: If this code is ever to be re-enabled (most of it is disabled already) then this will 315 if (!AddAgentHandler(Rest.Name,this))
316 // have to be handled through the AddHttpHandler interface. 316 {
317// if (!AddAgentHandler(Rest.Name,this)) 317 Rest.Log.ErrorFormat("{0} Unable to activate handler interface", MsgId);
318// { 318 foreach (IRest handler in handlers)
319// Rest.Log.ErrorFormat("{0} Unable to activate handler interface", MsgId); 319 {
320// foreach (IRest handler in handlers) 320 handler.Close();
321// { 321 }
322// handler.Close(); 322 }
323// }
324// }
325 323
326 } 324 }
327 catch (Exception e) 325 catch (Exception e)
@@ -344,13 +342,11 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
344 { 342 {
345 Rest.Log.InfoFormat("{0} Plugin is terminating", MsgId); 343 Rest.Log.InfoFormat("{0} Plugin is terminating", MsgId);
346 344
347 // FIXME: If this code is ever to be re-enabled (most of it is disabled already) then this will 345 try
348 // have to be handled through the AddHttpHandler interface. 346 {
349// try 347 RemoveAgentHandler(Rest.Name, this);
350// { 348 }
351// RemoveAgentHandler(Rest.Name, this); 349 catch (KeyNotFoundException){}
352// }
353// catch (KeyNotFoundException){}
354 350
355 foreach (IRest handler in handlers) 351 foreach (IRest handler in handlers)
356 { 352 {
diff --git a/OpenSim/ApplicationPlugins/Rest/RestPlugin.cs b/OpenSim/ApplicationPlugins/Rest/RestPlugin.cs
index a2425b5..eb16750 100644
--- a/OpenSim/ApplicationPlugins/Rest/RestPlugin.cs
+++ b/OpenSim/ApplicationPlugins/Rest/RestPlugin.cs
@@ -297,9 +297,7 @@ namespace OpenSim.ApplicationPlugins.Rest
297 { 297 {
298 if (!IsEnabled) return false; 298 if (!IsEnabled) return false;
299 _agents.Add(agentName, handler); 299 _agents.Add(agentName, handler);
300// return _httpd.AddAgentHandler(agentName, handler); 300 return _httpd.AddAgentHandler(agentName, handler);
301
302 return false;
303 } 301 }
304 302
305 /// <summary> 303 /// <summary>
@@ -318,7 +316,7 @@ namespace OpenSim.ApplicationPlugins.Rest
318 if (_agents[agentName] == handler) 316 if (_agents[agentName] == handler)
319 { 317 {
320 _agents.Remove(agentName); 318 _agents.Remove(agentName);
321// return _httpd.RemoveAgentHandler(agentName, handler); 319 return _httpd.RemoveAgentHandler(agentName, handler);
322 } 320 }
323 return false; 321 return false;
324 } 322 }
@@ -360,10 +358,10 @@ namespace OpenSim.ApplicationPlugins.Rest
360 _httpd.RemoveStreamHandler(h.HttpMethod, h.Path); 358 _httpd.RemoveStreamHandler(h.HttpMethod, h.Path);
361 } 359 }
362 _handlers = null; 360 _handlers = null;
363// foreach (KeyValuePair<string, IHttpAgentHandler> h in _agents) 361 foreach (KeyValuePair<string, IHttpAgentHandler> h in _agents)
364// { 362 {
365// _httpd.RemoveAgentHandler(h.Key, h.Value); 363 _httpd.RemoveAgentHandler(h.Key, h.Value);
366// } 364 }
367 _agents = null; 365 _agents = null;
368 } 366 }
369 367
diff --git a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
index 6437d0b..86e7aa0 100644
--- a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
+++ b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
@@ -200,25 +200,11 @@ namespace OpenSim.Capabilities.Handlers
200 int start, end; 200 int start, end;
201 if (TryParseRange(range, out start, out end)) 201 if (TryParseRange(range, out start, out end))
202 { 202 {
203
203 // Before clamping start make sure we can satisfy it in order to avoid 204 // Before clamping start make sure we can satisfy it in order to avoid
204 // sending back the last byte instead of an error status 205 // sending back the last byte instead of an error status
205 if (start >= texture.Data.Length) 206 if (start >= texture.Data.Length)
206 { 207 {
207// m_log.DebugFormat(
208// "[GETTEXTURE]: Client requested range for texture {0} starting at {1} but texture has end of {2}",
209// texture.ID, start, texture.Data.Length);
210
211 // Stricly speaking, as per http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html, we should be sending back
212 // Requested Range Not Satisfiable (416) here. However, it appears that at least recent implementations
213 // of the Linden Lab viewer (3.2.1 and 3.3.4 and probably earlier), a viewer that has previously
214 // received a very small texture may attempt to fetch bytes from the server past the
215 // range of data that it received originally. Whether this happens appears to depend on whether
216 // the viewer's estimation of how large a request it needs to make for certain discard levels
217 // (http://wiki.secondlife.com/wiki/Image_System#Discard_Level_and_Mip_Mapping), chiefly discard
218 // level 2. If this estimate is greater than the total texture size, returning a RequestedRangeNotSatisfiable
219 // here will cause the viewer to treat the texture as bad and never display the full resolution
220 // However, if we return PartialContent (or OK) instead, the viewer will display that resolution.
221
222// response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable; 208// response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable;
223 // viewers don't seem to handle RequestedRangeNotSatisfiable and keep retrying with same parameters 209 // viewers don't seem to handle RequestedRangeNotSatisfiable and keep retrying with same parameters
224 response["int_response_code"] = (int)System.Net.HttpStatusCode.NotFound; 210 response["int_response_code"] = (int)System.Net.HttpStatusCode.NotFound;
@@ -229,7 +215,7 @@ namespace OpenSim.Capabilities.Handlers
229 start = Utils.Clamp(start, 0, end); 215 start = Utils.Clamp(start, 0, end);
230 int len = end - start + 1; 216 int len = end - start + 1;
231 217
232// m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID); 218 //m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
233 219
234 response["content-type"] = texture.Metadata.ContentType; 220 response["content-type"] = texture.Metadata.ContentType;
235 221
diff --git a/OpenSim/Data/IRegionData.cs b/OpenSim/Data/IRegionData.cs
index 70e1065..546b5e8 100644
--- a/OpenSim/Data/IRegionData.cs
+++ b/OpenSim/Data/IRegionData.cs
@@ -85,6 +85,21 @@ namespace OpenSim.Data
85 List<RegionData> GetHyperlinks(UUID scopeID); 85 List<RegionData> GetHyperlinks(UUID scopeID);
86 } 86 }
87 87
88 [Flags]
89 public enum RegionFlags : int
90 {
91 DefaultRegion = 1, // Used for new Rez. Random if multiple defined
92 FallbackRegion = 2, // Regions we redirect to when the destination is down
93 RegionOnline = 4, // Set when a region comes online, unset when it unregisters and DeleteOnUnregister is false
94 NoDirectLogin = 8, // Region unavailable for direct logins (by name)
95 Persistent = 16, // Don't remove on unregister
96 LockedOut = 32, // Don't allow registration
97 NoMove = 64, // Don't allow moving this region
98 Reservation = 128, // This is an inactive reservation
99 Authenticate = 256, // Require authentication
100 Hyperlink = 512 // Record represents a HG link
101 }
102
88 public class RegionDataDistanceCompare : IComparer<RegionData> 103 public class RegionDataDistanceCompare : IComparer<RegionData>
89 { 104 {
90 private Vector2 m_origin; 105 private Vector2 m_origin;
diff --git a/OpenSim/Data/IXInventoryData.cs b/OpenSim/Data/IXInventoryData.cs
index e64a828..85a5c08 100644
--- a/OpenSim/Data/IXInventoryData.cs
+++ b/OpenSim/Data/IXInventoryData.cs
@@ -40,11 +40,6 @@ namespace OpenSim.Data
40 public UUID folderID; 40 public UUID folderID;
41 public UUID agentID; 41 public UUID agentID;
42 public UUID parentFolderID; 42 public UUID parentFolderID;
43
44 public XInventoryFolder Clone()
45 {
46 return (XInventoryFolder)MemberwiseClone();
47 }
48 } 43 }
49 44
50 public class XInventoryItem 45 public class XInventoryItem
@@ -69,11 +64,6 @@ namespace OpenSim.Data
69 public UUID avatarID; 64 public UUID avatarID;
70 public UUID parentFolderID; 65 public UUID parentFolderID;
71 public int inventoryGroupPermissions; 66 public int inventoryGroupPermissions;
72
73 public XInventoryItem Clone()
74 {
75 return (XInventoryItem)MemberwiseClone();
76 }
77 } 67 }
78 68
79 public interface IXInventoryData 69 public interface IXInventoryData
diff --git a/OpenSim/Data/MSSQL/MSSQLRegionData.cs b/OpenSim/Data/MSSQL/MSSQLRegionData.cs
index 0d89706..3ae87c3 100644
--- a/OpenSim/Data/MSSQL/MSSQLRegionData.cs
+++ b/OpenSim/Data/MSSQL/MSSQLRegionData.cs
@@ -37,7 +37,6 @@ using OpenMetaverse;
37using OpenSim.Framework; 37using OpenSim.Framework;
38using OpenSim.Region.Framework.Interfaces; 38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes; 39using OpenSim.Region.Framework.Scenes;
40using RegionFlags = OpenSim.Framework.RegionFlags;
41 40
42namespace OpenSim.Data.MSSQL 41namespace OpenSim.Data.MSSQL
43{ 42{
diff --git a/OpenSim/Data/MySQL/MySQLRegionData.cs b/OpenSim/Data/MySQL/MySQLRegionData.cs
index a2d4ae4..0614879 100644
--- a/OpenSim/Data/MySQL/MySQLRegionData.cs
+++ b/OpenSim/Data/MySQL/MySQLRegionData.cs
@@ -30,11 +30,11 @@ using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Data; 31using System.Data;
32using System.Reflection; 32using System.Reflection;
33using MySql.Data.MySqlClient; 33
34using OpenMetaverse; 34using OpenMetaverse;
35using OpenSim.Framework; 35using OpenSim.Framework;
36using OpenSim.Data; 36using OpenSim.Data;
37using RegionFlags = OpenSim.Framework.RegionFlags; 37using MySql.Data.MySqlClient;
38 38
39namespace OpenSim.Data.MySQL 39namespace OpenSim.Data.MySQL
40{ 40{
diff --git a/OpenSim/Data/MySQL/MySQLSimulationData.cs b/OpenSim/Data/MySQL/MySQLSimulationData.cs
index 12c979a..4d7c0c9 100644
--- a/OpenSim/Data/MySQL/MySQLSimulationData.cs
+++ b/OpenSim/Data/MySQL/MySQLSimulationData.cs
@@ -747,99 +747,95 @@ namespace OpenSim.Data.MySQL
747 RegionLightShareData nWP = new RegionLightShareData(); 747 RegionLightShareData nWP = new RegionLightShareData();
748 nWP.OnSave += StoreRegionWindlightSettings; 748 nWP.OnSave += StoreRegionWindlightSettings;
749 749
750 lock (m_dbLock) 750 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
751 { 751 {
752 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) 752 dbcon.Open();
753
754 string command = "select * from `regionwindlight` where region_id = ?regionID";
755
756 using (MySqlCommand cmd = new MySqlCommand(command))
753 { 757 {
754 dbcon.Open(); 758 cmd.Connection = dbcon;
755 759
756 string command = "select * from `regionwindlight` where region_id = ?regionID"; 760 cmd.Parameters.AddWithValue("?regionID", regionUUID.ToString());
757 761
758 using (MySqlCommand cmd = new MySqlCommand(command)) 762 IDataReader result = ExecuteReader(cmd);
763 if (!result.Read())
759 { 764 {
760 cmd.Connection = dbcon; 765 //No result, so store our default windlight profile and return it
761 766 nWP.regionID = regionUUID;
762 cmd.Parameters.AddWithValue("?regionID", regionUUID.ToString()); 767 // StoreRegionWindlightSettings(nWP);
763 768 return nWP;
764 IDataReader result = ExecuteReader(cmd); 769 }
765 if (!result.Read()) 770 else
766 { 771 {
767 //No result, so store our default windlight profile and return it 772 nWP.regionID = DBGuid.FromDB(result["region_id"]);
768 nWP.regionID = regionUUID; 773 nWP.waterColor.X = Convert.ToSingle(result["water_color_r"]);
769// StoreRegionWindlightSettings(nWP); 774 nWP.waterColor.Y = Convert.ToSingle(result["water_color_g"]);
770 return nWP; 775 nWP.waterColor.Z = Convert.ToSingle(result["water_color_b"]);
771 } 776 nWP.waterFogDensityExponent = Convert.ToSingle(result["water_fog_density_exponent"]);
772 else 777 nWP.underwaterFogModifier = Convert.ToSingle(result["underwater_fog_modifier"]);
773 { 778 nWP.reflectionWaveletScale.X = Convert.ToSingle(result["reflection_wavelet_scale_1"]);
774 nWP.regionID = DBGuid.FromDB(result["region_id"]); 779 nWP.reflectionWaveletScale.Y = Convert.ToSingle(result["reflection_wavelet_scale_2"]);
775 nWP.waterColor.X = Convert.ToSingle(result["water_color_r"]); 780 nWP.reflectionWaveletScale.Z = Convert.ToSingle(result["reflection_wavelet_scale_3"]);
776 nWP.waterColor.Y = Convert.ToSingle(result["water_color_g"]); 781 nWP.fresnelScale = Convert.ToSingle(result["fresnel_scale"]);
777 nWP.waterColor.Z = Convert.ToSingle(result["water_color_b"]); 782 nWP.fresnelOffset = Convert.ToSingle(result["fresnel_offset"]);
778 nWP.waterFogDensityExponent = Convert.ToSingle(result["water_fog_density_exponent"]); 783 nWP.refractScaleAbove = Convert.ToSingle(result["refract_scale_above"]);
779 nWP.underwaterFogModifier = Convert.ToSingle(result["underwater_fog_modifier"]); 784 nWP.refractScaleBelow = Convert.ToSingle(result["refract_scale_below"]);
780 nWP.reflectionWaveletScale.X = Convert.ToSingle(result["reflection_wavelet_scale_1"]); 785 nWP.blurMultiplier = Convert.ToSingle(result["blur_multiplier"]);
781 nWP.reflectionWaveletScale.Y = Convert.ToSingle(result["reflection_wavelet_scale_2"]); 786 nWP.bigWaveDirection.X = Convert.ToSingle(result["big_wave_direction_x"]);
782 nWP.reflectionWaveletScale.Z = Convert.ToSingle(result["reflection_wavelet_scale_3"]); 787 nWP.bigWaveDirection.Y = Convert.ToSingle(result["big_wave_direction_y"]);
783 nWP.fresnelScale = Convert.ToSingle(result["fresnel_scale"]); 788 nWP.littleWaveDirection.X = Convert.ToSingle(result["little_wave_direction_x"]);
784 nWP.fresnelOffset = Convert.ToSingle(result["fresnel_offset"]); 789 nWP.littleWaveDirection.Y = Convert.ToSingle(result["little_wave_direction_y"]);
785 nWP.refractScaleAbove = Convert.ToSingle(result["refract_scale_above"]); 790 UUID.TryParse(result["normal_map_texture"].ToString(), out nWP.normalMapTexture);
786 nWP.refractScaleBelow = Convert.ToSingle(result["refract_scale_below"]); 791 nWP.horizon.X = Convert.ToSingle(result["horizon_r"]);
787 nWP.blurMultiplier = Convert.ToSingle(result["blur_multiplier"]); 792 nWP.horizon.Y = Convert.ToSingle(result["horizon_g"]);
788 nWP.bigWaveDirection.X = Convert.ToSingle(result["big_wave_direction_x"]); 793 nWP.horizon.Z = Convert.ToSingle(result["horizon_b"]);
789 nWP.bigWaveDirection.Y = Convert.ToSingle(result["big_wave_direction_y"]); 794 nWP.horizon.W = Convert.ToSingle(result["horizon_i"]);
790 nWP.littleWaveDirection.X = Convert.ToSingle(result["little_wave_direction_x"]); 795 nWP.hazeHorizon = Convert.ToSingle(result["haze_horizon"]);
791 nWP.littleWaveDirection.Y = Convert.ToSingle(result["little_wave_direction_y"]); 796 nWP.blueDensity.X = Convert.ToSingle(result["blue_density_r"]);
792 UUID.TryParse(result["normal_map_texture"].ToString(), out nWP.normalMapTexture); 797 nWP.blueDensity.Y = Convert.ToSingle(result["blue_density_g"]);
793 nWP.horizon.X = Convert.ToSingle(result["horizon_r"]); 798 nWP.blueDensity.Z = Convert.ToSingle(result["blue_density_b"]);
794 nWP.horizon.Y = Convert.ToSingle(result["horizon_g"]); 799 nWP.blueDensity.W = Convert.ToSingle(result["blue_density_i"]);
795 nWP.horizon.Z = Convert.ToSingle(result["horizon_b"]); 800 nWP.hazeDensity = Convert.ToSingle(result["haze_density"]);
796 nWP.horizon.W = Convert.ToSingle(result["horizon_i"]); 801 nWP.densityMultiplier = Convert.ToSingle(result["density_multiplier"]);
797 nWP.hazeHorizon = Convert.ToSingle(result["haze_horizon"]); 802 nWP.distanceMultiplier = Convert.ToSingle(result["distance_multiplier"]);
798 nWP.blueDensity.X = Convert.ToSingle(result["blue_density_r"]); 803 nWP.maxAltitude = Convert.ToUInt16(result["max_altitude"]);
799 nWP.blueDensity.Y = Convert.ToSingle(result["blue_density_g"]); 804 nWP.sunMoonColor.X = Convert.ToSingle(result["sun_moon_color_r"]);
800 nWP.blueDensity.Z = Convert.ToSingle(result["blue_density_b"]); 805 nWP.sunMoonColor.Y = Convert.ToSingle(result["sun_moon_color_g"]);
801 nWP.blueDensity.W = Convert.ToSingle(result["blue_density_i"]); 806 nWP.sunMoonColor.Z = Convert.ToSingle(result["sun_moon_color_b"]);
802 nWP.hazeDensity = Convert.ToSingle(result["haze_density"]); 807 nWP.sunMoonColor.W = Convert.ToSingle(result["sun_moon_color_i"]);
803 nWP.densityMultiplier = Convert.ToSingle(result["density_multiplier"]); 808 nWP.sunMoonPosition = Convert.ToSingle(result["sun_moon_position"]);
804 nWP.distanceMultiplier = Convert.ToSingle(result["distance_multiplier"]); 809 nWP.ambient.X = Convert.ToSingle(result["ambient_r"]);
805 nWP.maxAltitude = Convert.ToUInt16(result["max_altitude"]); 810 nWP.ambient.Y = Convert.ToSingle(result["ambient_g"]);
806 nWP.sunMoonColor.X = Convert.ToSingle(result["sun_moon_color_r"]); 811 nWP.ambient.Z = Convert.ToSingle(result["ambient_b"]);
807 nWP.sunMoonColor.Y = Convert.ToSingle(result["sun_moon_color_g"]); 812 nWP.ambient.W = Convert.ToSingle(result["ambient_i"]);
808 nWP.sunMoonColor.Z = Convert.ToSingle(result["sun_moon_color_b"]); 813 nWP.eastAngle = Convert.ToSingle(result["east_angle"]);
809 nWP.sunMoonColor.W = Convert.ToSingle(result["sun_moon_color_i"]); 814 nWP.sunGlowFocus = Convert.ToSingle(result["sun_glow_focus"]);
810 nWP.sunMoonPosition = Convert.ToSingle(result["sun_moon_position"]); 815 nWP.sunGlowSize = Convert.ToSingle(result["sun_glow_size"]);
811 nWP.ambient.X = Convert.ToSingle(result["ambient_r"]); 816 nWP.sceneGamma = Convert.ToSingle(result["scene_gamma"]);
812 nWP.ambient.Y = Convert.ToSingle(result["ambient_g"]); 817 nWP.starBrightness = Convert.ToSingle(result["star_brightness"]);
813 nWP.ambient.Z = Convert.ToSingle(result["ambient_b"]); 818 nWP.cloudColor.X = Convert.ToSingle(result["cloud_color_r"]);
814 nWP.ambient.W = Convert.ToSingle(result["ambient_i"]); 819 nWP.cloudColor.Y = Convert.ToSingle(result["cloud_color_g"]);
815 nWP.eastAngle = Convert.ToSingle(result["east_angle"]); 820 nWP.cloudColor.Z = Convert.ToSingle(result["cloud_color_b"]);
816 nWP.sunGlowFocus = Convert.ToSingle(result["sun_glow_focus"]); 821 nWP.cloudColor.W = Convert.ToSingle(result["cloud_color_i"]);
817 nWP.sunGlowSize = Convert.ToSingle(result["sun_glow_size"]); 822 nWP.cloudXYDensity.X = Convert.ToSingle(result["cloud_x"]);
818 nWP.sceneGamma = Convert.ToSingle(result["scene_gamma"]); 823 nWP.cloudXYDensity.Y = Convert.ToSingle(result["cloud_y"]);
819 nWP.starBrightness = Convert.ToSingle(result["star_brightness"]); 824 nWP.cloudXYDensity.Z = Convert.ToSingle(result["cloud_density"]);
820 nWP.cloudColor.X = Convert.ToSingle(result["cloud_color_r"]); 825 nWP.cloudCoverage = Convert.ToSingle(result["cloud_coverage"]);
821 nWP.cloudColor.Y = Convert.ToSingle(result["cloud_color_g"]); 826 nWP.cloudScale = Convert.ToSingle(result["cloud_scale"]);
822 nWP.cloudColor.Z = Convert.ToSingle(result["cloud_color_b"]); 827 nWP.cloudDetailXYDensity.X = Convert.ToSingle(result["cloud_detail_x"]);
823 nWP.cloudColor.W = Convert.ToSingle(result["cloud_color_i"]); 828 nWP.cloudDetailXYDensity.Y = Convert.ToSingle(result["cloud_detail_y"]);
824 nWP.cloudXYDensity.X = Convert.ToSingle(result["cloud_x"]); 829 nWP.cloudDetailXYDensity.Z = Convert.ToSingle(result["cloud_detail_density"]);
825 nWP.cloudXYDensity.Y = Convert.ToSingle(result["cloud_y"]); 830 nWP.cloudScrollX = Convert.ToSingle(result["cloud_scroll_x"]);
826 nWP.cloudXYDensity.Z = Convert.ToSingle(result["cloud_density"]); 831 nWP.cloudScrollXLock = Convert.ToBoolean(result["cloud_scroll_x_lock"]);
827 nWP.cloudCoverage = Convert.ToSingle(result["cloud_coverage"]); 832 nWP.cloudScrollY = Convert.ToSingle(result["cloud_scroll_y"]);
828 nWP.cloudScale = Convert.ToSingle(result["cloud_scale"]); 833 nWP.cloudScrollYLock = Convert.ToBoolean(result["cloud_scroll_y_lock"]);
829 nWP.cloudDetailXYDensity.X = Convert.ToSingle(result["cloud_detail_x"]); 834 nWP.drawClassicClouds = Convert.ToBoolean(result["draw_classic_clouds"]);
830 nWP.cloudDetailXYDensity.Y = Convert.ToSingle(result["cloud_detail_y"]); 835 nWP.valid = true;
831 nWP.cloudDetailXYDensity.Z = Convert.ToSingle(result["cloud_detail_density"]);
832 nWP.cloudScrollX = Convert.ToSingle(result["cloud_scroll_x"]);
833 nWP.cloudScrollXLock = Convert.ToBoolean(result["cloud_scroll_x_lock"]);
834 nWP.cloudScrollY = Convert.ToSingle(result["cloud_scroll_y"]);
835 nWP.cloudScrollYLock = Convert.ToBoolean(result["cloud_scroll_y_lock"]);
836 nWP.drawClassicClouds = Convert.ToBoolean(result["draw_classic_clouds"]);
837 nWP.valid = true;
838 }
839 } 836 }
840 } 837 }
841 } 838 }
842
843 return nWP; 839 return nWP;
844 } 840 }
845 841
@@ -885,124 +881,118 @@ namespace OpenSim.Data.MySQL
885 881
886 public virtual void StoreRegionWindlightSettings(RegionLightShareData wl) 882 public virtual void StoreRegionWindlightSettings(RegionLightShareData wl)
887 { 883 {
888 lock (m_dbLock) 884 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
889 { 885 {
890 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) 886 dbcon.Open();
887
888 using (MySqlCommand cmd = dbcon.CreateCommand())
891 { 889 {
892 dbcon.Open(); 890 cmd.CommandText = "REPLACE INTO `regionwindlight` (`region_id`, `water_color_r`, `water_color_g`, ";
893 891 cmd.CommandText += "`water_color_b`, `water_fog_density_exponent`, `underwater_fog_modifier`, ";
894 using (MySqlCommand cmd = dbcon.CreateCommand()) 892 cmd.CommandText += "`reflection_wavelet_scale_1`, `reflection_wavelet_scale_2`, `reflection_wavelet_scale_3`, ";
895 { 893 cmd.CommandText += "`fresnel_scale`, `fresnel_offset`, `refract_scale_above`, `refract_scale_below`, ";
896 cmd.CommandText = "REPLACE INTO `regionwindlight` (`region_id`, `water_color_r`, `water_color_g`, "; 894 cmd.CommandText += "`blur_multiplier`, `big_wave_direction_x`, `big_wave_direction_y`, `little_wave_direction_x`, ";
897 cmd.CommandText += "`water_color_b`, `water_fog_density_exponent`, `underwater_fog_modifier`, "; 895 cmd.CommandText += "`little_wave_direction_y`, `normal_map_texture`, `horizon_r`, `horizon_g`, `horizon_b`, ";
898 cmd.CommandText += "`reflection_wavelet_scale_1`, `reflection_wavelet_scale_2`, `reflection_wavelet_scale_3`, "; 896 cmd.CommandText += "`horizon_i`, `haze_horizon`, `blue_density_r`, `blue_density_g`, `blue_density_b`, ";
899 cmd.CommandText += "`fresnel_scale`, `fresnel_offset`, `refract_scale_above`, `refract_scale_below`, "; 897 cmd.CommandText += "`blue_density_i`, `haze_density`, `density_multiplier`, `distance_multiplier`, `max_altitude`, ";
900 cmd.CommandText += "`blur_multiplier`, `big_wave_direction_x`, `big_wave_direction_y`, `little_wave_direction_x`, "; 898 cmd.CommandText += "`sun_moon_color_r`, `sun_moon_color_g`, `sun_moon_color_b`, `sun_moon_color_i`, `sun_moon_position`, ";
901 cmd.CommandText += "`little_wave_direction_y`, `normal_map_texture`, `horizon_r`, `horizon_g`, `horizon_b`, "; 899 cmd.CommandText += "`ambient_r`, `ambient_g`, `ambient_b`, `ambient_i`, `east_angle`, `sun_glow_focus`, `sun_glow_size`, ";
902 cmd.CommandText += "`horizon_i`, `haze_horizon`, `blue_density_r`, `blue_density_g`, `blue_density_b`, "; 900 cmd.CommandText += "`scene_gamma`, `star_brightness`, `cloud_color_r`, `cloud_color_g`, `cloud_color_b`, `cloud_color_i`, ";
903 cmd.CommandText += "`blue_density_i`, `haze_density`, `density_multiplier`, `distance_multiplier`, `max_altitude`, "; 901 cmd.CommandText += "`cloud_x`, `cloud_y`, `cloud_density`, `cloud_coverage`, `cloud_scale`, `cloud_detail_x`, ";
904 cmd.CommandText += "`sun_moon_color_r`, `sun_moon_color_g`, `sun_moon_color_b`, `sun_moon_color_i`, `sun_moon_position`, "; 902 cmd.CommandText += "`cloud_detail_y`, `cloud_detail_density`, `cloud_scroll_x`, `cloud_scroll_x_lock`, `cloud_scroll_y`, ";
905 cmd.CommandText += "`ambient_r`, `ambient_g`, `ambient_b`, `ambient_i`, `east_angle`, `sun_glow_focus`, `sun_glow_size`, "; 903 cmd.CommandText += "`cloud_scroll_y_lock`, `draw_classic_clouds`) VALUES (?region_id, ?water_color_r, ";
906 cmd.CommandText += "`scene_gamma`, `star_brightness`, `cloud_color_r`, `cloud_color_g`, `cloud_color_b`, `cloud_color_i`, "; 904 cmd.CommandText += "?water_color_g, ?water_color_b, ?water_fog_density_exponent, ?underwater_fog_modifier, ?reflection_wavelet_scale_1, ";
907 cmd.CommandText += "`cloud_x`, `cloud_y`, `cloud_density`, `cloud_coverage`, `cloud_scale`, `cloud_detail_x`, "; 905 cmd.CommandText += "?reflection_wavelet_scale_2, ?reflection_wavelet_scale_3, ?fresnel_scale, ?fresnel_offset, ?refract_scale_above, ";
908 cmd.CommandText += "`cloud_detail_y`, `cloud_detail_density`, `cloud_scroll_x`, `cloud_scroll_x_lock`, `cloud_scroll_y`, "; 906 cmd.CommandText += "?refract_scale_below, ?blur_multiplier, ?big_wave_direction_x, ?big_wave_direction_y, ?little_wave_direction_x, ";
909 cmd.CommandText += "`cloud_scroll_y_lock`, `draw_classic_clouds`) VALUES (?region_id, ?water_color_r, "; 907 cmd.CommandText += "?little_wave_direction_y, ?normal_map_texture, ?horizon_r, ?horizon_g, ?horizon_b, ?horizon_i, ?haze_horizon, ";
910 cmd.CommandText += "?water_color_g, ?water_color_b, ?water_fog_density_exponent, ?underwater_fog_modifier, ?reflection_wavelet_scale_1, "; 908 cmd.CommandText += "?blue_density_r, ?blue_density_g, ?blue_density_b, ?blue_density_i, ?haze_density, ?density_multiplier, ";
911 cmd.CommandText += "?reflection_wavelet_scale_2, ?reflection_wavelet_scale_3, ?fresnel_scale, ?fresnel_offset, ?refract_scale_above, "; 909 cmd.CommandText += "?distance_multiplier, ?max_altitude, ?sun_moon_color_r, ?sun_moon_color_g, ?sun_moon_color_b, ";
912 cmd.CommandText += "?refract_scale_below, ?blur_multiplier, ?big_wave_direction_x, ?big_wave_direction_y, ?little_wave_direction_x, "; 910 cmd.CommandText += "?sun_moon_color_i, ?sun_moon_position, ?ambient_r, ?ambient_g, ?ambient_b, ?ambient_i, ?east_angle, ";
913 cmd.CommandText += "?little_wave_direction_y, ?normal_map_texture, ?horizon_r, ?horizon_g, ?horizon_b, ?horizon_i, ?haze_horizon, "; 911 cmd.CommandText += "?sun_glow_focus, ?sun_glow_size, ?scene_gamma, ?star_brightness, ?cloud_color_r, ?cloud_color_g, ";
914 cmd.CommandText += "?blue_density_r, ?blue_density_g, ?blue_density_b, ?blue_density_i, ?haze_density, ?density_multiplier, "; 912 cmd.CommandText += "?cloud_color_b, ?cloud_color_i, ?cloud_x, ?cloud_y, ?cloud_density, ?cloud_coverage, ?cloud_scale, ";
915 cmd.CommandText += "?distance_multiplier, ?max_altitude, ?sun_moon_color_r, ?sun_moon_color_g, ?sun_moon_color_b, "; 913 cmd.CommandText += "?cloud_detail_x, ?cloud_detail_y, ?cloud_detail_density, ?cloud_scroll_x, ?cloud_scroll_x_lock, ";
916 cmd.CommandText += "?sun_moon_color_i, ?sun_moon_position, ?ambient_r, ?ambient_g, ?ambient_b, ?ambient_i, ?east_angle, "; 914 cmd.CommandText += "?cloud_scroll_y, ?cloud_scroll_y_lock, ?draw_classic_clouds)";
917 cmd.CommandText += "?sun_glow_focus, ?sun_glow_size, ?scene_gamma, ?star_brightness, ?cloud_color_r, ?cloud_color_g, "; 915
918 cmd.CommandText += "?cloud_color_b, ?cloud_color_i, ?cloud_x, ?cloud_y, ?cloud_density, ?cloud_coverage, ?cloud_scale, "; 916 cmd.Parameters.AddWithValue("region_id", wl.regionID);
919 cmd.CommandText += "?cloud_detail_x, ?cloud_detail_y, ?cloud_detail_density, ?cloud_scroll_x, ?cloud_scroll_x_lock, "; 917 cmd.Parameters.AddWithValue("water_color_r", wl.waterColor.X);
920 cmd.CommandText += "?cloud_scroll_y, ?cloud_scroll_y_lock, ?draw_classic_clouds)"; 918 cmd.Parameters.AddWithValue("water_color_g", wl.waterColor.Y);
921 919 cmd.Parameters.AddWithValue("water_color_b", wl.waterColor.Z);
922 cmd.Parameters.AddWithValue("region_id", wl.regionID); 920 cmd.Parameters.AddWithValue("water_fog_density_exponent", wl.waterFogDensityExponent);
923 cmd.Parameters.AddWithValue("water_color_r", wl.waterColor.X); 921 cmd.Parameters.AddWithValue("underwater_fog_modifier", wl.underwaterFogModifier);
924 cmd.Parameters.AddWithValue("water_color_g", wl.waterColor.Y); 922 cmd.Parameters.AddWithValue("reflection_wavelet_scale_1", wl.reflectionWaveletScale.X);
925 cmd.Parameters.AddWithValue("water_color_b", wl.waterColor.Z); 923 cmd.Parameters.AddWithValue("reflection_wavelet_scale_2", wl.reflectionWaveletScale.Y);
926 cmd.Parameters.AddWithValue("water_fog_density_exponent", wl.waterFogDensityExponent); 924 cmd.Parameters.AddWithValue("reflection_wavelet_scale_3", wl.reflectionWaveletScale.Z);
927 cmd.Parameters.AddWithValue("underwater_fog_modifier", wl.underwaterFogModifier); 925 cmd.Parameters.AddWithValue("fresnel_scale", wl.fresnelScale);
928 cmd.Parameters.AddWithValue("reflection_wavelet_scale_1", wl.reflectionWaveletScale.X); 926 cmd.Parameters.AddWithValue("fresnel_offset", wl.fresnelOffset);
929 cmd.Parameters.AddWithValue("reflection_wavelet_scale_2", wl.reflectionWaveletScale.Y); 927 cmd.Parameters.AddWithValue("refract_scale_above", wl.refractScaleAbove);
930 cmd.Parameters.AddWithValue("reflection_wavelet_scale_3", wl.reflectionWaveletScale.Z); 928 cmd.Parameters.AddWithValue("refract_scale_below", wl.refractScaleBelow);
931 cmd.Parameters.AddWithValue("fresnel_scale", wl.fresnelScale); 929 cmd.Parameters.AddWithValue("blur_multiplier", wl.blurMultiplier);
932 cmd.Parameters.AddWithValue("fresnel_offset", wl.fresnelOffset); 930 cmd.Parameters.AddWithValue("big_wave_direction_x", wl.bigWaveDirection.X);
933 cmd.Parameters.AddWithValue("refract_scale_above", wl.refractScaleAbove); 931 cmd.Parameters.AddWithValue("big_wave_direction_y", wl.bigWaveDirection.Y);
934 cmd.Parameters.AddWithValue("refract_scale_below", wl.refractScaleBelow); 932 cmd.Parameters.AddWithValue("little_wave_direction_x", wl.littleWaveDirection.X);
935 cmd.Parameters.AddWithValue("blur_multiplier", wl.blurMultiplier); 933 cmd.Parameters.AddWithValue("little_wave_direction_y", wl.littleWaveDirection.Y);
936 cmd.Parameters.AddWithValue("big_wave_direction_x", wl.bigWaveDirection.X); 934 cmd.Parameters.AddWithValue("normal_map_texture", wl.normalMapTexture);
937 cmd.Parameters.AddWithValue("big_wave_direction_y", wl.bigWaveDirection.Y); 935 cmd.Parameters.AddWithValue("horizon_r", wl.horizon.X);
938 cmd.Parameters.AddWithValue("little_wave_direction_x", wl.littleWaveDirection.X); 936 cmd.Parameters.AddWithValue("horizon_g", wl.horizon.Y);
939 cmd.Parameters.AddWithValue("little_wave_direction_y", wl.littleWaveDirection.Y); 937 cmd.Parameters.AddWithValue("horizon_b", wl.horizon.Z);
940 cmd.Parameters.AddWithValue("normal_map_texture", wl.normalMapTexture); 938 cmd.Parameters.AddWithValue("horizon_i", wl.horizon.W);
941 cmd.Parameters.AddWithValue("horizon_r", wl.horizon.X); 939 cmd.Parameters.AddWithValue("haze_horizon", wl.hazeHorizon);
942 cmd.Parameters.AddWithValue("horizon_g", wl.horizon.Y); 940 cmd.Parameters.AddWithValue("blue_density_r", wl.blueDensity.X);
943 cmd.Parameters.AddWithValue("horizon_b", wl.horizon.Z); 941 cmd.Parameters.AddWithValue("blue_density_g", wl.blueDensity.Y);
944 cmd.Parameters.AddWithValue("horizon_i", wl.horizon.W); 942 cmd.Parameters.AddWithValue("blue_density_b", wl.blueDensity.Z);
945 cmd.Parameters.AddWithValue("haze_horizon", wl.hazeHorizon); 943 cmd.Parameters.AddWithValue("blue_density_i", wl.blueDensity.W);
946 cmd.Parameters.AddWithValue("blue_density_r", wl.blueDensity.X); 944 cmd.Parameters.AddWithValue("haze_density", wl.hazeDensity);
947 cmd.Parameters.AddWithValue("blue_density_g", wl.blueDensity.Y); 945 cmd.Parameters.AddWithValue("density_multiplier", wl.densityMultiplier);
948 cmd.Parameters.AddWithValue("blue_density_b", wl.blueDensity.Z); 946 cmd.Parameters.AddWithValue("distance_multiplier", wl.distanceMultiplier);
949 cmd.Parameters.AddWithValue("blue_density_i", wl.blueDensity.W); 947 cmd.Parameters.AddWithValue("max_altitude", wl.maxAltitude);
950 cmd.Parameters.AddWithValue("haze_density", wl.hazeDensity); 948 cmd.Parameters.AddWithValue("sun_moon_color_r", wl.sunMoonColor.X);
951 cmd.Parameters.AddWithValue("density_multiplier", wl.densityMultiplier); 949 cmd.Parameters.AddWithValue("sun_moon_color_g", wl.sunMoonColor.Y);
952 cmd.Parameters.AddWithValue("distance_multiplier", wl.distanceMultiplier); 950 cmd.Parameters.AddWithValue("sun_moon_color_b", wl.sunMoonColor.Z);
953 cmd.Parameters.AddWithValue("max_altitude", wl.maxAltitude); 951 cmd.Parameters.AddWithValue("sun_moon_color_i", wl.sunMoonColor.W);
954 cmd.Parameters.AddWithValue("sun_moon_color_r", wl.sunMoonColor.X); 952 cmd.Parameters.AddWithValue("sun_moon_position", wl.sunMoonPosition);
955 cmd.Parameters.AddWithValue("sun_moon_color_g", wl.sunMoonColor.Y); 953 cmd.Parameters.AddWithValue("ambient_r", wl.ambient.X);
956 cmd.Parameters.AddWithValue("sun_moon_color_b", wl.sunMoonColor.Z); 954 cmd.Parameters.AddWithValue("ambient_g", wl.ambient.Y);
957 cmd.Parameters.AddWithValue("sun_moon_color_i", wl.sunMoonColor.W); 955 cmd.Parameters.AddWithValue("ambient_b", wl.ambient.Z);
958 cmd.Parameters.AddWithValue("sun_moon_position", wl.sunMoonPosition); 956 cmd.Parameters.AddWithValue("ambient_i", wl.ambient.W);
959 cmd.Parameters.AddWithValue("ambient_r", wl.ambient.X); 957 cmd.Parameters.AddWithValue("east_angle", wl.eastAngle);
960 cmd.Parameters.AddWithValue("ambient_g", wl.ambient.Y); 958 cmd.Parameters.AddWithValue("sun_glow_focus", wl.sunGlowFocus);
961 cmd.Parameters.AddWithValue("ambient_b", wl.ambient.Z); 959 cmd.Parameters.AddWithValue("sun_glow_size", wl.sunGlowSize);
962 cmd.Parameters.AddWithValue("ambient_i", wl.ambient.W); 960 cmd.Parameters.AddWithValue("scene_gamma", wl.sceneGamma);
963 cmd.Parameters.AddWithValue("east_angle", wl.eastAngle); 961 cmd.Parameters.AddWithValue("star_brightness", wl.starBrightness);
964 cmd.Parameters.AddWithValue("sun_glow_focus", wl.sunGlowFocus); 962 cmd.Parameters.AddWithValue("cloud_color_r", wl.cloudColor.X);
965 cmd.Parameters.AddWithValue("sun_glow_size", wl.sunGlowSize); 963 cmd.Parameters.AddWithValue("cloud_color_g", wl.cloudColor.Y);
966 cmd.Parameters.AddWithValue("scene_gamma", wl.sceneGamma); 964 cmd.Parameters.AddWithValue("cloud_color_b", wl.cloudColor.Z);
967 cmd.Parameters.AddWithValue("star_brightness", wl.starBrightness); 965 cmd.Parameters.AddWithValue("cloud_color_i", wl.cloudColor.W);
968 cmd.Parameters.AddWithValue("cloud_color_r", wl.cloudColor.X); 966 cmd.Parameters.AddWithValue("cloud_x", wl.cloudXYDensity.X);
969 cmd.Parameters.AddWithValue("cloud_color_g", wl.cloudColor.Y); 967 cmd.Parameters.AddWithValue("cloud_y", wl.cloudXYDensity.Y);
970 cmd.Parameters.AddWithValue("cloud_color_b", wl.cloudColor.Z); 968 cmd.Parameters.AddWithValue("cloud_density", wl.cloudXYDensity.Z);
971 cmd.Parameters.AddWithValue("cloud_color_i", wl.cloudColor.W); 969 cmd.Parameters.AddWithValue("cloud_coverage", wl.cloudCoverage);
972 cmd.Parameters.AddWithValue("cloud_x", wl.cloudXYDensity.X); 970 cmd.Parameters.AddWithValue("cloud_scale", wl.cloudScale);
973 cmd.Parameters.AddWithValue("cloud_y", wl.cloudXYDensity.Y); 971 cmd.Parameters.AddWithValue("cloud_detail_x", wl.cloudDetailXYDensity.X);
974 cmd.Parameters.AddWithValue("cloud_density", wl.cloudXYDensity.Z); 972 cmd.Parameters.AddWithValue("cloud_detail_y", wl.cloudDetailXYDensity.Y);
975 cmd.Parameters.AddWithValue("cloud_coverage", wl.cloudCoverage); 973 cmd.Parameters.AddWithValue("cloud_detail_density", wl.cloudDetailXYDensity.Z);
976 cmd.Parameters.AddWithValue("cloud_scale", wl.cloudScale); 974 cmd.Parameters.AddWithValue("cloud_scroll_x", wl.cloudScrollX);
977 cmd.Parameters.AddWithValue("cloud_detail_x", wl.cloudDetailXYDensity.X); 975 cmd.Parameters.AddWithValue("cloud_scroll_x_lock", wl.cloudScrollXLock);
978 cmd.Parameters.AddWithValue("cloud_detail_y", wl.cloudDetailXYDensity.Y); 976 cmd.Parameters.AddWithValue("cloud_scroll_y", wl.cloudScrollY);
979 cmd.Parameters.AddWithValue("cloud_detail_density", wl.cloudDetailXYDensity.Z); 977 cmd.Parameters.AddWithValue("cloud_scroll_y_lock", wl.cloudScrollYLock);
980 cmd.Parameters.AddWithValue("cloud_scroll_x", wl.cloudScrollX); 978 cmd.Parameters.AddWithValue("draw_classic_clouds", wl.drawClassicClouds);
981 cmd.Parameters.AddWithValue("cloud_scroll_x_lock", wl.cloudScrollXLock); 979
982 cmd.Parameters.AddWithValue("cloud_scroll_y", wl.cloudScrollY); 980 ExecuteNonQuery(cmd);
983 cmd.Parameters.AddWithValue("cloud_scroll_y_lock", wl.cloudScrollYLock);
984 cmd.Parameters.AddWithValue("draw_classic_clouds", wl.drawClassicClouds);
985
986 ExecuteNonQuery(cmd);
987 }
988 } 981 }
989 } 982 }
990 } 983 }
991 984
992 public virtual void RemoveRegionWindlightSettings(UUID regionID) 985 public virtual void RemoveRegionWindlightSettings(UUID regionID)
993 { 986 {
994 lock (m_dbLock) 987 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
995 { 988 {
996 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) 989 dbcon.Open();
990
991 using (MySqlCommand cmd = dbcon.CreateCommand())
997 { 992 {
998 dbcon.Open(); 993 cmd.CommandText = "delete from `regionwindlight` where `region_id`=?regionID";
999 994 cmd.Parameters.AddWithValue("?regionID", regionID.ToString());
1000 using (MySqlCommand cmd = dbcon.CreateCommand()) 995 ExecuteNonQuery(cmd);
1001 {
1002 cmd.CommandText = "delete from `regionwindlight` where `region_id`=?regionID";
1003 cmd.Parameters.AddWithValue("?regionID", regionID.ToString());
1004 ExecuteNonQuery(cmd);
1005 }
1006 } 996 }
1007 } 997 }
1008 } 998 }
@@ -1010,29 +1000,26 @@ namespace OpenSim.Data.MySQL
1010 #region RegionEnvironmentSettings 1000 #region RegionEnvironmentSettings
1011 public string LoadRegionEnvironmentSettings(UUID regionUUID) 1001 public string LoadRegionEnvironmentSettings(UUID regionUUID)
1012 { 1002 {
1013 lock (m_dbLock) 1003 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
1014 { 1004 {
1015 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) 1005 dbcon.Open();
1006
1007 string command = "select * from `regionenvironment` where region_id = ?region_id";
1008
1009 using (MySqlCommand cmd = new MySqlCommand(command))
1016 { 1010 {
1017 dbcon.Open(); 1011 cmd.Connection = dbcon;
1018 1012
1019 string command = "select * from `regionenvironment` where region_id = ?region_id"; 1013 cmd.Parameters.AddWithValue("?region_id", regionUUID.ToString());
1020 1014
1021 using (MySqlCommand cmd = new MySqlCommand(command)) 1015 IDataReader result = ExecuteReader(cmd);
1016 if (!result.Read())
1022 { 1017 {
1023 cmd.Connection = dbcon; 1018 return String.Empty;
1024 1019 }
1025 cmd.Parameters.AddWithValue("?region_id", regionUUID.ToString()); 1020 else
1026 1021 {
1027 IDataReader result = ExecuteReader(cmd); 1022 return Convert.ToString(result["llsd_settings"]);
1028 if (!result.Read())
1029 {
1030 return String.Empty;
1031 }
1032 else
1033 {
1034 return Convert.ToString(result["llsd_settings"]);
1035 }
1036 } 1023 }
1037 } 1024 }
1038 } 1025 }
@@ -1040,39 +1027,33 @@ namespace OpenSim.Data.MySQL
1040 1027
1041 public void StoreRegionEnvironmentSettings(UUID regionUUID, string settings) 1028 public void StoreRegionEnvironmentSettings(UUID regionUUID, string settings)
1042 { 1029 {
1043 lock (m_dbLock) 1030 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
1044 { 1031 {
1045 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) 1032 dbcon.Open();
1033
1034 using (MySqlCommand cmd = dbcon.CreateCommand())
1046 { 1035 {
1047 dbcon.Open(); 1036 cmd.CommandText = "REPLACE INTO `regionenvironment` (`region_id`, `llsd_settings`) VALUES (?region_id, ?llsd_settings)";
1048 1037
1049 using (MySqlCommand cmd = dbcon.CreateCommand()) 1038 cmd.Parameters.AddWithValue("region_id", regionUUID);
1050 { 1039 cmd.Parameters.AddWithValue("llsd_settings", settings);
1051 cmd.CommandText = "REPLACE INTO `regionenvironment` (`region_id`, `llsd_settings`) VALUES (?region_id, ?llsd_settings)"; 1040
1052 1041 ExecuteNonQuery(cmd);
1053 cmd.Parameters.AddWithValue("region_id", regionUUID);
1054 cmd.Parameters.AddWithValue("llsd_settings", settings);
1055
1056 ExecuteNonQuery(cmd);
1057 }
1058 } 1042 }
1059 } 1043 }
1060 } 1044 }
1061 1045
1062 public void RemoveRegionEnvironmentSettings(UUID regionUUID) 1046 public void RemoveRegionEnvironmentSettings(UUID regionUUID)
1063 { 1047 {
1064 lock (m_dbLock) 1048 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
1065 { 1049 {
1066 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) 1050 dbcon.Open();
1051
1052 using (MySqlCommand cmd = dbcon.CreateCommand())
1067 { 1053 {
1068 dbcon.Open(); 1054 cmd.CommandText = "delete from `regionenvironment` where region_id = ?region_id";
1069 1055 cmd.Parameters.AddWithValue("?region_id", regionUUID.ToString());
1070 using (MySqlCommand cmd = dbcon.CreateCommand()) 1056 ExecuteNonQuery(cmd);
1071 {
1072 cmd.CommandText = "delete from `regionenvironment` where region_id = ?region_id";
1073 cmd.Parameters.AddWithValue("?region_id", regionUUID.ToString());
1074 ExecuteNonQuery(cmd);
1075 }
1076 } 1057 }
1077 } 1058 }
1078 } 1059 }
diff --git a/OpenSim/Data/MySQL/Resources/GridUserStore.migrations b/OpenSim/Data/MySQL/Resources/GridUserStore.migrations
index d08e096..32b85ee 100644
--- a/OpenSim/Data/MySQL/Resources/GridUserStore.migrations
+++ b/OpenSim/Data/MySQL/Resources/GridUserStore.migrations
@@ -17,8 +17,3 @@ CREATE TABLE `GridUser` (
17) ENGINE=InnoDB; 17) ENGINE=InnoDB;
18 18
19COMMIT; 19COMMIT;
20
21:VERSION 2 # --------------------------
22BEGIN;
23
24COMMIT;
diff --git a/OpenSim/Data/Null/NullRegionData.cs b/OpenSim/Data/Null/NullRegionData.cs
index b4d701a..deb50cb 100644
--- a/OpenSim/Data/Null/NullRegionData.cs
+++ b/OpenSim/Data/Null/NullRegionData.cs
@@ -33,7 +33,6 @@ using OpenSim.Framework;
33using OpenSim.Data; 33using OpenSim.Data;
34using System.Reflection; 34using System.Reflection;
35using log4net; 35using log4net;
36using RegionFlags = OpenSim.Framework.RegionFlags;
37 36
38namespace OpenSim.Data.Null 37namespace OpenSim.Data.Null
39{ 38{
diff --git a/OpenSim/Data/SQLite/SQLiteSimulationData.cs b/OpenSim/Data/SQLite/SQLiteSimulationData.cs
index 42cd59d..431709f 100644
--- a/OpenSim/Data/SQLite/SQLiteSimulationData.cs
+++ b/OpenSim/Data/SQLite/SQLiteSimulationData.cs
@@ -1366,13 +1366,6 @@ namespace OpenSim.Data.SQLite
1366 createCol(land, "UserLookAtZ", typeof(Double)); 1366 createCol(land, "UserLookAtZ", typeof(Double));
1367 createCol(land, "AuthbuyerID", typeof(String)); 1367 createCol(land, "AuthbuyerID", typeof(String));
1368 createCol(land, "OtherCleanTime", typeof(Int32)); 1368 createCol(land, "OtherCleanTime", typeof(Int32));
1369 createCol(land, "Dwell", typeof(Int32));
1370 createCol(land, "MediaType", typeof(String));
1371 createCol(land, "MediaDescription", typeof(String));
1372 createCol(land, "MediaSize", typeof(String));
1373 createCol(land, "MediaLoop", typeof(Boolean));
1374 createCol(land, "ObscureMedia", typeof(Boolean));
1375 createCol(land, "ObscureMusic", typeof(Boolean));
1376 1369
1377 land.PrimaryKey = new DataColumn[] { land.Columns["UUID"] }; 1370 land.PrimaryKey = new DataColumn[] { land.Columns["UUID"] };
1378 1371
@@ -1788,16 +1781,9 @@ namespace OpenSim.Data.SQLite
1788 newData.PassHours = Convert.ToSingle(row["PassHours"]); 1781 newData.PassHours = Convert.ToSingle(row["PassHours"]);
1789 newData.PassPrice = Convert.ToInt32(row["PassPrice"]); 1782 newData.PassPrice = Convert.ToInt32(row["PassPrice"]);
1790 newData.SnapshotID = (UUID)(String)row["SnapshotUUID"]; 1783 newData.SnapshotID = (UUID)(String)row["SnapshotUUID"];
1791 newData.Dwell = Convert.ToInt32(row["Dwell"]);
1792 newData.MediaType = (String)row["MediaType"];
1793 newData.MediaDescription = (String)row["MediaDescription"];
1794 newData.MediaWidth = Convert.ToInt32((((string)row["MediaSize"]).Split(','))[0]);
1795 newData.MediaHeight = Convert.ToInt32((((string)row["MediaSize"]).Split(','))[1]);
1796 newData.MediaLoop = Convert.ToBoolean(row["MediaLoop"]);
1797 newData.ObscureMedia = Convert.ToBoolean(row["ObscureMedia"]);
1798 newData.ObscureMusic = Convert.ToBoolean(row["ObscureMusic"]);
1799 try 1784 try
1800 { 1785 {
1786
1801 newData.UserLocation = 1787 newData.UserLocation =
1802 new Vector3(Convert.ToSingle(row["UserLocationX"]), Convert.ToSingle(row["UserLocationY"]), 1788 new Vector3(Convert.ToSingle(row["UserLocationX"]), Convert.ToSingle(row["UserLocationY"]),
1803 Convert.ToSingle(row["UserLocationZ"])); 1789 Convert.ToSingle(row["UserLocationZ"]));
@@ -2209,13 +2195,12 @@ namespace OpenSim.Data.SQLite
2209 row["UserLookAtZ"] = land.UserLookAt.Z; 2195 row["UserLookAtZ"] = land.UserLookAt.Z;
2210 row["AuthbuyerID"] = land.AuthBuyerID.ToString(); 2196 row["AuthbuyerID"] = land.AuthBuyerID.ToString();
2211 row["OtherCleanTime"] = land.OtherCleanTime; 2197 row["OtherCleanTime"] = land.OtherCleanTime;
2212 row["Dwell"] = land.Dwell;
2213 row["MediaType"] = land.MediaType; 2198 row["MediaType"] = land.MediaType;
2214 row["MediaDescription"] = land.MediaDescription; 2199 row["MediaDescription"] = land.MediaDescription;
2215 row["MediaSize"] = String.Format("{0},{1}", land.MediaWidth, land.MediaHeight); 2200 row["MediaSize"] = land.MediaWidth.ToString() + "," + land.MediaHeight.ToString();
2216 row["MediaLoop"] = land.MediaLoop; 2201 row["MediaLoop"] = land.MediaLoop.ToString();
2217 row["ObscureMusic"] = land.ObscureMusic; 2202 row["ObscureMusic"] = land.ObscureMusic.ToString();
2218 row["ObscureMedia"] = land.ObscureMedia; 2203 row["ObscureMedia"] = land.ObscureMedia.ToString();
2219 } 2204 }
2220 2205
2221 /// <summary> 2206 /// <summary>
diff --git a/OpenSim/Framework/AssetPermissions.cs b/OpenSim/Framework/AssetPermissions.cs
deleted file mode 100644
index 4a905c2..0000000
--- a/OpenSim/Framework/AssetPermissions.cs
+++ /dev/null
@@ -1,84 +0,0 @@
1using System;
2using System.Collections.Generic;
3using System.Reflection;
4
5using Nini.Config;
6using log4net;
7
8using OpenMetaverse;
9
10namespace OpenSim.Framework
11{
12 public class AssetPermissions
13 {
14 private static readonly ILog m_log =
15 LogManager.GetLogger(
16 MethodBase.GetCurrentMethod().DeclaringType);
17
18 private bool[] m_DisallowExport, m_DisallowImport;
19 private string[] m_AssetTypeNames;
20
21 public AssetPermissions(IConfig config)
22 {
23 Type enumType = typeof(AssetType);
24 m_AssetTypeNames = Enum.GetNames(enumType);
25 for (int i = 0; i < m_AssetTypeNames.Length; i++)
26 m_AssetTypeNames[i] = m_AssetTypeNames[i].ToLower();
27 int n = Enum.GetValues(enumType).Length;
28 m_DisallowExport = new bool[n];
29 m_DisallowImport = new bool[n];
30
31 LoadPermsFromConfig(config, "DisallowExport", m_DisallowExport);
32 LoadPermsFromConfig(config, "DisallowImport", m_DisallowImport);
33
34 }
35
36 private void LoadPermsFromConfig(IConfig assetConfig, string variable, bool[] bitArray)
37 {
38 if (assetConfig == null)
39 return;
40
41 string perms = assetConfig.GetString(variable, String.Empty);
42 string[] parts = perms.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
43 foreach (string s in parts)
44 {
45 int index = Array.IndexOf(m_AssetTypeNames, s.Trim().ToLower());
46 if (index >= 0)
47 bitArray[index] = true;
48 else
49 m_log.WarnFormat("[Asset Permissions]: Invalid AssetType {0}", s);
50 }
51
52 }
53
54 public bool AllowedExport(sbyte type)
55 {
56 string assetTypeName = ((AssetType)type).ToString();
57
58 int index = Array.IndexOf(m_AssetTypeNames, assetTypeName.ToLower());
59 if (index >= 0 && m_DisallowExport[index])
60 {
61 m_log.DebugFormat("[Asset Permissions]: Export denied: configuration does not allow export of AssetType {0}", assetTypeName);
62 return false;
63 }
64
65 return true;
66 }
67
68 public bool AllowedImport(sbyte type)
69 {
70 string assetTypeName = ((AssetType)type).ToString();
71
72 int index = Array.IndexOf(m_AssetTypeNames, assetTypeName.ToLower());
73 if (index >= 0 && m_DisallowImport[index])
74 {
75 m_log.DebugFormat("[Asset Permissions]: Import denied: configuration does not allow import of AssetType {0}", assetTypeName);
76 return false;
77 }
78
79 return true;
80 }
81
82
83 }
84}
diff --git a/OpenSim/Framework/AvatarAppearance.cs b/OpenSim/Framework/AvatarAppearance.cs
index 1638541..c5d9641 100644
--- a/OpenSim/Framework/AvatarAppearance.cs
+++ b/OpenSim/Framework/AvatarAppearance.cs
@@ -358,9 +358,6 @@ namespace OpenSim.Framework
358 SetVisualParams(visualParams); 358 SetVisualParams(visualParams);
359 } 359 }
360 360
361 /// <summary>
362 /// Set avatar height by a calculation based on their visual parameters.
363 /// </summary>
364 public virtual void SetHeight() 361 public virtual void SetHeight()
365 { 362 {
366 // Start with shortest possible female avatar height 363 // Start with shortest possible female avatar height
diff --git a/OpenSim/Framework/Cache.cs b/OpenSim/Framework/Cache.cs
index 31cab4a..79e20fc 100644
--- a/OpenSim/Framework/Cache.cs
+++ b/OpenSim/Framework/Cache.cs
@@ -199,14 +199,7 @@ namespace OpenSim.Framework
199 // 199 //
200 public class Cache 200 public class Cache
201 { 201 {
202 /// <summary>
203 /// Must only be accessed under lock.
204 /// </summary>
205 private List<CacheItemBase> m_Index = new List<CacheItemBase>(); 202 private List<CacheItemBase> m_Index = new List<CacheItemBase>();
206
207 /// <summary>
208 /// Must only be accessed under m_Index lock.
209 /// </summary>
210 private Dictionary<string, CacheItemBase> m_Lookup = 203 private Dictionary<string, CacheItemBase> m_Lookup =
211 new Dictionary<string, CacheItemBase>(); 204 new Dictionary<string, CacheItemBase>();
212 205
@@ -327,19 +320,19 @@ namespace OpenSim.Framework
327 { 320 {
328 if (m_Lookup.ContainsKey(index)) 321 if (m_Lookup.ContainsKey(index))
329 item = m_Lookup[index]; 322 item = m_Lookup[index];
323 }
330 324
331 if (item == null) 325 if (item == null)
332 { 326 {
333 Expire(true);
334 return null;
335 }
336
337 item.hits++;
338 item.lastUsed = DateTime.Now;
339
340 Expire(true); 327 Expire(true);
328 return null;
341 } 329 }
342 330
331 item.hits++;
332 item.lastUsed = DateTime.Now;
333
334 Expire(true);
335
343 return item; 336 return item;
344 } 337 }
345 338
@@ -392,10 +385,7 @@ namespace OpenSim.Framework
392 // 385 //
393 public Object Find(Predicate<CacheItemBase> d) 386 public Object Find(Predicate<CacheItemBase> d)
394 { 387 {
395 CacheItemBase item; 388 CacheItemBase item = m_Index.Find(d);
396
397 lock (m_Index)
398 item = m_Index.Find(d);
399 389
400 if (item == null) 390 if (item == null)
401 return null; 391 return null;
@@ -429,12 +419,12 @@ namespace OpenSim.Framework
429 public virtual void Store(string index, Object data, Type container, 419 public virtual void Store(string index, Object data, Type container,
430 Object[] parameters) 420 Object[] parameters)
431 { 421 {
422 Expire(false);
423
432 CacheItemBase item; 424 CacheItemBase item;
433 425
434 lock (m_Index) 426 lock (m_Index)
435 { 427 {
436 Expire(false);
437
438 if (m_Index.Contains(new CacheItemBase(index))) 428 if (m_Index.Contains(new CacheItemBase(index)))
439 { 429 {
440 if ((m_Flags & CacheFlags.AllowUpdate) != 0) 430 if ((m_Flags & CacheFlags.AllowUpdate) != 0)
@@ -460,17 +450,9 @@ namespace OpenSim.Framework
460 m_Index.Add(item); 450 m_Index.Add(item);
461 m_Lookup[index] = item; 451 m_Lookup[index] = item;
462 } 452 }
463
464 item.Store(data); 453 item.Store(data);
465 } 454 }
466 455
467 /// <summary>
468 /// Expire items as appropriate.
469 /// </summary>
470 /// <remarks>
471 /// Callers must lock m_Index.
472 /// </remarks>
473 /// <param name='getting'></param>
474 protected virtual void Expire(bool getting) 456 protected virtual void Expire(bool getting)
475 { 457 {
476 if (getting && (m_Strategy == CacheStrategy.Aggressive)) 458 if (getting && (m_Strategy == CacheStrategy.Aggressive))
@@ -493,10 +475,12 @@ namespace OpenSim.Framework
493 475
494 switch (m_Strategy) 476 switch (m_Strategy)
495 { 477 {
496 case CacheStrategy.Aggressive: 478 case CacheStrategy.Aggressive:
497 if (Count < Size) 479 if (Count < Size)
498 return; 480 return;
499 481
482 lock (m_Index)
483 {
500 m_Index.Sort(new SortLRU()); 484 m_Index.Sort(new SortLRU());
501 m_Index.Reverse(); 485 m_Index.Reverse();
502 486
@@ -506,7 +490,7 @@ namespace OpenSim.Framework
506 490
507 ExpireDelegate doExpire = OnExpire; 491 ExpireDelegate doExpire = OnExpire;
508 492
509 if (doExpire != null) 493 if (doExpire != null)
510 { 494 {
511 List<CacheItemBase> candidates = 495 List<CacheItemBase> candidates =
512 m_Index.GetRange(target, Count - target); 496 m_Index.GetRange(target, Count - target);
@@ -529,34 +513,27 @@ namespace OpenSim.Framework
529 foreach (CacheItemBase item in m_Index) 513 foreach (CacheItemBase item in m_Index)
530 m_Lookup[item.uuid] = item; 514 m_Lookup[item.uuid] = item;
531 } 515 }
532 516 }
533 break; 517 break;
534 518 default:
535 default: 519 break;
536 break;
537 } 520 }
538 } 521 }
539 522
540 public void Invalidate(string uuid) 523 public void Invalidate(string uuid)
541 { 524 {
542 lock (m_Index) 525 if (!m_Lookup.ContainsKey(uuid))
543 { 526 return;
544 if (!m_Lookup.ContainsKey(uuid))
545 return;
546 527
547 CacheItemBase item = m_Lookup[uuid]; 528 CacheItemBase item = m_Lookup[uuid];
548 m_Lookup.Remove(uuid); 529 m_Lookup.Remove(uuid);
549 m_Index.Remove(item); 530 m_Index.Remove(item);
550 }
551 } 531 }
552 532
553 public void Clear() 533 public void Clear()
554 { 534 {
555 lock (m_Index) 535 m_Index.Clear();
556 { 536 m_Lookup.Clear();
557 m_Index.Clear();
558 m_Lookup.Clear();
559 }
560 } 537 }
561 } 538 }
562} \ No newline at end of file 539}
diff --git a/OpenSim/Framework/Client/IClientChat.cs b/OpenSim/Framework/Client/IClientChat.cs
index 86b1faa..078ea9b 100644
--- a/OpenSim/Framework/Client/IClientChat.cs
+++ b/OpenSim/Framework/Client/IClientChat.cs
@@ -33,8 +33,7 @@ namespace OpenSim.Framework.Client
33 { 33 {
34 event ChatMessage OnChatFromClient; 34 event ChatMessage OnChatFromClient;
35 35
36 void SendChatMessage( 36 void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, byte source,
37 string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, UUID ownerID, byte source, 37 byte audible);
38 byte audible);
39 } 38 }
40} \ No newline at end of file 39}
diff --git a/OpenSim/Framework/Console/ConsoleUtil.cs b/OpenSim/Framework/Console/ConsoleUtil.cs
deleted file mode 100644
index 16a63e0..0000000
--- a/OpenSim/Framework/Console/ConsoleUtil.cs
+++ /dev/null
@@ -1,228 +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.Linq;
32using System.Reflection;
33using log4net;
34using OpenMetaverse;
35
36namespace OpenSim.Framework.Console
37{
38 public class ConsoleUtil
39 {
40 // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
41
42 public const int LocalIdNotFound = 0;
43
44 /// <summary>
45 /// Used by modules to display stock co-ordinate help, though possibly this should be under some general section
46 /// rather than in each help summary.
47 /// </summary>
48 public const string CoordHelp
49 = @"Each component of the coord is comma separated. There must be no spaces between the commas.
50 If you don't care about the z component you can simply omit it.
51 If you don't care about the x or y components then you can leave them blank (though a comma is still required)
52 If you want to specify the maxmimum value of a component then you can use ~ instead of a number
53 If you want to specify the minimum value of a component then you can use -~ instead of a number
54 e.g.
55 delete object pos 20,20,20 to 40,40,40
56 delete object pos 20,20 to 40,40
57 delete object pos ,20,20 to ,40,40
58 delete object pos ,,30 to ,,~
59 delete object pos ,,-~ to ,,30";
60
61 public const string MinRawConsoleVectorValue = "-~";
62 public const string MaxRawConsoleVectorValue = "~";
63
64 public const string VectorSeparator = ",";
65 public static char[] VectorSeparatorChars = VectorSeparator.ToCharArray();
66
67 /// <summary>
68 /// Check if the given file path exists.
69 /// </summary>
70 /// <remarks>If not, warning is printed to the given console.</remarks>
71 /// <returns>true if the file does not exist, false otherwise.</returns>
72 /// <param name='console'></param>
73 /// <param name='path'></param>
74 public static bool CheckFileDoesNotExist(ICommandConsole console, string path)
75 {
76 if (File.Exists(path))
77 {
78 console.OutputFormat("File {0} already exists. Please move or remove it.", path);
79 return false;
80 }
81
82 return true;
83 }
84
85 /// <summary>
86 /// Try to parse a console UUID from the console.
87 /// </summary>
88 /// <remarks>
89 /// Will complain to the console if parsing fails.
90 /// </remarks>
91 /// <returns></returns>
92 /// <param name='console'>If null then no complaint is printed.</param>
93 /// <param name='rawUuid'></param>
94 /// <param name='uuid'></param>
95 public static bool TryParseConsoleUuid(ICommandConsole console, string rawUuid, out UUID uuid)
96 {
97 if (!UUID.TryParse(rawUuid, out uuid))
98 {
99 if (console != null)
100 console.OutputFormat("{0} is not a valid uuid", rawUuid);
101
102 return false;
103 }
104
105 return true;
106 }
107
108 public static bool TryParseConsoleLocalId(ICommandConsole console, string rawLocalId, out uint localId)
109 {
110 if (!uint.TryParse(rawLocalId, out localId))
111 {
112 if (console != null)
113 console.OutputFormat("{0} is not a valid local id", localId);
114
115 return false;
116 }
117
118 if (localId == 0)
119 {
120 if (console != null)
121 console.OutputFormat("{0} is not a valid local id - it must be greater than 0", localId);
122
123 return false;
124 }
125
126 return true;
127 }
128
129 /// <summary>
130 /// Tries to parse the input as either a UUID or a local ID.
131 /// </summary>
132 /// <returns>true if parsing succeeded, false otherwise.</returns>
133 /// <param name='console'></param>
134 /// <param name='rawId'></param>
135 /// <param name='uuid'></param>
136 /// <param name='localId'>
137 /// Will be set to ConsoleUtil.LocalIdNotFound if parsing result was a UUID or no parse succeeded.
138 /// </param>
139 public static bool TryParseConsoleId(ICommandConsole console, string rawId, out UUID uuid, out uint localId)
140 {
141 if (TryParseConsoleUuid(null, rawId, out uuid))
142 {
143 localId = LocalIdNotFound;
144 return true;
145 }
146
147 if (TryParseConsoleLocalId(null, rawId, out localId))
148 {
149 return true;
150 }
151
152 if (console != null)
153 console.OutputFormat("{0} is not a valid UUID or local id", rawId);
154
155 return false;
156 }
157
158 /// <summary>
159 /// Convert a minimum vector input from the console to an OpenMetaverse.Vector3
160 /// </summary>
161 /// <param name='rawConsoleVector'>/param>
162 /// <param name='vector'></param>
163 /// <returns></returns>
164 public static bool TryParseConsoleMinVector(string rawConsoleVector, out Vector3 vector)
165 {
166 return TryParseConsoleVector(rawConsoleVector, c => float.MinValue.ToString(), out vector);
167 }
168
169 /// <summary>
170 /// Convert a maximum vector input from the console to an OpenMetaverse.Vector3
171 /// </summary>
172 /// <param name='rawConsoleVector'>/param>
173 /// <param name='vector'></param>
174 /// <returns></returns>
175 public static bool TryParseConsoleMaxVector(string rawConsoleVector, out Vector3 vector)
176 {
177 return TryParseConsoleVector(rawConsoleVector, c => float.MaxValue.ToString(), out vector);
178 }
179
180 /// <summary>
181 /// Convert a vector input from the console to an OpenMetaverse.Vector3
182 /// </summary>
183 /// <param name='rawConsoleVector'>
184 /// A string in the form <x>,<y>,<z> where there is no space between values.
185 /// Any component can be missing (e.g. ,,40). blankComponentFunc is invoked to replace the blank with a suitable value
186 /// Also, if the blank component is at the end, then the comma can be missed off entirely (e.g. 40,30 or 40)
187 /// The strings "~" and "-~" are valid in components. The first substitutes float.MaxValue whilst the second is float.MinValue
188 /// Other than that, component values must be numeric.
189 /// </param>
190 /// <param name='blankComponentFunc'></param>
191 /// <param name='vector'></param>
192 /// <returns></returns>
193 public static bool TryParseConsoleVector(
194 string rawConsoleVector, Func<string, string> blankComponentFunc, out Vector3 vector)
195 {
196 List<string> components = rawConsoleVector.Split(VectorSeparatorChars).ToList();
197
198 if (components.Count < 1 || components.Count > 3)
199 {
200 vector = Vector3.Zero;
201 return false;
202 }
203
204 for (int i = components.Count; i < 3; i++)
205 components.Add("");
206
207 List<string> semiDigestedComponents
208 = components.ConvertAll<string>(
209 c =>
210 {
211 if (c == "")
212 return blankComponentFunc.Invoke(c);
213 else if (c == MaxRawConsoleVectorValue)
214 return float.MaxValue.ToString();
215 else if (c == MinRawConsoleVectorValue)
216 return float.MinValue.ToString();
217 else
218 return c;
219 });
220
221 string semiDigestedConsoleVector = string.Join(VectorSeparator, semiDigestedComponents.ToArray());
222
223 // m_log.DebugFormat("[CONSOLE UTIL]: Parsing {0} into OpenMetaverse.Vector3", semiDigestedConsoleVector);
224
225 return Vector3.TryParse(semiDigestedConsoleVector, out vector);
226 }
227 }
228} \ No newline at end of file
diff --git a/OpenSim/Framework/Constants.cs b/OpenSim/Framework/Constants.cs
index a2eb5ee..1b1aaf2 100644
--- a/OpenSim/Framework/Constants.cs
+++ b/OpenSim/Framework/Constants.cs
@@ -31,7 +31,6 @@ namespace OpenSim.Framework
31 public class Constants 31 public class Constants
32 { 32 {
33 public const uint RegionSize = 256; 33 public const uint RegionSize = 256;
34 public const uint RegionHeight = 4096;
35 public const byte TerrainPatchSize = 16; 34 public const byte TerrainPatchSize = 16;
36 public const string DefaultTexture = "89556747-24cb-43ed-920b-47caed15465f"; 35 public const string DefaultTexture = "89556747-24cb-43ed-920b-47caed15465f";
37 36
diff --git a/OpenSim/Framework/EstateSettings.cs b/OpenSim/Framework/EstateSettings.cs
index e03750b..9020761 100644
--- a/OpenSim/Framework/EstateSettings.cs
+++ b/OpenSim/Framework/EstateSettings.cs
@@ -419,11 +419,11 @@ namespace OpenSim.Framework
419 419
420 public void SetFromFlags(ulong regionFlags) 420 public void SetFromFlags(ulong regionFlags)
421 { 421 {
422 ResetHomeOnTeleport = ((regionFlags & (ulong)OpenMetaverse.RegionFlags.ResetHomeOnTeleport) == (ulong)OpenMetaverse.RegionFlags.ResetHomeOnTeleport); 422 ResetHomeOnTeleport = ((regionFlags & (ulong)RegionFlags.ResetHomeOnTeleport) == (ulong)RegionFlags.ResetHomeOnTeleport);
423 BlockDwell = ((regionFlags & (ulong)OpenMetaverse.RegionFlags.BlockDwell) == (ulong)OpenMetaverse.RegionFlags.BlockDwell); 423 BlockDwell = ((regionFlags & (ulong)RegionFlags.BlockDwell) == (ulong)RegionFlags.BlockDwell);
424 AllowLandmark = ((regionFlags & (ulong)OpenMetaverse.RegionFlags.AllowLandmark) == (ulong)OpenMetaverse.RegionFlags.AllowLandmark); 424 AllowLandmark = ((regionFlags & (ulong)RegionFlags.AllowLandmark) == (ulong)RegionFlags.AllowLandmark);
425 AllowParcelChanges = ((regionFlags & (ulong)OpenMetaverse.RegionFlags.AllowParcelChanges) == (ulong)OpenMetaverse.RegionFlags.AllowParcelChanges); 425 AllowParcelChanges = ((regionFlags & (ulong)RegionFlags.AllowParcelChanges) == (ulong)RegionFlags.AllowParcelChanges);
426 AllowSetHome = ((regionFlags & (ulong)OpenMetaverse.RegionFlags.AllowSetHome) == (ulong)OpenMetaverse.RegionFlags.AllowSetHome); 426 AllowSetHome = ((regionFlags & (ulong)RegionFlags.AllowSetHome) == (ulong)RegionFlags.AllowSetHome);
427 } 427 }
428 428
429 public bool GroupAccess(UUID groupID) 429 public bool GroupAccess(UUID groupID)
diff --git a/OpenSim/Framework/GridInstantMessage.cs b/OpenSim/Framework/GridInstantMessage.cs
index 6ae0488..a6bf6e3 100644
--- a/OpenSim/Framework/GridInstantMessage.cs
+++ b/OpenSim/Framework/GridInstantMessage.cs
@@ -44,6 +44,7 @@ namespace OpenSim.Framework
44 public Vector3 Position; 44 public Vector3 Position;
45 public byte[] binaryBucket; 45 public byte[] binaryBucket;
46 46
47
47 public uint ParentEstateID; 48 public uint ParentEstateID;
48 public Guid RegionID; 49 public Guid RegionID;
49 public uint timestamp; 50 public uint timestamp;
@@ -57,7 +58,7 @@ namespace OpenSim.Framework
57 string _fromAgentName, UUID _toAgentID, 58 string _fromAgentName, UUID _toAgentID,
58 byte _dialog, bool _fromGroup, string _message, 59 byte _dialog, bool _fromGroup, string _message,
59 UUID _imSessionID, bool _offline, Vector3 _position, 60 UUID _imSessionID, bool _offline, Vector3 _position,
60 byte[] _binaryBucket, bool addTimestamp) 61 byte[] _binaryBucket)
61 { 62 {
62 fromAgentID = _fromAgentID.Guid; 63 fromAgentID = _fromAgentID.Guid;
63 fromAgentName = _fromAgentName; 64 fromAgentName = _fromAgentName;
@@ -78,9 +79,7 @@ namespace OpenSim.Framework
78 ParentEstateID = scene.RegionInfo.EstateSettings.ParentEstateID; 79 ParentEstateID = scene.RegionInfo.EstateSettings.ParentEstateID;
79 RegionID = scene.RegionInfo.RegionSettings.RegionUUID.Guid; 80 RegionID = scene.RegionInfo.RegionSettings.RegionUUID.Guid;
80 } 81 }
81 82 timestamp = (uint)Util.UnixTimeSinceEpoch();
82 if (addTimestamp)
83 timestamp = (uint)Util.UnixTimeSinceEpoch();
84 } 83 }
85 84
86 public GridInstantMessage(IScene scene, UUID _fromAgentID, 85 public GridInstantMessage(IScene scene, UUID _fromAgentID,
@@ -88,7 +87,7 @@ namespace OpenSim.Framework
88 string _message, bool _offline, 87 string _message, bool _offline,
89 Vector3 _position) : this(scene, _fromAgentID, _fromAgentName, 88 Vector3 _position) : this(scene, _fromAgentID, _fromAgentName,
90 _toAgentID, _dialog, false, _message, 89 _toAgentID, _dialog, false, _message,
91 _fromAgentID ^ _toAgentID, _offline, _position, new byte[0], true) 90 _fromAgentID ^ _toAgentID, _offline, _position, new byte[0])
92 { 91 {
93 } 92 }
94 } 93 }
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs
index 1c6685a..e31c7f6 100644
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -815,23 +815,8 @@ namespace OpenSim.Framework
815 event Action<IClientAPI> OnRegionHandShakeReply; 815 event Action<IClientAPI> OnRegionHandShakeReply;
816 event GenericCall1 OnRequestWearables; 816 event GenericCall1 OnRequestWearables;
817 event Action<IClientAPI, bool> OnCompleteMovementToRegion; 817 event Action<IClientAPI, bool> OnCompleteMovementToRegion;
818
819 /// <summary>
820 /// Called when an AgentUpdate message is received and before OnAgentUpdate.
821 /// </summary>
822 /// <remarks>
823 /// Listeners must not retain a reference to AgentUpdateArgs since this object may be reused for subsequent AgentUpdates.
824 /// </remarks>
825 event UpdateAgent OnPreAgentUpdate; 818 event UpdateAgent OnPreAgentUpdate;
826
827 /// <summary>
828 /// Called when an AgentUpdate message is received and after OnPreAgentUpdate.
829 /// </summary>
830 /// <remarks>
831 /// Listeners must not retain a reference to AgentUpdateArgs since this object may be reused for subsequent AgentUpdates.
832 /// </remarks>
833 event UpdateAgent OnAgentUpdate; 819 event UpdateAgent OnAgentUpdate;
834
835 event AgentRequestSit OnAgentRequestSit; 820 event AgentRequestSit OnAgentRequestSit;
836 event AgentSit OnAgentSit; 821 event AgentSit OnAgentSit;
837 event AvatarPickerRequest OnAvatarPickerRequest; 822 event AvatarPickerRequest OnAvatarPickerRequest;
@@ -1061,21 +1046,8 @@ namespace OpenSim.Framework
1061 1046
1062 void InPacket(object NewPack); 1047 void InPacket(object NewPack);
1063 void ProcessInPacket(Packet NewPack); 1048 void ProcessInPacket(Packet NewPack);
1064
1065 /// <summary>
1066 /// Close this client
1067 /// </summary>
1068 void Close(); 1049 void Close();
1069 1050 void Close(bool sendStop);
1070 /// <summary>
1071 /// Close this client
1072 /// </summary>
1073 /// <param name='force'>
1074 /// If true, attempts the close without checking active status. You do not want to try this except as a last
1075 /// ditch attempt where Active == false but the ScenePresence still exists.
1076 /// </param>
1077 void Close(bool sendStop, bool force);
1078
1079 void Kick(string message); 1051 void Kick(string message);
1080 1052
1081 /// <summary> 1053 /// <summary>
@@ -1112,20 +1084,8 @@ namespace OpenSim.Framework
1112 void SendAnimations(UUID[] animID, int[] seqs, UUID sourceAgentId, UUID[] objectIDs); 1084 void SendAnimations(UUID[] animID, int[] seqs, UUID sourceAgentId, UUID[] objectIDs);
1113 void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args); 1085 void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args);
1114 1086
1115 /// <summary> 1087 void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, byte source,
1116 /// Send chat to the viewer. 1088 byte audible);
1117 /// </summary>
1118 /// <param name='message'></param>
1119 /// <param name='type'></param>
1120 /// <param name='fromPos'></param>
1121 /// <param name='fromName'></param>
1122 /// <param name='fromAgentID'></param>
1123 /// <param name='ownerID'></param>
1124 /// <param name='source'></param>
1125 /// <param name='audible'></param>
1126 void SendChatMessage(
1127 string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, UUID ownerID, byte source,
1128 byte audible);
1129 1089
1130 void SendInstantMessage(GridInstantMessage im); 1090 void SendInstantMessage(GridInstantMessage im);
1131 1091
diff --git a/OpenSim/Framework/InventoryFolderBase.cs b/OpenSim/Framework/InventoryFolderBase.cs
index b3457a6..a12183c 100644
--- a/OpenSim/Framework/InventoryFolderBase.cs
+++ b/OpenSim/Framework/InventoryFolderBase.cs
@@ -73,27 +73,33 @@ namespace OpenSim.Framework
73 { 73 {
74 } 74 }
75 75
76 public InventoryFolderBase(UUID id) : this() 76 public InventoryFolderBase(UUID id)
77 { 77 {
78 ID = id; 78 ID = id;
79 } 79 }
80 80
81 public InventoryFolderBase(UUID id, UUID owner) : this(id) 81 public InventoryFolderBase(UUID id, UUID owner)
82 { 82 {
83 ID = id;
83 Owner = owner; 84 Owner = owner;
84 } 85 }
85 86
86 public InventoryFolderBase(UUID id, string name, UUID owner, UUID parent) : this(id, owner) 87 public InventoryFolderBase(UUID id, string name, UUID owner, UUID parent)
87 { 88 {
89 ID = id;
88 Name = name; 90 Name = name;
91 Owner = owner;
89 ParentID = parent; 92 ParentID = parent;
90 } 93 }
91 94
92 public InventoryFolderBase( 95 public InventoryFolderBase(UUID id, string name, UUID owner, short type, UUID parent, ushort version)
93 UUID id, string name, UUID owner, short type, UUID parent, ushort version) : this(id, name, owner, parent)
94 { 96 {
97 ID = id;
98 Name = name;
99 Owner = owner;
95 Type = type; 100 Type = type;
101 ParentID = parent;
96 Version = version; 102 Version = version;
97 } 103 }
98 } 104 }
99} \ No newline at end of file 105}
diff --git a/OpenSim/Framework/LandData.cs b/OpenSim/Framework/LandData.cs
index 4dffd3f..dcaa46d 100644
--- a/OpenSim/Framework/LandData.cs
+++ b/OpenSim/Framework/LandData.cs
@@ -49,8 +49,8 @@ namespace OpenSim.Framework
49 // use only one serializer to give the runtime a chance to 49 // use only one serializer to give the runtime a chance to
50 // optimize it (it won't do that if you use a new instance 50 // optimize it (it won't do that if you use a new instance
51 // every time) 51 // every time)
52 private static XmlSerializer serializer = new XmlSerializer(typeof(LandData)); 52 private static XmlSerializer serializer = new XmlSerializer(typeof (LandData));
53 53
54 private Vector3 _AABBMax = new Vector3(); 54 private Vector3 _AABBMax = new Vector3();
55 private Vector3 _AABBMin = new Vector3(); 55 private Vector3 _AABBMin = new Vector3();
56 private int _area = 0; 56 private int _area = 0;
@@ -65,11 +65,11 @@ namespace OpenSim.Framework
65 private byte[] _bitmap = new byte[512]; 65 private byte[] _bitmap = new byte[512];
66 private string _description = String.Empty; 66 private string _description = String.Empty;
67 67
68 private uint _flags = (uint)ParcelFlags.AllowFly | (uint)ParcelFlags.AllowLandmark | 68 private uint _flags = (uint) ParcelFlags.AllowFly | (uint) ParcelFlags.AllowLandmark |
69 (uint)ParcelFlags.AllowAPrimitiveEntry | 69 (uint) ParcelFlags.AllowAPrimitiveEntry |
70 (uint)ParcelFlags.AllowDeedToGroup | 70 (uint) ParcelFlags.AllowDeedToGroup |
71 (uint)ParcelFlags.CreateObjects | (uint)ParcelFlags.AllowOtherScripts | 71 (uint) ParcelFlags.CreateObjects | (uint) ParcelFlags.AllowOtherScripts |
72 (uint)ParcelFlags.AllowVoiceChat; 72 (uint) ParcelFlags.SoundLocal | (uint) ParcelFlags.AllowVoiceChat;
73 73
74 private byte _landingType = 0; 74 private byte _landingType = 0;
75 private string _name = "Your Parcel"; 75 private string _name = "Your Parcel";
@@ -97,36 +97,16 @@ namespace OpenSim.Framework
97 private bool _mediaLoop = false; 97 private bool _mediaLoop = false;
98 private bool _obscureMusic = false; 98 private bool _obscureMusic = false;
99 private bool _obscureMedia = false; 99 private bool _obscureMedia = false;
100 private float _dwell = 0;
101
102 /// <summary>
103 /// Traffic count of parcel
104 /// </summary>
105 [XmlIgnore]
106 public float Dwell
107 {
108 get
109 {
110 return _dwell;
111 }
112 set
113 {
114 _dwell = value;
115 }
116 }
117 100
118 /// <summary> 101 /// <summary>
119 /// Whether to obscure parcel media URL 102 /// Whether to obscure parcel media URL
120 /// </summary> 103 /// </summary>
121 [XmlIgnore] 104 [XmlIgnore]
122 public bool ObscureMedia 105 public bool ObscureMedia {
123 { 106 get {
124 get
125 {
126 return _obscureMedia; 107 return _obscureMedia;
127 } 108 }
128 set 109 set {
129 {
130 _obscureMedia = value; 110 _obscureMedia = value;
131 } 111 }
132 } 112 }
@@ -135,14 +115,11 @@ namespace OpenSim.Framework
135 /// Whether to obscure parcel music URL 115 /// Whether to obscure parcel music URL
136 /// </summary> 116 /// </summary>
137 [XmlIgnore] 117 [XmlIgnore]
138 public bool ObscureMusic 118 public bool ObscureMusic {
139 { 119 get {
140 get
141 {
142 return _obscureMusic; 120 return _obscureMusic;
143 } 121 }
144 set 122 set {
145 {
146 _obscureMusic = value; 123 _obscureMusic = value;
147 } 124 }
148 } 125 }
@@ -151,14 +128,11 @@ namespace OpenSim.Framework
151 /// Whether to loop parcel media 128 /// Whether to loop parcel media
152 /// </summary> 129 /// </summary>
153 [XmlIgnore] 130 [XmlIgnore]
154 public bool MediaLoop 131 public bool MediaLoop {
155 { 132 get {
156 get
157 {
158 return _mediaLoop; 133 return _mediaLoop;
159 } 134 }
160 set 135 set {
161 {
162 _mediaLoop = value; 136 _mediaLoop = value;
163 } 137 }
164 } 138 }
@@ -167,14 +141,11 @@ namespace OpenSim.Framework
167 /// Height of parcel media render 141 /// Height of parcel media render
168 /// </summary> 142 /// </summary>
169 [XmlIgnore] 143 [XmlIgnore]
170 public int MediaHeight 144 public int MediaHeight {
171 { 145 get {
172 get
173 {
174 return _mediaHeight; 146 return _mediaHeight;
175 } 147 }
176 set 148 set {
177 {
178 _mediaHeight = value; 149 _mediaHeight = value;
179 } 150 }
180 } 151 }
@@ -183,14 +154,11 @@ namespace OpenSim.Framework
183 /// Width of parcel media render 154 /// Width of parcel media render
184 /// </summary> 155 /// </summary>
185 [XmlIgnore] 156 [XmlIgnore]
186 public int MediaWidth 157 public int MediaWidth {
187 { 158 get {
188 get
189 {
190 return _mediaWidth; 159 return _mediaWidth;
191 } 160 }
192 set 161 set {
193 {
194 _mediaWidth = value; 162 _mediaWidth = value;
195 } 163 }
196 } 164 }
@@ -199,14 +167,11 @@ namespace OpenSim.Framework
199 /// Upper corner of the AABB for the parcel 167 /// Upper corner of the AABB for the parcel
200 /// </summary> 168 /// </summary>
201 [XmlIgnore] 169 [XmlIgnore]
202 public Vector3 AABBMax 170 public Vector3 AABBMax {
203 { 171 get {
204 get
205 {
206 return _AABBMax; 172 return _AABBMax;
207 } 173 }
208 set 174 set {
209 {
210 _AABBMax = value; 175 _AABBMax = value;
211 } 176 }
212 } 177 }
@@ -214,14 +179,11 @@ namespace OpenSim.Framework
214 /// Lower corner of the AABB for the parcel 179 /// Lower corner of the AABB for the parcel
215 /// </summary> 180 /// </summary>
216 [XmlIgnore] 181 [XmlIgnore]
217 public Vector3 AABBMin 182 public Vector3 AABBMin {
218 { 183 get {
219 get
220 {
221 return _AABBMin; 184 return _AABBMin;
222 } 185 }
223 set 186 set {
224 {
225 _AABBMin = value; 187 _AABBMin = value;
226 } 188 }
227 } 189 }
@@ -229,14 +191,11 @@ namespace OpenSim.Framework
229 /// <summary> 191 /// <summary>
230 /// Area in meters^2 the parcel contains 192 /// Area in meters^2 the parcel contains
231 /// </summary> 193 /// </summary>
232 public int Area 194 public int Area {
233 { 195 get {
234 get
235 {
236 return _area; 196 return _area;
237 } 197 }
238 set 198 set {
239 {
240 _area = value; 199 _area = value;
241 } 200 }
242 } 201 }
@@ -244,14 +203,11 @@ namespace OpenSim.Framework
244 /// <summary> 203 /// <summary>
245 /// ID of auction (3rd Party Integration) when parcel is being auctioned 204 /// ID of auction (3rd Party Integration) when parcel is being auctioned
246 /// </summary> 205 /// </summary>
247 public uint AuctionID 206 public uint AuctionID {
248 { 207 get {
249 get
250 {
251 return _auctionID; 208 return _auctionID;
252 } 209 }
253 set 210 set {
254 {
255 _auctionID = value; 211 _auctionID = value;
256 } 212 }
257 } 213 }
@@ -259,14 +215,11 @@ namespace OpenSim.Framework
259 /// <summary> 215 /// <summary>
260 /// UUID of authorized buyer of parcel. This is UUID.Zero if anyone can buy it. 216 /// UUID of authorized buyer of parcel. This is UUID.Zero if anyone can buy it.
261 /// </summary> 217 /// </summary>
262 public UUID AuthBuyerID 218 public UUID AuthBuyerID {
263 { 219 get {
264 get
265 {
266 return _authBuyerID; 220 return _authBuyerID;
267 } 221 }
268 set 222 set {
269 {
270 _authBuyerID = value; 223 _authBuyerID = value;
271 } 224 }
272 } 225 }
@@ -274,14 +227,11 @@ namespace OpenSim.Framework
274 /// <summary> 227 /// <summary>
275 /// Category of parcel. Used for classifying the parcel in classified listings 228 /// Category of parcel. Used for classifying the parcel in classified listings
276 /// </summary> 229 /// </summary>
277 public ParcelCategory Category 230 public ParcelCategory Category {
278 { 231 get {
279 get
280 {
281 return _category; 232 return _category;
282 } 233 }
283 set 234 set {
284 {
285 _category = value; 235 _category = value;
286 } 236 }
287 } 237 }
@@ -289,14 +239,11 @@ namespace OpenSim.Framework
289 /// <summary> 239 /// <summary>
290 /// Date that the current owner purchased or claimed the parcel 240 /// Date that the current owner purchased or claimed the parcel
291 /// </summary> 241 /// </summary>
292 public int ClaimDate 242 public int ClaimDate {
293 { 243 get {
294 get
295 {
296 return _claimDate; 244 return _claimDate;
297 } 245 }
298 set 246 set {
299 {
300 _claimDate = value; 247 _claimDate = value;
301 } 248 }
302 } 249 }
@@ -304,14 +251,11 @@ namespace OpenSim.Framework
304 /// <summary> 251 /// <summary>
305 /// The last price that the parcel was sold at 252 /// The last price that the parcel was sold at
306 /// </summary> 253 /// </summary>
307 public int ClaimPrice 254 public int ClaimPrice {
308 { 255 get {
309 get
310 {
311 return _claimPrice; 256 return _claimPrice;
312 } 257 }
313 set 258 set {
314 {
315 _claimPrice = value; 259 _claimPrice = value;
316 } 260 }
317 } 261 }
@@ -319,14 +263,11 @@ namespace OpenSim.Framework
319 /// <summary> 263 /// <summary>
320 /// Global ID for the parcel. (3rd Party Integration) 264 /// Global ID for the parcel. (3rd Party Integration)
321 /// </summary> 265 /// </summary>
322 public UUID GlobalID 266 public UUID GlobalID {
323 { 267 get {
324 get
325 {
326 return _globalID; 268 return _globalID;
327 } 269 }
328 set 270 set {
329 {
330 _globalID = value; 271 _globalID = value;
331 } 272 }
332 } 273 }
@@ -334,14 +275,11 @@ namespace OpenSim.Framework
334 /// <summary> 275 /// <summary>
335 /// Unique ID of the Group that owns 276 /// Unique ID of the Group that owns
336 /// </summary> 277 /// </summary>
337 public UUID GroupID 278 public UUID GroupID {
338 { 279 get {
339 get
340 {
341 return _groupID; 280 return _groupID;
342 } 281 }
343 set 282 set {
344 {
345 _groupID = value; 283 _groupID = value;
346 } 284 }
347 } 285 }
@@ -349,14 +287,11 @@ namespace OpenSim.Framework
349 /// <summary> 287 /// <summary>
350 /// Returns true if the Land Parcel is owned by a group 288 /// Returns true if the Land Parcel is owned by a group
351 /// </summary> 289 /// </summary>
352 public bool IsGroupOwned 290 public bool IsGroupOwned {
353 { 291 get {
354 get
355 {
356 return _isGroupOwned; 292 return _isGroupOwned;
357 } 293 }
358 set 294 set {
359 {
360 _isGroupOwned = value; 295 _isGroupOwned = value;
361 } 296 }
362 } 297 }
@@ -364,14 +299,11 @@ namespace OpenSim.Framework
364 /// <summary> 299 /// <summary>
365 /// jp2 data for the image representative of the parcel in the parcel dialog 300 /// jp2 data for the image representative of the parcel in the parcel dialog
366 /// </summary> 301 /// </summary>
367 public byte[] Bitmap 302 public byte[] Bitmap {
368 { 303 get {
369 get
370 {
371 return _bitmap; 304 return _bitmap;
372 } 305 }
373 set 306 set {
374 {
375 _bitmap = value; 307 _bitmap = value;
376 } 308 }
377 } 309 }
@@ -379,14 +311,11 @@ namespace OpenSim.Framework
379 /// <summary> 311 /// <summary>
380 /// Parcel Description 312 /// Parcel Description
381 /// </summary> 313 /// </summary>
382 public string Description 314 public string Description {
383 { 315 get {
384 get
385 {
386 return _description; 316 return _description;
387 } 317 }
388 set 318 set {
389 {
390 _description = value; 319 _description = value;
391 } 320 }
392 } 321 }
@@ -394,14 +323,11 @@ namespace OpenSim.Framework
394 /// <summary> 323 /// <summary>
395 /// Parcel settings. Access flags, Fly, NoPush, Voice, Scripts allowed, etc. ParcelFlags 324 /// Parcel settings. Access flags, Fly, NoPush, Voice, Scripts allowed, etc. ParcelFlags
396 /// </summary> 325 /// </summary>
397 public uint Flags 326 public uint Flags {
398 { 327 get {
399 get
400 {
401 return _flags; 328 return _flags;
402 } 329 }
403 set 330 set {
404 {
405 _flags = value; 331 _flags = value;
406 } 332 }
407 } 333 }
@@ -410,14 +336,11 @@ namespace OpenSim.Framework
410 /// Determines if people are able to teleport where they please on the parcel or if they 336 /// Determines if people are able to teleport where they please on the parcel or if they
411 /// get constrainted to a specific point on teleport within the parcel 337 /// get constrainted to a specific point on teleport within the parcel
412 /// </summary> 338 /// </summary>
413 public byte LandingType 339 public byte LandingType {
414 { 340 get {
415 get
416 {
417 return _landingType; 341 return _landingType;
418 } 342 }
419 set 343 set {
420 {
421 _landingType = value; 344 _landingType = value;
422 } 345 }
423 } 346 }
@@ -425,14 +348,11 @@ namespace OpenSim.Framework
425 /// <summary> 348 /// <summary>
426 /// Parcel Name 349 /// Parcel Name
427 /// </summary> 350 /// </summary>
428 public string Name 351 public string Name {
429 { 352 get {
430 get
431 {
432 return _name; 353 return _name;
433 } 354 }
434 set 355 set {
435 {
436 _name = value; 356 _name = value;
437 } 357 }
438 } 358 }
@@ -440,14 +360,11 @@ namespace OpenSim.Framework
440 /// <summary> 360 /// <summary>
441 /// Status of Parcel, Leased, Abandoned, For Sale 361 /// Status of Parcel, Leased, Abandoned, For Sale
442 /// </summary> 362 /// </summary>
443 public ParcelStatus Status 363 public ParcelStatus Status {
444 { 364 get {
445 get
446 {
447 return _status; 365 return _status;
448 } 366 }
449 set 367 set {
450 {
451 _status = value; 368 _status = value;
452 } 369 }
453 } 370 }
@@ -455,14 +372,11 @@ namespace OpenSim.Framework
455 /// <summary> 372 /// <summary>
456 /// Internal ID of the parcel. Sometimes the client will try to use this value 373 /// Internal ID of the parcel. Sometimes the client will try to use this value
457 /// </summary> 374 /// </summary>
458 public int LocalID 375 public int LocalID {
459 { 376 get {
460 get
461 {
462 return _localID; 377 return _localID;
463 } 378 }
464 set 379 set {
465 {
466 _localID = value; 380 _localID = value;
467 } 381 }
468 } 382 }
@@ -470,14 +384,11 @@ namespace OpenSim.Framework
470 /// <summary> 384 /// <summary>
471 /// Determines if we scale the media based on the surface it's on 385 /// Determines if we scale the media based on the surface it's on
472 /// </summary> 386 /// </summary>
473 public byte MediaAutoScale 387 public byte MediaAutoScale {
474 { 388 get {
475 get
476 {
477 return _mediaAutoScale; 389 return _mediaAutoScale;
478 } 390 }
479 set 391 set {
480 {
481 _mediaAutoScale = value; 392 _mediaAutoScale = value;
482 } 393 }
483 } 394 }
@@ -485,14 +396,11 @@ namespace OpenSim.Framework
485 /// <summary> 396 /// <summary>
486 /// Texture Guid to replace with the output of the media stream 397 /// Texture Guid to replace with the output of the media stream
487 /// </summary> 398 /// </summary>
488 public UUID MediaID 399 public UUID MediaID {
489 { 400 get {
490 get
491 {
492 return _mediaID; 401 return _mediaID;
493 } 402 }
494 set 403 set {
495 {
496 _mediaID = value; 404 _mediaID = value;
497 } 405 }
498 } 406 }
@@ -500,14 +408,11 @@ namespace OpenSim.Framework
500 /// <summary> 408 /// <summary>
501 /// URL to the media file to display 409 /// URL to the media file to display
502 /// </summary> 410 /// </summary>
503 public string MediaURL 411 public string MediaURL {
504 { 412 get {
505 get
506 {
507 return _mediaURL; 413 return _mediaURL;
508 } 414 }
509 set 415 set {
510 {
511 _mediaURL = value; 416 _mediaURL = value;
512 } 417 }
513 } 418 }
@@ -527,14 +432,11 @@ namespace OpenSim.Framework
527 /// <summary> 432 /// <summary>
528 /// URL to the shoutcast music stream to play on the parcel 433 /// URL to the shoutcast music stream to play on the parcel
529 /// </summary> 434 /// </summary>
530 public string MusicURL 435 public string MusicURL {
531 { 436 get {
532 get
533 {
534 return _musicURL; 437 return _musicURL;
535 } 438 }
536 set 439 set {
537 {
538 _musicURL = value; 440 _musicURL = value;
539 } 441 }
540 } 442 }
@@ -543,14 +445,11 @@ namespace OpenSim.Framework
543 /// Owner Avatar or Group of the parcel. Naturally, all land masses must be 445 /// Owner Avatar or Group of the parcel. Naturally, all land masses must be
544 /// owned by someone 446 /// owned by someone
545 /// </summary> 447 /// </summary>
546 public UUID OwnerID 448 public UUID OwnerID {
547 { 449 get {
548 get
549 {
550 return _ownerID; 450 return _ownerID;
551 } 451 }
552 set 452 set {
553 {
554 _ownerID = value; 453 _ownerID = value;
555 } 454 }
556 } 455 }
@@ -558,14 +457,11 @@ namespace OpenSim.Framework
558 /// <summary> 457 /// <summary>
559 /// List of access data for the parcel. User data, some bitflags, and a time 458 /// List of access data for the parcel. User data, some bitflags, and a time
560 /// </summary> 459 /// </summary>
561 public List<LandAccessEntry> ParcelAccessList 460 public List<LandAccessEntry> ParcelAccessList {
562 { 461 get {
563 get
564 {
565 return _parcelAccessList; 462 return _parcelAccessList;
566 } 463 }
567 set 464 set {
568 {
569 _parcelAccessList = value; 465 _parcelAccessList = value;
570 } 466 }
571 } 467 }
@@ -573,14 +469,11 @@ namespace OpenSim.Framework
573 /// <summary> 469 /// <summary>
574 /// How long in hours a Pass to the parcel is given 470 /// How long in hours a Pass to the parcel is given
575 /// </summary> 471 /// </summary>
576 public float PassHours 472 public float PassHours {
577 { 473 get {
578 get
579 {
580 return _passHours; 474 return _passHours;
581 } 475 }
582 set 476 set {
583 {
584 _passHours = value; 477 _passHours = value;
585 } 478 }
586 } 479 }
@@ -588,14 +481,11 @@ namespace OpenSim.Framework
588 /// <summary> 481 /// <summary>
589 /// Price to purchase a Pass to a restricted parcel 482 /// Price to purchase a Pass to a restricted parcel
590 /// </summary> 483 /// </summary>
591 public int PassPrice 484 public int PassPrice {
592 { 485 get {
593 get
594 {
595 return _passPrice; 486 return _passPrice;
596 } 487 }
597 set 488 set {
598 {
599 _passPrice = value; 489 _passPrice = value;
600 } 490 }
601 } 491 }
@@ -603,14 +493,11 @@ namespace OpenSim.Framework
603 /// <summary> 493 /// <summary>
604 /// When the parcel is being sold, this is the price to purchase the parcel 494 /// When the parcel is being sold, this is the price to purchase the parcel
605 /// </summary> 495 /// </summary>
606 public int SalePrice 496 public int SalePrice {
607 { 497 get {
608 get
609 {
610 return _salePrice; 498 return _salePrice;
611 } 499 }
612 set 500 set {
613 {
614 _salePrice = value; 501 _salePrice = value;
615 } 502 }
616 } 503 }
@@ -619,14 +506,11 @@ namespace OpenSim.Framework
619 /// Number of meters^2 in the Simulator 506 /// Number of meters^2 in the Simulator
620 /// </summary> 507 /// </summary>
621 [XmlIgnore] 508 [XmlIgnore]
622 public int SimwideArea 509 public int SimwideArea {
623 { 510 get {
624 get
625 {
626 return _simwideArea; 511 return _simwideArea;
627 } 512 }
628 set 513 set {
629 {
630 _simwideArea = value; 514 _simwideArea = value;
631 } 515 }
632 } 516 }
@@ -635,14 +519,11 @@ namespace OpenSim.Framework
635 /// Number of SceneObjectPart in the Simulator 519 /// Number of SceneObjectPart in the Simulator
636 /// </summary> 520 /// </summary>
637 [XmlIgnore] 521 [XmlIgnore]
638 public int SimwidePrims 522 public int SimwidePrims {
639 { 523 get {
640 get
641 {
642 return _simwidePrims; 524 return _simwidePrims;
643 } 525 }
644 set 526 set {
645 {
646 _simwidePrims = value; 527 _simwidePrims = value;
647 } 528 }
648 } 529 }
@@ -650,14 +531,11 @@ namespace OpenSim.Framework
650 /// <summary> 531 /// <summary>
651 /// ID of the snapshot used in the client parcel dialog of the parcel 532 /// ID of the snapshot used in the client parcel dialog of the parcel
652 /// </summary> 533 /// </summary>
653 public UUID SnapshotID 534 public UUID SnapshotID {
654 { 535 get {
655 get
656 {
657 return _snapshotID; 536 return _snapshotID;
658 } 537 }
659 set 538 set {
660 {
661 _snapshotID = value; 539 _snapshotID = value;
662 } 540 }
663 } 541 }
@@ -666,14 +544,11 @@ namespace OpenSim.Framework
666 /// When teleporting is restricted to a certain point, this is the location 544 /// When teleporting is restricted to a certain point, this is the location
667 /// that the user will be redirected to 545 /// that the user will be redirected to
668 /// </summary> 546 /// </summary>
669 public Vector3 UserLocation 547 public Vector3 UserLocation {
670 { 548 get {
671 get
672 {
673 return _userLocation; 549 return _userLocation;
674 } 550 }
675 set 551 set {
676 {
677 _userLocation = value; 552 _userLocation = value;
678 } 553 }
679 } 554 }
@@ -682,14 +557,11 @@ namespace OpenSim.Framework
682 /// When teleporting is restricted to a certain point, this is the rotation 557 /// When teleporting is restricted to a certain point, this is the rotation
683 /// that the user will be positioned 558 /// that the user will be positioned
684 /// </summary> 559 /// </summary>
685 public Vector3 UserLookAt 560 public Vector3 UserLookAt {
686 { 561 get {
687 get
688 {
689 return _userLookAt; 562 return _userLookAt;
690 } 563 }
691 set 564 set {
692 {
693 _userLookAt = value; 565 _userLookAt = value;
694 } 566 }
695 } 567 }
@@ -698,14 +570,11 @@ namespace OpenSim.Framework
698 /// Autoreturn number of minutes to return SceneObjectGroup that are owned by someone who doesn't own 570 /// Autoreturn number of minutes to return SceneObjectGroup that are owned by someone who doesn't own
699 /// the parcel and isn't set to the same 'group' as the parcel. 571 /// the parcel and isn't set to the same 'group' as the parcel.
700 /// </summary> 572 /// </summary>
701 public int OtherCleanTime 573 public int OtherCleanTime {
702 { 574 get {
703 get
704 {
705 return _otherCleanTime; 575 return _otherCleanTime;
706 } 576 }
707 set 577 set {
708 {
709 _otherCleanTime = value; 578 _otherCleanTime = value;
710 } 579 }
711 } 580 }
@@ -713,14 +582,11 @@ namespace OpenSim.Framework
713 /// <summary> 582 /// <summary>
714 /// parcel media description 583 /// parcel media description
715 /// </summary> 584 /// </summary>
716 public string MediaDescription 585 public string MediaDescription {
717 { 586 get {
718 get
719 {
720 return _mediaDescription; 587 return _mediaDescription;
721 } 588 }
722 set 589 set {
723 {
724 _mediaDescription = value; 590 _mediaDescription = value;
725 } 591 }
726 } 592 }
@@ -756,7 +622,7 @@ namespace OpenSim.Framework
756 landData._mediaURL = _mediaURL; 622 landData._mediaURL = _mediaURL;
757 landData._musicURL = _musicURL; 623 landData._musicURL = _musicURL;
758 landData._ownerID = _ownerID; 624 landData._ownerID = _ownerID;
759 landData._bitmap = (byte[])_bitmap.Clone(); 625 landData._bitmap = (byte[]) _bitmap.Clone();
760 landData._description = _description; 626 landData._description = _description;
761 landData._flags = _flags; 627 landData._flags = _flags;
762 landData._name = _name; 628 landData._name = _name;
@@ -777,7 +643,6 @@ namespace OpenSim.Framework
777 landData._obscureMedia = _obscureMedia; 643 landData._obscureMedia = _obscureMedia;
778 landData._simwideArea = _simwideArea; 644 landData._simwideArea = _simwideArea;
779 landData._simwidePrims = _simwidePrims; 645 landData._simwidePrims = _simwidePrims;
780 landData._dwell = _dwell;
781 646
782 landData._parcelAccessList.Clear(); 647 landData._parcelAccessList.Clear();
783 foreach (LandAccessEntry entry in _parcelAccessList) 648 foreach (LandAccessEntry entry in _parcelAccessList)
diff --git a/OpenSim/Framework/Monitoring/BaseStatsCollector.cs b/OpenSim/Framework/Monitoring/BaseStatsCollector.cs
index 446e3c0..9ee0876 100644
--- a/OpenSim/Framework/Monitoring/BaseStatsCollector.cs
+++ b/OpenSim/Framework/Monitoring/BaseStatsCollector.cs
@@ -43,32 +43,27 @@ namespace OpenSim.Framework.Monitoring
43 StringBuilder sb = new StringBuilder(Environment.NewLine); 43 StringBuilder sb = new StringBuilder(Environment.NewLine);
44 sb.Append("MEMORY STATISTICS"); 44 sb.Append("MEMORY STATISTICS");
45 sb.Append(Environment.NewLine); 45 sb.Append(Environment.NewLine);
46 sb.AppendFormat( 46 sb.Append(
47 string.Format(
47 "Allocated to OpenSim objects: {0} MB\n", 48 "Allocated to OpenSim objects: {0} MB\n",
48 Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0)); 49 Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0)));
49
50 sb.AppendFormat(
51 "OpenSim last object memory churn : {0} MB/s\n",
52 Math.Round((MemoryWatchdog.LastMemoryChurn * 1000) / 1024.0 / 1024, 3));
53
54 sb.AppendFormat(
55 "OpenSim average object memory churn : {0} MB/s\n",
56 Math.Round((MemoryWatchdog.AverageMemoryChurn * 1000) / 1024.0 / 1024, 3));
57 50
58 Process myprocess = Process.GetCurrentProcess(); 51 Process myprocess = Process.GetCurrentProcess();
59 if (!myprocess.HasExited) 52 if (!myprocess.HasExited)
60 { 53 {
61 myprocess.Refresh(); 54 myprocess.Refresh();
62 sb.AppendFormat( 55 sb.Append(
56 string.Format(
63 "Process memory: Physical {0} MB \t Paged {1} MB \t Virtual {2} MB\n", 57 "Process memory: Physical {0} MB \t Paged {1} MB \t Virtual {2} MB\n",
64 Math.Round(Process.GetCurrentProcess().WorkingSet64 / 1024.0 / 1024.0), 58 Math.Round(Process.GetCurrentProcess().WorkingSet64 / 1024.0 / 1024.0),
65 Math.Round(Process.GetCurrentProcess().PagedMemorySize64 / 1024.0 / 1024.0), 59 Math.Round(Process.GetCurrentProcess().PagedMemorySize64 / 1024.0 / 1024.0),
66 Math.Round(Process.GetCurrentProcess().VirtualMemorySize64 / 1024.0 / 1024.0)); 60 Math.Round(Process.GetCurrentProcess().VirtualMemorySize64 / 1024.0 / 1024.0)));
67 sb.AppendFormat( 61 sb.Append(
62 string.Format(
68 "Peak process memory: Physical {0} MB \t Paged {1} MB \t Virtual {2} MB\n", 63 "Peak process memory: Physical {0} MB \t Paged {1} MB \t Virtual {2} MB\n",
69 Math.Round(Process.GetCurrentProcess().PeakWorkingSet64 / 1024.0 / 1024.0), 64 Math.Round(Process.GetCurrentProcess().PeakWorkingSet64 / 1024.0 / 1024.0),
70 Math.Round(Process.GetCurrentProcess().PeakPagedMemorySize64 / 1024.0 / 1024.0), 65 Math.Round(Process.GetCurrentProcess().PeakPagedMemorySize64 / 1024.0 / 1024.0),
71 Math.Round(Process.GetCurrentProcess().PeakVirtualMemorySize64 / 1024.0 / 1024.0)); 66 Math.Round(Process.GetCurrentProcess().PeakVirtualMemorySize64 / 1024.0 / 1024.0)));
72 } 67 }
73 else 68 else
74 sb.Append("Process reported as Exited \n"); 69 sb.Append("Process reported as Exited \n");
diff --git a/OpenSim/Framework/Monitoring/MemoryWatchdog.cs b/OpenSim/Framework/Monitoring/MemoryWatchdog.cs
index c6010cd..a23cf1f 100644
--- a/OpenSim/Framework/Monitoring/MemoryWatchdog.cs
+++ b/OpenSim/Framework/Monitoring/MemoryWatchdog.cs
@@ -60,7 +60,7 @@ namespace OpenSim.Framework.Monitoring
60 private static bool m_enabled; 60 private static bool m_enabled;
61 61
62 /// <summary> 62 /// <summary>
63 /// Last memory churn in bytes per millisecond. 63 /// Average memory churn in bytes per millisecond.
64 /// </summary> 64 /// </summary>
65 public static double AverageMemoryChurn 65 public static double AverageMemoryChurn
66 { 66 {
@@ -68,14 +68,6 @@ namespace OpenSim.Framework.Monitoring
68 } 68 }
69 69
70 /// <summary> 70 /// <summary>
71 /// Average memory churn in bytes per millisecond.
72 /// </summary>
73 public static double LastMemoryChurn
74 {
75 get { if (m_samples.Count > 0) return m_samples.Last(); else return 0; }
76 }
77
78 /// <summary>
79 /// Maximum number of statistical samples. 71 /// Maximum number of statistical samples.
80 /// </summary> 72 /// </summary>
81 /// <remarks> 73 /// <remarks>
diff --git a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs
index aa86202..cdd7cc7 100644
--- a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs
+++ b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs
@@ -355,25 +355,10 @@ Asset service request failures: {3}" + Environment.NewLine,
355 sb.Append(Environment.NewLine); 355 sb.Append(Environment.NewLine);
356 sb.Append( 356 sb.Append(
357 string.Format( 357 string.Format(
358 "{0,6:0} {1,6:0} {2,6:0} {3,6:0} {4,6:0} {5,6:0.0} {6,6:0.0} {7,6:0.0} {8,6:0.0} {9,6:0.0} {10,6:0.0}\n\n", 358 "{0,6:0} {1,6:0} {2,6:0} {3,6:0} {4,6:0} {5,6:0.0} {6,6:0.0} {7,6:0.0} {8,6:0.0} {9,6:0.0} {10,6:0.0}",
359 inPacketsPerSecond, outPacketsPerSecond, pendingDownloads, pendingUploads, unackedBytes, totalFrameTime, 359 inPacketsPerSecond, outPacketsPerSecond, pendingDownloads, pendingUploads, unackedBytes, totalFrameTime,
360 netFrameTime, physicsFrameTime, otherFrameTime, agentFrameTime, imageFrameTime)); 360 netFrameTime, physicsFrameTime, otherFrameTime, agentFrameTime, imageFrameTime));
361 361 sb.Append(Environment.NewLine);
362 Dictionary<string, Dictionary<string, Stat>> sceneStats;
363
364 if (StatsManager.TryGetStats("scene", out sceneStats))
365 {
366 foreach (KeyValuePair<string, Dictionary<string, Stat>> kvp in sceneStats)
367 {
368 foreach (Stat stat in kvp.Value.Values)
369 {
370 if (stat.Verbosity == StatVerbosity.Info)
371 {
372 sb.AppendFormat("{0} ({1}): {2}{3}\n", stat.Name, stat.Container, stat.Value, stat.UnitName);
373 }
374 }
375 }
376 }
377 362
378 /* 363 /*
379 sb.Append(Environment.NewLine); 364 sb.Append(Environment.NewLine);
diff --git a/OpenSim/Framework/Monitoring/StatsManager.cs b/OpenSim/Framework/Monitoring/StatsManager.cs
index 4844336..d78fa6a 100644
--- a/OpenSim/Framework/Monitoring/StatsManager.cs
+++ b/OpenSim/Framework/Monitoring/StatsManager.cs
@@ -25,9 +25,6 @@
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;
29using System.Collections.Generic;
30
31namespace OpenSim.Framework.Monitoring 28namespace OpenSim.Framework.Monitoring
32{ 29{
33 /// <summary> 30 /// <summary>
@@ -35,24 +32,6 @@ namespace OpenSim.Framework.Monitoring
35 /// </summary> 32 /// </summary>
36 public class StatsManager 33 public class StatsManager
37 { 34 {
38 // Subcommand used to list other stats.
39 public const string AllSubCommand = "all";
40
41 // Subcommand used to list other stats.
42 public const string ListSubCommand = "list";
43
44 // All subcommands
45 public static HashSet<string> SubCommands = new HashSet<string> { AllSubCommand, ListSubCommand };
46
47 /// <summary>
48 /// Registered stats categorized by category/container/shortname
49 /// </summary>
50 /// <remarks>
51 /// Do not add or remove directly from this dictionary.
52 /// </remarks>
53 public static Dictionary<string, Dictionary<string, Dictionary<string, Stat>>> RegisteredStats
54 = new Dictionary<string, Dictionary<string, Dictionary<string, Stat>>>();
55
56 private static AssetStatsCollector assetStats; 35 private static AssetStatsCollector assetStats;
57 private static UserStatsCollector userStats; 36 private static UserStatsCollector userStats;
58 private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector(); 37 private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector();
@@ -61,75 +40,6 @@ namespace OpenSim.Framework.Monitoring
61 public static UserStatsCollector UserStats { get { return userStats; } } 40 public static UserStatsCollector UserStats { get { return userStats; } }
62 public static SimExtraStatsCollector SimExtraStats { get { return simExtraStats; } } 41 public static SimExtraStatsCollector SimExtraStats { get { return simExtraStats; } }
63 42
64 public static void RegisterConsoleCommands(ICommandConsole console)
65 {
66 console.Commands.AddCommand(
67 "General",
68 false,
69 "show stats",
70 "show stats [list|all|<category>]",
71 "Show statistical information for this server",
72 "If no final argument is specified then legacy statistics information is currently shown.\n"
73 + "If list is specified then statistic categories are shown.\n"
74 + "If all is specified then all registered statistics are shown.\n"
75 + "If a category name is specified then only statistics from that category are shown.\n"
76 + "THIS STATS FACILITY IS EXPERIMENTAL AND DOES NOT YET CONTAIN ALL STATS",
77 HandleShowStatsCommand);
78 }
79
80 public static void HandleShowStatsCommand(string module, string[] cmd)
81 {
82 ICommandConsole con = MainConsole.Instance;
83
84 if (cmd.Length > 2)
85 {
86 var categoryName = cmd[2];
87
88 if (categoryName == AllSubCommand)
89 {
90 foreach (var category in RegisteredStats.Values)
91 {
92 OutputCategoryStatsToConsole(con, category);
93 }
94 }
95 else if (categoryName == ListSubCommand)
96 {
97 con.Output("Statistic categories available are:");
98 foreach (string category in RegisteredStats.Keys)
99 con.OutputFormat(" {0}", category);
100 }
101 else
102 {
103 Dictionary<string, Dictionary<string, Stat>> category;
104 if (!RegisteredStats.TryGetValue(categoryName, out category))
105 {
106 con.OutputFormat("No such category as {0}", categoryName);
107 }
108 else
109 {
110 OutputCategoryStatsToConsole(con, category);
111 }
112 }
113 }
114 else
115 {
116 // Legacy
117 con.Output(SimExtraStats.Report());
118 }
119 }
120
121 private static void OutputCategoryStatsToConsole(
122 ICommandConsole con, Dictionary<string, Dictionary<string, Stat>> category)
123 {
124 foreach (var container in category.Values)
125 {
126 foreach (Stat stat in container.Values)
127 {
128 con.Output(stat.ToConsoleString());
129 }
130 }
131 }
132
133 /// <summary> 43 /// <summary>
134 /// Start collecting statistics related to assets. 44 /// Start collecting statistics related to assets.
135 /// Should only be called once. 45 /// Should only be called once.
@@ -151,275 +61,5 @@ namespace OpenSim.Framework.Monitoring
151 61
152 return userStats; 62 return userStats;
153 } 63 }
154
155 /// <summary>
156 /// Registers a statistic.
157 /// </summary>
158 /// <param name='stat'></param>
159 /// <returns></returns>
160 public static bool RegisterStat(Stat stat)
161 {
162 Dictionary<string, Dictionary<string, Stat>> category = null, newCategory;
163 Dictionary<string, Stat> container = null, newContainer;
164
165 lock (RegisteredStats)
166 {
167 // Stat name is not unique across category/container/shortname key.
168 // XXX: For now just return false. This is to avoid problems in regression tests where all tests
169 // in a class are run in the same instance of the VM.
170 if (TryGetStat(stat, out category, out container))
171 return false;
172
173 // We take a copy-on-write approach here of replacing dictionaries when keys are added or removed.
174 // This means that we don't need to lock or copy them on iteration, which will be a much more
175 // common operation after startup.
176 if (container != null)
177 newContainer = new Dictionary<string, Stat>(container);
178 else
179 newContainer = new Dictionary<string, Stat>();
180
181 if (category != null)
182 newCategory = new Dictionary<string, Dictionary<string, Stat>>(category);
183 else
184 newCategory = new Dictionary<string, Dictionary<string, Stat>>();
185
186 newContainer[stat.ShortName] = stat;
187 newCategory[stat.Container] = newContainer;
188 RegisteredStats[stat.Category] = newCategory;
189 }
190
191 return true;
192 }
193
194 /// <summary>
195 /// Deregister a statistic
196 /// </summary>>
197 /// <param name='stat'></param>
198 /// <returns></returns
199 public static bool DeregisterStat(Stat stat)
200 {
201 Dictionary<string, Dictionary<string, Stat>> category = null, newCategory;
202 Dictionary<string, Stat> container = null, newContainer;
203
204 lock (RegisteredStats)
205 {
206 if (!TryGetStat(stat, out category, out container))
207 return false;
208
209 newContainer = new Dictionary<string, Stat>(container);
210 newContainer.Remove(stat.ShortName);
211
212 newCategory = new Dictionary<string, Dictionary<string, Stat>>(category);
213 newCategory.Remove(stat.Container);
214
215 newCategory[stat.Container] = newContainer;
216 RegisteredStats[stat.Category] = newCategory;
217
218 return true;
219 }
220 }
221
222 public static bool TryGetStats(string category, out Dictionary<string, Dictionary<string, Stat>> stats)
223 {
224 return RegisteredStats.TryGetValue(category, out stats);
225 }
226
227 public static bool TryGetStat(
228 Stat stat,
229 out Dictionary<string, Dictionary<string, Stat>> category,
230 out Dictionary<string, Stat> container)
231 {
232 category = null;
233 container = null;
234
235 lock (RegisteredStats)
236 {
237 if (RegisteredStats.TryGetValue(stat.Category, out category))
238 {
239 if (category.TryGetValue(stat.Container, out container))
240 {
241 if (container.ContainsKey(stat.ShortName))
242 return true;
243 }
244 }
245 }
246
247 return false;
248 }
249 }
250
251 /// <summary>
252 /// Stat type.
253 /// </summary>
254 /// <remarks>
255 /// A push stat is one which is continually updated and so it's value can simply by read.
256 /// A pull stat is one where reading the value triggers a collection method - the stat is not continually updated.
257 /// </remarks>
258 public enum StatType
259 {
260 Push,
261 Pull
262 }
263
264 /// <summary>
265 /// Verbosity of stat.
266 /// </summary>
267 /// <remarks>
268 /// Info will always be displayed.
269 /// </remarks>
270 public enum StatVerbosity
271 {
272 Debug,
273 Info
274 }
275
276 /// <summary>
277 /// Holds individual static details
278 /// </summary>
279 public class Stat
280 {
281 /// <summary>
282 /// Category of this stat (e.g. cache, scene, etc).
283 /// </summary>
284 public string Category { get; private set; }
285
286 /// <summary>
287 /// Containing name for this stat.
288 /// FIXME: In the case of a scene, this is currently the scene name (though this leaves
289 /// us with a to-be-resolved problem of non-unique region names).
290 /// </summary>
291 /// <value>
292 /// The container.
293 /// </value>
294 public string Container { get; private set; }
295
296 public StatType StatType { get; private set; }
297
298 /// <summary>
299 /// Action used to update this stat when the value is requested if it's a pull type.
300 /// </summary>
301 public Action<Stat> PullAction { get; private set; }
302
303 public StatVerbosity Verbosity { get; private set; }
304 public string ShortName { get; private set; }
305 public string Name { get; private set; }
306 public string Description { get; private set; }
307 public virtual string UnitName { get; private set; }
308
309 public virtual double Value
310 {
311 get
312 {
313 // Asking for an update here means that the updater cannot access this value without infinite recursion.
314 // XXX: A slightly messy but simple solution may be to flick a flag so we can tell if this is being
315 // called by the pull action and just return the value.
316 if (StatType == StatType.Pull)
317 PullAction(this);
318
319 return m_value;
320 }
321
322 set
323 {
324 m_value = value;
325 }
326 }
327
328 private double m_value;
329
330 /// <summary>
331 /// Constructor
332 /// </summary>
333 /// <param name='shortName'>Short name for the stat. Must not contain spaces. e.g. "LongFrames"</param>
334 /// <param name='name'>Human readable name for the stat. e.g. "Long frames"</param>
335 /// <param name='description'>Description of stat</param>
336 /// <param name='unitName'>
337 /// Unit name for the stat. Should be preceeded by a space if the unit name isn't normally appeneded immediately to the value.
338 /// e.g. " frames"
339 /// </param>
340 /// <param name='category'>Category under which this stat should appear, e.g. "scene". Do not capitalize.</param>
341 /// <param name='container'>Entity to which this stat relates. e.g. scene name if this is a per scene stat.</param>
342 /// <param name='type'>Push or pull</param>
343 /// <param name='pullAction'>Pull stats need an action to update the stat on request. Push stats should set null here.</param>
344 /// <param name='verbosity'>Verbosity of stat. Controls whether it will appear in short stat display or only full display.</param>
345 public Stat(
346 string shortName,
347 string name,
348 string description,
349 string unitName,
350 string category,
351 string container,
352 StatType type,
353 Action<Stat> pullAction,
354 StatVerbosity verbosity)
355 {
356 if (StatsManager.SubCommands.Contains(category))
357 throw new Exception(
358 string.Format("Stat cannot be in category '{0}' since this is reserved for a subcommand", category));
359
360 ShortName = shortName;
361 Name = name;
362 Description = description;
363 UnitName = unitName;
364 Category = category;
365 Container = container;
366 StatType = type;
367
368 if (StatType == StatType.Push && pullAction != null)
369 throw new Exception("A push stat cannot have a pull action");
370 else
371 PullAction = pullAction;
372
373 Verbosity = verbosity;
374 }
375
376 public virtual string ToConsoleString()
377 {
378 return string.Format(
379 "{0}.{1}.{2} : {3}{4}", Category, Container, ShortName, Value, UnitName);
380 }
381 }
382
383 public class PercentageStat : Stat
384 {
385 public int Antecedent { get; set; }
386 public int Consequent { get; set; }
387
388 public override double Value
389 {
390 get
391 {
392 int c = Consequent;
393
394 // Avoid any chance of a multi-threaded divide-by-zero
395 if (c == 0)
396 return 0;
397
398 return (double)Antecedent / c * 100;
399 }
400
401 set
402 {
403 throw new Exception("Cannot set value on a PercentageStat");
404 }
405 }
406
407 public PercentageStat(
408 string shortName,
409 string name,
410 string description,
411 string category,
412 string container,
413 StatType type,
414 Action<Stat> pullAction,
415 StatVerbosity verbosity)
416 : base(shortName, name, description, "%", category, container, type, pullAction, verbosity) {}
417
418 public override string ToConsoleString()
419 {
420 return string.Format(
421 "{0}.{1}.{2} : {3:0.##}{4} ({5}/{6})",
422 Category, Container, ShortName, Value, UnitName, Antecedent, Consequent);
423 }
424 } 64 }
425} \ No newline at end of file 65} \ No newline at end of file
diff --git a/OpenSim/Framework/Monitoring/Watchdog.cs b/OpenSim/Framework/Monitoring/Watchdog.cs
index 28d6d5c..b709baa 100644
--- a/OpenSim/Framework/Monitoring/Watchdog.cs
+++ b/OpenSim/Framework/Monitoring/Watchdog.cs
@@ -89,17 +89,6 @@ namespace OpenSim.Framework.Monitoring
89 FirstTick = Environment.TickCount & Int32.MaxValue; 89 FirstTick = Environment.TickCount & Int32.MaxValue;
90 LastTick = FirstTick; 90 LastTick = FirstTick;
91 } 91 }
92
93 public ThreadWatchdogInfo(ThreadWatchdogInfo previousTwi)
94 {
95 Thread = previousTwi.Thread;
96 FirstTick = previousTwi.FirstTick;
97 LastTick = previousTwi.LastTick;
98 Timeout = previousTwi.Timeout;
99 IsTimedOut = previousTwi.IsTimedOut;
100 AlarmIfTimeout = previousTwi.AlarmIfTimeout;
101 AlarmMethod = previousTwi.AlarmMethod;
102 }
103 } 92 }
104 93
105 /// <summary> 94 /// <summary>
@@ -231,25 +220,7 @@ namespace OpenSim.Framework.Monitoring
231 private static bool RemoveThread(int threadID) 220 private static bool RemoveThread(int threadID)
232 { 221 {
233 lock (m_threads) 222 lock (m_threads)
234 { 223 return m_threads.Remove(threadID);
235 ThreadWatchdogInfo twi;
236 if (m_threads.TryGetValue(threadID, out twi))
237 {
238 m_log.DebugFormat(
239 "[WATCHDOG]: Removing thread {0}, ID {1}", twi.Thread.Name, twi.Thread.ManagedThreadId);
240
241 m_threads.Remove(threadID);
242
243 return true;
244 }
245 else
246 {
247 m_log.WarnFormat(
248 "[WATCHDOG]: Requested to remove thread with ID {0} but this is not being monitored", threadID);
249
250 return false;
251 }
252 }
253 } 224 }
254 225
255 public static bool AbortThread(int threadID) 226 public static bool AbortThread(int threadID)
@@ -364,9 +335,7 @@ namespace OpenSim.Framework.Monitoring
364 if (callbackInfos == null) 335 if (callbackInfos == null)
365 callbackInfos = new List<ThreadWatchdogInfo>(); 336 callbackInfos = new List<ThreadWatchdogInfo>();
366 337
367 // Send a copy of the watchdog info to prevent race conditions where the watchdog 338 callbackInfos.Add(threadInfo);
368 // thread updates the monitoring info after an alarm has been sent out.
369 callbackInfos.Add(new ThreadWatchdogInfo(threadInfo));
370 } 339 }
371 } 340 }
372 } 341 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs b/OpenSim/Framework/PacketPool.cs
index 9f22fb4..41d17c5 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs
+++ b/OpenSim/Framework/PacketPool.cs
@@ -31,10 +31,10 @@ using System.Reflection;
31using OpenMetaverse; 31using OpenMetaverse;
32using OpenMetaverse.Packets; 32using OpenMetaverse.Packets;
33using log4net; 33using log4net;
34using OpenSim.Framework.Monitoring;
35 34
36namespace OpenSim.Region.ClientStack.LindenUDP 35namespace OpenSim.Framework
37{ 36{
37
38 public sealed class PacketPool 38 public sealed class PacketPool
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);
@@ -44,32 +44,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
44 private bool packetPoolEnabled = true; 44 private bool packetPoolEnabled = true;
45 private bool dataBlockPoolEnabled = true; 45 private bool dataBlockPoolEnabled = true;
46 46
47 private PercentageStat m_packetsReusedStat = new PercentageStat(
48 "PacketsReused",
49 "Packets reused",
50 "Number of packets reused out of all requests to the packet pool",
51 "clientstack",
52 "packetpool",
53 StatType.Push,
54 null,
55 StatVerbosity.Debug);
56
57 private PercentageStat m_blocksReusedStat = new PercentageStat(
58 "PacketDataBlocksReused",
59 "Packet data blocks reused",
60 "Number of data blocks reused out of all requests to the packet pool",
61 "clientstack",
62 "packetpool",
63 StatType.Push,
64 null,
65 StatVerbosity.Debug);
66
67 /// <summary>
68 /// Pool of packets available for reuse.
69 /// </summary>
70 private readonly Dictionary<PacketType, Stack<Packet>> pool = new Dictionary<PacketType, Stack<Packet>>(); 47 private readonly Dictionary<PacketType, Stack<Packet>> pool = new Dictionary<PacketType, Stack<Packet>>();
71 48
72 private static Dictionary<Type, Stack<Object>> DataBlocks = new Dictionary<Type, Stack<Object>>(); 49 private static Dictionary<Type, Stack<Object>> DataBlocks =
50 new Dictionary<Type, Stack<Object>>();
51
52 static PacketPool()
53 {
54 }
73 55
74 public static PacketPool Instance 56 public static PacketPool Instance
75 { 57 {
@@ -88,45 +70,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
88 get { return dataBlockPoolEnabled; } 70 get { return dataBlockPoolEnabled; }
89 } 71 }
90 72
91 private PacketPool()
92 {
93 StatsManager.RegisterStat(m_packetsReusedStat);
94 StatsManager.RegisterStat(m_blocksReusedStat);
95
96 StatsManager.RegisterStat(
97 new Stat(
98 "PacketsPoolCount",
99 "Objects within the packet pool",
100 "The number of objects currently stored within the packet pool",
101 "",
102 "clientstack",
103 "packetpool",
104 StatType.Pull,
105 stat => { lock (pool) { stat.Value = pool.Count; } },
106 StatVerbosity.Debug));
107
108 StatsManager.RegisterStat(
109 new Stat(
110 "PacketDataBlocksPoolCount",
111 "Objects within the packet data block pool",
112 "The number of objects currently stored within the packet data block pool",
113 "",
114 "clientstack",
115 "packetpool",
116 StatType.Pull,
117 stat => { lock (DataBlocks) { stat.Value = DataBlocks.Count; } },
118 StatVerbosity.Debug));
119 }
120
121 /// <summary>
122 /// Gets a packet of the given type.
123 /// </summary>
124 /// <param name='type'></param>
125 /// <returns>Guaranteed to always return a packet, whether from the pool or newly constructed.</returns>
126 public Packet GetPacket(PacketType type) 73 public Packet GetPacket(PacketType type)
127 { 74 {
128 m_packetsReusedStat.Consequent++;
129
130 Packet packet; 75 Packet packet;
131 76
132 if (!packetPoolEnabled) 77 if (!packetPoolEnabled)
@@ -136,19 +81,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
136 { 81 {
137 if (!pool.ContainsKey(type) || pool[type] == null || (pool[type]).Count == 0) 82 if (!pool.ContainsKey(type) || pool[type] == null || (pool[type]).Count == 0)
138 { 83 {
139// m_log.DebugFormat("[PACKETPOOL]: Building {0} packet", type);
140
141 // Creating a new packet if we cannot reuse an old package 84 // Creating a new packet if we cannot reuse an old package
142 packet = Packet.BuildPacket(type); 85 packet = Packet.BuildPacket(type);
143 } 86 }
144 else 87 else
145 { 88 {
146// m_log.DebugFormat("[PACKETPOOL]: Pulling {0} packet", type);
147
148 // Recycle old packages 89 // Recycle old packages
149 m_packetsReusedStat.Antecedent++; 90 packet = (pool[type]).Pop();
150
151 packet = pool[type].Pop();
152 } 91 }
153 } 92 }
154 93
@@ -197,7 +136,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
197 { 136 {
198 PacketType type = GetType(bytes); 137 PacketType type = GetType(bytes);
199 138
200// Array.Clear(zeroBuffer, 0, zeroBuffer.Length); 139 Array.Clear(zeroBuffer, 0, zeroBuffer.Length);
201 140
202 int i = 0; 141 int i = 0;
203 Packet packet = GetPacket(type); 142 Packet packet = GetPacket(type);
@@ -244,7 +183,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
244 switch (packet.Type) 183 switch (packet.Type)
245 { 184 {
246 // List pooling packets here 185 // List pooling packets here
247 case PacketType.AgentUpdate:
248 case PacketType.PacketAck: 186 case PacketType.PacketAck:
249 case PacketType.ObjectUpdate: 187 case PacketType.ObjectUpdate:
250 case PacketType.ImprovedTerseObjectUpdate: 188 case PacketType.ImprovedTerseObjectUpdate:
@@ -259,9 +197,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
259 197
260 if ((pool[type]).Count < 50) 198 if ((pool[type]).Count < 50)
261 { 199 {
262// m_log.DebugFormat("[PACKETPOOL]: Pushing {0} packet", type); 200 (pool[type]).Push(packet);
263
264 pool[type].Push(packet);
265 } 201 }
266 } 202 }
267 break; 203 break;
@@ -273,21 +209,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
273 } 209 }
274 } 210 }
275 211
276 public T GetDataBlock<T>() where T: new() 212 public static T GetDataBlock<T>() where T: new()
277 { 213 {
278 lock (DataBlocks) 214 lock (DataBlocks)
279 { 215 {
280 m_blocksReusedStat.Consequent++;
281
282 Stack<Object> s; 216 Stack<Object> s;
283 217
284 if (DataBlocks.TryGetValue(typeof(T), out s)) 218 if (DataBlocks.TryGetValue(typeof(T), out s))
285 { 219 {
286 if (s.Count > 0) 220 if (s.Count > 0)
287 {
288 m_blocksReusedStat.Antecedent++;
289 return (T)s.Pop(); 221 return (T)s.Pop();
290 }
291 } 222 }
292 else 223 else
293 { 224 {
@@ -298,7 +229,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
298 } 229 }
299 } 230 }
300 231
301 public void ReturnDataBlock<T>(T block) where T: new() 232 public static void ReturnDataBlock<T>(T block) where T: new()
302 { 233 {
303 if (block == null) 234 if (block == null)
304 return; 235 return;
@@ -313,4 +244,4 @@ namespace OpenSim.Region.ClientStack.LindenUDP
313 } 244 }
314 } 245 }
315 } 246 }
316} \ No newline at end of file 247}
diff --git a/OpenSim/Framework/Pool.cs b/OpenSim/Framework/Pool.cs
deleted file mode 100644
index 5484f5c..0000000
--- a/OpenSim/Framework/Pool.cs
+++ /dev/null
@@ -1,91 +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;
30
31namespace OpenSim.Framework
32{
33 /// <summary>
34 /// Naive pool implementation.
35 /// </summary>
36 /// <remarks>
37 /// Currently assumes that objects are in a useable state when returned.
38 /// </remarks>
39 public class Pool<T>
40 {
41 /// <summary>
42 /// Number of objects in the pool.
43 /// </summary>
44 public int Count
45 {
46 get
47 {
48 lock (m_pool)
49 return m_pool.Count;
50 }
51 }
52
53 private Stack<T> m_pool;
54
55 /// <summary>
56 /// Maximum pool size. Beyond this, any returned objects are not pooled.
57 /// </summary>
58 private int m_maxPoolSize;
59
60 private Func<T> m_createFunction;
61
62 public Pool(Func<T> createFunction, int maxSize)
63 {
64 m_maxPoolSize = maxSize;
65 m_createFunction = createFunction;
66 m_pool = new Stack<T>(m_maxPoolSize);
67 }
68
69 public T GetObject()
70 {
71 lock (m_pool)
72 {
73 if (m_pool.Count > 0)
74 return m_pool.Pop();
75 else
76 return m_createFunction();
77 }
78 }
79
80 public void ReturnObject(T obj)
81 {
82 lock (m_pool)
83 {
84 if (m_pool.Count >= m_maxPoolSize)
85 return;
86 else
87 m_pool.Push(obj);
88 }
89 }
90 }
91} \ No newline at end of file
diff --git a/OpenSim/Framework/RegionFlags.cs b/OpenSim/Framework/RegionFlags.cs
deleted file mode 100644
index a3089b0..0000000
--- a/OpenSim/Framework/RegionFlags.cs
+++ /dev/null
@@ -1,53 +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;
29
30namespace OpenSim.Framework
31{
32 /// <summary>
33 /// Region flags used internally by OpenSimulator to store installation specific information about regions.
34 /// </summary>
35 /// <remarks>
36 /// Don't confuse with OpenMetaverse.RegionFlags which are client facing flags (i.e. they go over the wire).
37 /// Returned by IGridService.GetRegionFlags()
38 /// </remarks>
39 [Flags]
40 public enum RegionFlags : int
41 {
42 DefaultRegion = 1, // Used for new Rez. Random if multiple defined
43 FallbackRegion = 2, // Regions we redirect to when the destination is down
44 RegionOnline = 4, // Set when a region comes online, unset when it unregisters and DeleteOnUnregister is false
45 NoDirectLogin = 8, // Region unavailable for direct logins (by name)
46 Persistent = 16, // Don't remove on unregister
47 LockedOut = 32, // Don't allow registration
48 NoMove = 64, // Don't allow moving this region
49 Reservation = 128, // This is an inactive reservation
50 Authenticate = 256, // Require authentication
51 Hyperlink = 512 // Record represents a HG link
52 }
53} \ No newline at end of file
diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs
index e7bed6a..4bde7be 100644
--- a/OpenSim/Framework/RegionInfo.cs
+++ b/OpenSim/Framework/RegionInfo.cs
@@ -122,13 +122,10 @@ namespace OpenSim.Framework
122 public UUID lastMapUUID = UUID.Zero; 122 public UUID lastMapUUID = UUID.Zero;
123 public string lastMapRefresh = "0"; 123 public string lastMapRefresh = "0";
124 124
125 private float m_nonphysPrimMin = 0;
126 private int m_nonphysPrimMax = 0; 125 private int m_nonphysPrimMax = 0;
127 private float m_physPrimMin = 0;
128 private int m_physPrimMax = 0; 126 private int m_physPrimMax = 0;
129 private bool m_clampPrimSize = false; 127 private bool m_clampPrimSize = false;
130 private int m_objectCapacity = 0; 128 private int m_objectCapacity = 0;
131 private int m_linksetCapacity = 0;
132 private int m_agentCapacity = 0; 129 private int m_agentCapacity = 0;
133 private string m_regionType = String.Empty; 130 private string m_regionType = String.Empty;
134 private RegionLightShareData m_windlight = new RegionLightShareData(); 131 private RegionLightShareData m_windlight = new RegionLightShareData();
@@ -290,21 +287,11 @@ namespace OpenSim.Framework
290 set { m_windlight = value; } 287 set { m_windlight = value; }
291 } 288 }
292 289
293 public float NonphysPrimMin
294 {
295 get { return m_nonphysPrimMin; }
296 }
297
298 public int NonphysPrimMax 290 public int NonphysPrimMax
299 { 291 {
300 get { return m_nonphysPrimMax; } 292 get { return m_nonphysPrimMax; }
301 } 293 }
302 294
303 public float PhysPrimMin
304 {
305 get { return m_physPrimMin; }
306 }
307
308 public int PhysPrimMax 295 public int PhysPrimMax
309 { 296 {
310 get { return m_physPrimMax; } 297 get { return m_physPrimMax; }
@@ -320,11 +307,6 @@ namespace OpenSim.Framework
320 get { return m_objectCapacity; } 307 get { return m_objectCapacity; }
321 } 308 }
322 309
323 public int LinksetCapacity
324 {
325 get { return m_linksetCapacity; }
326 }
327
328 public int AgentCapacity 310 public int AgentCapacity
329 { 311 {
330 get { return m_agentCapacity; } 312 get { return m_agentCapacity; }
@@ -643,31 +625,16 @@ namespace OpenSim.Framework
643 m_regionType = config.GetString("RegionType", String.Empty); 625 m_regionType = config.GetString("RegionType", String.Empty);
644 allKeys.Remove("RegionType"); 626 allKeys.Remove("RegionType");
645 627
646 #region Prim stuff 628 // Prim stuff
647 629 //
648 m_nonphysPrimMin = config.GetFloat("NonPhysicalPrimMin", 0); 630 m_nonphysPrimMax = config.GetInt("NonphysicalPrimMax", 0);
649 allKeys.Remove("NonPhysicalPrimMin"); 631 allKeys.Remove("NonphysicalPrimMax");
650
651 m_nonphysPrimMax = config.GetInt("NonPhysicalPrimMax", 0);
652 allKeys.Remove("NonPhysicalPrimMax");
653
654 m_physPrimMin = config.GetFloat("PhysicalPrimMin", 0);
655 allKeys.Remove("PhysicalPrimMin");
656
657 m_physPrimMax = config.GetInt("PhysicalPrimMax", 0); 632 m_physPrimMax = config.GetInt("PhysicalPrimMax", 0);
658 allKeys.Remove("PhysicalPrimMax"); 633 allKeys.Remove("PhysicalPrimMax");
659
660 m_clampPrimSize = config.GetBoolean("ClampPrimSize", false); 634 m_clampPrimSize = config.GetBoolean("ClampPrimSize", false);
661 allKeys.Remove("ClampPrimSize"); 635 allKeys.Remove("ClampPrimSize");
662
663 m_objectCapacity = config.GetInt("MaxPrims", 15000); 636 m_objectCapacity = config.GetInt("MaxPrims", 15000);
664 allKeys.Remove("MaxPrims"); 637 allKeys.Remove("MaxPrims");
665
666 m_linksetCapacity = config.GetInt("LinksetPrims", 0);
667 allKeys.Remove("LinksetPrims");
668
669 #endregion
670
671 m_agentCapacity = config.GetInt("MaxAgents", 100); 638 m_agentCapacity = config.GetInt("MaxAgents", 100);
672 allKeys.Remove("MaxAgents"); 639 allKeys.Remove("MaxAgents");
673 640
@@ -706,27 +673,16 @@ namespace OpenSim.Framework
706 673
707 config.Set("ExternalHostName", m_externalHostName); 674 config.Set("ExternalHostName", m_externalHostName);
708 675
709 if (m_nonphysPrimMin > 0) 676 if (m_nonphysPrimMax != 0)
710 config.Set("NonphysicalPrimMax", m_nonphysPrimMin);
711
712 if (m_nonphysPrimMax > 0)
713 config.Set("NonphysicalPrimMax", m_nonphysPrimMax); 677 config.Set("NonphysicalPrimMax", m_nonphysPrimMax);
714 678 if (m_physPrimMax != 0)
715 if (m_physPrimMin > 0)
716 config.Set("PhysicalPrimMax", m_physPrimMin);
717
718 if (m_physPrimMax > 0)
719 config.Set("PhysicalPrimMax", m_physPrimMax); 679 config.Set("PhysicalPrimMax", m_physPrimMax);
720
721 config.Set("ClampPrimSize", m_clampPrimSize.ToString()); 680 config.Set("ClampPrimSize", m_clampPrimSize.ToString());
722 681
723 if (m_objectCapacity > 0) 682 if (m_objectCapacity != 0)
724 config.Set("MaxPrims", m_objectCapacity); 683 config.Set("MaxPrims", m_objectCapacity);
725 684
726 if (m_linksetCapacity > 0) 685 if (m_agentCapacity != 0)
727 config.Set("LinksetPrims", m_linksetCapacity);
728
729 if (m_agentCapacity > 0)
730 config.Set("MaxAgents", m_agentCapacity); 686 config.Set("MaxAgents", m_agentCapacity);
731 687
732 if (ScopeID != UUID.Zero) 688 if (ScopeID != UUID.Zero)
@@ -803,15 +759,9 @@ namespace OpenSim.Framework
803 configMember.addConfigurationOption("lastmap_refresh", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, 759 configMember.addConfigurationOption("lastmap_refresh", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY,
804 "Last Map Refresh", Util.UnixTimeSinceEpoch().ToString(), true); 760 "Last Map Refresh", Util.UnixTimeSinceEpoch().ToString(), true);
805 761
806 configMember.addConfigurationOption("nonphysical_prim_min", ConfigurationOption.ConfigurationTypes.TYPE_FLOAT,
807 "Minimum size for nonphysical prims", m_nonphysPrimMin.ToString(), true);
808
809 configMember.addConfigurationOption("nonphysical_prim_max", ConfigurationOption.ConfigurationTypes.TYPE_INT32, 762 configMember.addConfigurationOption("nonphysical_prim_max", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
810 "Maximum size for nonphysical prims", m_nonphysPrimMax.ToString(), true); 763 "Maximum size for nonphysical prims", m_nonphysPrimMax.ToString(), true);
811 764
812 configMember.addConfigurationOption("physical_prim_min", ConfigurationOption.ConfigurationTypes.TYPE_FLOAT,
813 "Minimum size for nonphysical prims", m_physPrimMin.ToString(), true);
814
815 configMember.addConfigurationOption("physical_prim_max", ConfigurationOption.ConfigurationTypes.TYPE_INT32, 765 configMember.addConfigurationOption("physical_prim_max", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
816 "Maximum size for physical prims", m_physPrimMax.ToString(), true); 766 "Maximum size for physical prims", m_physPrimMax.ToString(), true);
817 767
@@ -821,9 +771,6 @@ namespace OpenSim.Framework
821 configMember.addConfigurationOption("object_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32, 771 configMember.addConfigurationOption("object_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
822 "Max objects this sim will hold", m_objectCapacity.ToString(), true); 772 "Max objects this sim will hold", m_objectCapacity.ToString(), true);
823 773
824 configMember.addConfigurationOption("linkset_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
825 "Max prims an object will hold", m_linksetCapacity.ToString(), true);
826
827 configMember.addConfigurationOption("agent_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32, 774 configMember.addConfigurationOption("agent_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
828 "Max avatars this sim will hold", m_agentCapacity.ToString(), true); 775 "Max avatars this sim will hold", m_agentCapacity.ToString(), true);
829 776
@@ -945,9 +892,6 @@ namespace OpenSim.Framework
945 case "object_capacity": 892 case "object_capacity":
946 m_objectCapacity = (int)configuration_result; 893 m_objectCapacity = (int)configuration_result;
947 break; 894 break;
948 case "linkset_capacity":
949 m_linksetCapacity = (int)configuration_result;
950 break;
951 case "agent_capacity": 895 case "agent_capacity":
952 m_agentCapacity = (int)configuration_result; 896 m_agentCapacity = (int)configuration_result;
953 break; 897 break;
diff --git a/OpenSim/Framework/Serialization/ArchiveConstants.cs b/OpenSim/Framework/Serialization/ArchiveConstants.cs
index 48f1c4f..2c5e001 100644
--- a/OpenSim/Framework/Serialization/ArchiveConstants.cs
+++ b/OpenSim/Framework/Serialization/ArchiveConstants.cs
@@ -53,11 +53,6 @@ namespace OpenSim.Framework.Serialization
53 public const string INVENTORY_PATH = "inventory/"; 53 public const string INVENTORY_PATH = "inventory/";
54 54
55 /// <value> 55 /// <value>
56 /// Path for regions in a multi-region archive
57 /// </value>
58 public const string REGIONS_PATH = "regions/";
59
60 /// <value>
61 /// Path for the prims file 56 /// Path for the prims file
62 /// </value> 57 /// </value>
63 public const string OBJECTS_PATH = "objects/"; 58 public const string OBJECTS_PATH = "objects/";
diff --git a/OpenSim/Framework/Serialization/External/OspResolver.cs b/OpenSim/Framework/Serialization/External/OspResolver.cs
index fa7160f..d31d27c 100644
--- a/OpenSim/Framework/Serialization/External/OspResolver.cs
+++ b/OpenSim/Framework/Serialization/External/OspResolver.cs
@@ -65,14 +65,9 @@ namespace OpenSim.Framework.Serialization
65 65
66 UserAccount account = userService.GetUserAccount(UUID.Zero, userId); 66 UserAccount account = userService.GetUserAccount(UUID.Zero, userId);
67 if (account != null) 67 if (account != null)
68 {
69 return MakeOspa(account.FirstName, account.LastName); 68 return MakeOspa(account.FirstName, account.LastName);
70 }
71// else 69// else
72// {
73// m_log.WarnFormat("[OSP RESOLVER]: No user account for {0}", userId); 70// m_log.WarnFormat("[OSP RESOLVER]: No user account for {0}", userId);
74// System.Console.WriteLine("[OSP RESOLVER]: No user account for {0}", userId);
75// }
76 71
77 return null; 72 return null;
78 } 73 }
@@ -84,13 +79,10 @@ namespace OpenSim.Framework.Serialization
84 /// <returns></returns> 79 /// <returns></returns>
85 public static string MakeOspa(string firstName, string lastName) 80 public static string MakeOspa(string firstName, string lastName)
86 { 81 {
87 string ospa 82// m_log.DebugFormat("[OSP RESOLVER]: Making OSPA for {0} {1}", firstName, lastName);
88 = OSPA_PREFIX + OSPA_NAME_KEY + OSPA_PAIR_SEPARATOR + firstName + OSPA_NAME_VALUE_SEPARATOR + lastName;
89
90// m_log.DebugFormat("[OSP RESOLVER]: Made OSPA {0} for {1} {2}", ospa, firstName, lastName);
91// System.Console.WriteLine("[OSP RESOLVER]: Made OSPA {0} for {1} {2}", ospa, firstName, lastName);
92 83
93 return ospa; 84 return
85 OSPA_PREFIX + OSPA_NAME_KEY + OSPA_PAIR_SEPARATOR + firstName + OSPA_NAME_VALUE_SEPARATOR + lastName;
94 } 86 }
95 87
96 /// <summary> 88 /// <summary>
diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
index 605909d..cf19002 100644
--- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs
+++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
@@ -96,6 +96,11 @@ namespace OpenSim.Framework.Servers
96 get { return m_httpServer; } 96 get { return m_httpServer; }
97 } 97 }
98 98
99 /// <summary>
100 /// Holds the non-viewer statistics collection object for this service/server
101 /// </summary>
102 protected IStatsCollector m_stats;
103
99 public BaseOpenSimServer() 104 public BaseOpenSimServer()
100 { 105 {
101 m_startuptime = DateTime.Now; 106 m_startuptime = DateTime.Now;
@@ -172,6 +177,10 @@ namespace OpenSim.Framework.Servers
172 "show info", 177 "show info",
173 "Show general information about the server", HandleShow); 178 "Show general information about the server", HandleShow);
174 179
180 m_console.Commands.AddCommand("General", false, "show stats",
181 "show stats",
182 "Show statistics", HandleShow);
183
175 m_console.Commands.AddCommand("General", false, "show threads", 184 m_console.Commands.AddCommand("General", false, "show threads",
176 "show threads", 185 "show threads",
177 "Show thread status", HandleShow); 186 "Show thread status", HandleShow);
@@ -192,19 +201,8 @@ namespace OpenSim.Framework.Servers
192 "threads show", 201 "threads show",
193 "Show thread status. Synonym for \"show threads\"", 202 "Show thread status. Synonym for \"show threads\"",
194 (string module, string[] args) => Notice(GetThreadsReport())); 203 (string module, string[] args) => Notice(GetThreadsReport()));
195
196 m_console.Commands.AddCommand("General", false, "force gc",
197 "force gc",
198 "Manually invoke runtime garbage collection. For debugging purposes",
199 HandleForceGc);
200 } 204 }
201 } 205 }
202
203 private void HandleForceGc(string module, string[] args)
204 {
205 MainConsole.Instance.Output("Manually invoking runtime garbage collection");
206 GC.Collect();
207 }
208 206
209 /// <summary> 207 /// <summary>
210 /// Should be overriden and referenced by descendents if they need to perform extra shutdown processing 208 /// Should be overriden and referenced by descendents if they need to perform extra shutdown processing
@@ -228,7 +226,12 @@ namespace OpenSim.Framework.Servers
228 { 226 {
229 StringBuilder sb = new StringBuilder("DIAGNOSTICS\n\n"); 227 StringBuilder sb = new StringBuilder("DIAGNOSTICS\n\n");
230 sb.Append(GetUptimeReport()); 228 sb.Append(GetUptimeReport());
231 sb.Append(StatsManager.SimExtraStats.Report()); 229
230 if (m_stats != null)
231 {
232 sb.Append(m_stats.Report());
233 }
234
232 sb.Append(Environment.NewLine); 235 sb.Append(Environment.NewLine);
233 sb.Append(GetThreadsReport()); 236 sb.Append(GetThreadsReport());
234 237
@@ -379,6 +382,10 @@ namespace OpenSim.Framework.Servers
379 { 382 {
380 Notice("set log level [level] - change the console logging level only. For example, off or debug."); 383 Notice("set log level [level] - change the console logging level only. For example, off or debug.");
381 Notice("show info - show server information (e.g. startup path)."); 384 Notice("show info - show server information (e.g. startup path).");
385
386 if (m_stats != null)
387 Notice("show stats - show statistical information for this server");
388
382 Notice("show threads - list tracked threads"); 389 Notice("show threads - list tracked threads");
383 Notice("show uptime - show server startup time and uptime."); 390 Notice("show uptime - show server startup time and uptime.");
384 Notice("show version - show server version."); 391 Notice("show version - show server version.");
@@ -402,6 +409,11 @@ namespace OpenSim.Framework.Servers
402 ShowInfo(); 409 ShowInfo();
403 break; 410 break;
404 411
412 case "stats":
413 if (m_stats != null)
414 Notice(m_stats.Report());
415 break;
416
405 case "threads": 417 case "threads":
406 Notice(GetThreadsReport()); 418 Notice(GetThreadsReport());
407 break; 419 break;
@@ -592,7 +604,8 @@ namespace OpenSim.Framework.Servers
592 604
593 public string osSecret { 605 public string osSecret {
594 // Secret uuid for the simulator 606 // Secret uuid for the simulator
595 get { return m_osSecret; } 607 get { return m_osSecret; }
608
596 } 609 }
597 610
598 public string StatReport(IOSHttpRequest httpRequest) 611 public string StatReport(IOSHttpRequest httpRequest)
@@ -600,11 +613,11 @@ namespace OpenSim.Framework.Servers
600 // If we catch a request for "callback", wrap the response in the value for jsonp 613 // If we catch a request for "callback", wrap the response in the value for jsonp
601 if (httpRequest.Query.ContainsKey("callback")) 614 if (httpRequest.Query.ContainsKey("callback"))
602 { 615 {
603 return httpRequest.Query["callback"].ToString() + "(" + StatsManager.SimExtraStats.XReport((DateTime.Now - m_startuptime).ToString() , m_version) + ");"; 616 return httpRequest.Query["callback"].ToString() + "(" + m_stats.XReport((DateTime.Now - m_startuptime).ToString() , m_version) + ");";
604 } 617 }
605 else 618 else
606 { 619 {
607 return StatsManager.SimExtraStats.XReport((DateTime.Now - m_startuptime).ToString() , m_version); 620 return m_stats.XReport((DateTime.Now - m_startuptime).ToString() , m_version);
608 } 621 }
609 } 622 }
610 623
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
index 3198891..788a0b9 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
@@ -54,23 +54,8 @@ namespace OpenSim.Framework.Servers.HttpServer
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55 private HttpServerLogWriter httpserverlog = new HttpServerLogWriter(); 55 private HttpServerLogWriter httpserverlog = new HttpServerLogWriter();
56 56
57 /// <summary>
58 /// Gets or sets the debug level.
59 /// </summary>
60 /// <value>
61 /// See MainServer.DebugLevel.
62 /// </value>
63 public int DebugLevel { get; set; } 57 public int DebugLevel { get; set; }
64 58
65 /// <summary>
66 /// Request number for diagnostic purposes.
67 /// </summary>
68 /// <remarks>
69 /// This is an internal number. In some debug situations an external number may also be supplied in the
70 /// opensim-request-id header but we are not currently logging this.
71 /// </remarks>
72 public int RequestNumber { get; private set; }
73
74 private volatile int NotSocketErrors = 0; 59 private volatile int NotSocketErrors = 0;
75 public volatile bool HTTPDRunning = false; 60 public volatile bool HTTPDRunning = false;
76 61
@@ -82,7 +67,7 @@ namespace OpenSim.Framework.Servers.HttpServer
82 protected Dictionary<string, LLSDMethod> m_llsdHandlers = new Dictionary<string, LLSDMethod>(); 67 protected Dictionary<string, LLSDMethod> m_llsdHandlers = new Dictionary<string, LLSDMethod>();
83 protected Dictionary<string, IRequestHandler> m_streamHandlers = new Dictionary<string, IRequestHandler>(); 68 protected Dictionary<string, IRequestHandler> m_streamHandlers = new Dictionary<string, IRequestHandler>();
84 protected Dictionary<string, GenericHTTPMethod> m_HTTPHandlers = new Dictionary<string, GenericHTTPMethod>(); 69 protected Dictionary<string, GenericHTTPMethod> m_HTTPHandlers = new Dictionary<string, GenericHTTPMethod>();
85// protected Dictionary<string, IHttpAgentHandler> m_agentHandlers = new Dictionary<string, IHttpAgentHandler>(); 70 protected Dictionary<string, IHttpAgentHandler> m_agentHandlers = new Dictionary<string, IHttpAgentHandler>();
86 protected Dictionary<string, PollServiceEventArgs> m_pollHandlers = 71 protected Dictionary<string, PollServiceEventArgs> m_pollHandlers =
87 new Dictionary<string, PollServiceEventArgs>(); 72 new Dictionary<string, PollServiceEventArgs>();
88 73
@@ -260,29 +245,29 @@ namespace OpenSim.Framework.Servers.HttpServer
260 return new List<string>(m_pollHandlers.Keys); 245 return new List<string>(m_pollHandlers.Keys);
261 } 246 }
262 247
263// // Note that the agent string is provided simply to differentiate 248 // Note that the agent string is provided simply to differentiate
264// // the handlers - it is NOT required to be an actual agent header 249 // the handlers - it is NOT required to be an actual agent header
265// // value. 250 // value.
266// public bool AddAgentHandler(string agent, IHttpAgentHandler handler) 251 public bool AddAgentHandler(string agent, IHttpAgentHandler handler)
267// { 252 {
268// lock (m_agentHandlers) 253 lock (m_agentHandlers)
269// { 254 {
270// if (!m_agentHandlers.ContainsKey(agent)) 255 if (!m_agentHandlers.ContainsKey(agent))
271// { 256 {
272// m_agentHandlers.Add(agent, handler); 257 m_agentHandlers.Add(agent, handler);
273// return true; 258 return true;
274// } 259 }
275// } 260 }
276// 261
277// //must already have a handler for that path so return false 262 //must already have a handler for that path so return false
278// return false; 263 return false;
279// } 264 }
280// 265
281// public List<string> GetAgentHandlerKeys() 266 public List<string> GetAgentHandlerKeys()
282// { 267 {
283// lock (m_agentHandlers) 268 lock (m_agentHandlers)
284// return new List<string>(m_agentHandlers.Keys); 269 return new List<string>(m_agentHandlers.Keys);
285// } 270 }
286 271
287 public bool AddLLSDHandler(string path, LLSDMethod handler) 272 public bool AddLLSDHandler(string path, LLSDMethod handler)
288 { 273 {
@@ -311,8 +296,6 @@ namespace OpenSim.Framework.Servers.HttpServer
311 296
312 private void OnRequest(object source, RequestEventArgs args) 297 private void OnRequest(object source, RequestEventArgs args)
313 { 298 {
314 RequestNumber++;
315
316 try 299 try
317 { 300 {
318 IHttpClientContext context = (IHttpClientContext)source; 301 IHttpClientContext context = (IHttpClientContext)source;
@@ -423,6 +406,7 @@ namespace OpenSim.Framework.Servers.HttpServer
423 string requestMethod = request.HttpMethod; 406 string requestMethod = request.HttpMethod;
424 string uriString = request.RawUrl; 407 string uriString = request.RawUrl;
425 408
409// string reqnum = "unknown";
426 int requestStartTick = Environment.TickCount; 410 int requestStartTick = Environment.TickCount;
427 411
428 // Will be adjusted later on. 412 // Will be adjusted later on.
@@ -439,22 +423,22 @@ namespace OpenSim.Framework.Servers.HttpServer
439 423
440 Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", true); 424 Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", true);
441 425
442// // This is the REST agent interface. We require an agent to properly identify 426 // This is the REST agent interface. We require an agent to properly identify
443// // itself. If the REST handler recognizes the prefix it will attempt to 427 // itself. If the REST handler recognizes the prefix it will attempt to
444// // satisfy the request. If it is not recognizable, and no damage has occurred 428 // satisfy the request. If it is not recognizable, and no damage has occurred
445// // the request can be passed through to the other handlers. This is a low 429 // the request can be passed through to the other handlers. This is a low
446// // probability event; if a request is matched it is normally expected to be 430 // probability event; if a request is matched it is normally expected to be
447// // handled 431 // handled
448// IHttpAgentHandler agentHandler; 432 IHttpAgentHandler agentHandler;
449// 433
450// if (TryGetAgentHandler(request, response, out agentHandler)) 434 if (TryGetAgentHandler(request, response, out agentHandler))
451// { 435 {
452// if (HandleAgentRequest(agentHandler, request, response)) 436 if (HandleAgentRequest(agentHandler, request, response))
453// { 437 {
454// requestEndTick = Environment.TickCount; 438 requestEndTick = Environment.TickCount;
455// return; 439 return;
456// } 440 }
457// } 441 }
458 442
459 //response.KeepAlive = true; 443 //response.KeepAlive = true;
460 response.SendChunked = false; 444 response.SendChunked = false;
@@ -466,7 +450,9 @@ namespace OpenSim.Framework.Servers.HttpServer
466 if (TryGetStreamHandler(handlerKey, out requestHandler)) 450 if (TryGetStreamHandler(handlerKey, out requestHandler))
467 { 451 {
468 if (DebugLevel >= 3) 452 if (DebugLevel >= 3)
469 LogIncomingToStreamHandler(request, requestHandler); 453 m_log.DebugFormat(
454 "[BASE HTTP SERVER]: Found stream handler for {0} {1} {2} {3}",
455 request.HttpMethod, request.Url.PathAndQuery, requestHandler.Name, requestHandler.Description);
470 456
471 response.ContentType = requestHandler.ContentType; // Lets do this defaulting before in case handler has varying content type. 457 response.ContentType = requestHandler.ContentType; // Lets do this defaulting before in case handler has varying content type.
472 458
@@ -543,8 +529,11 @@ namespace OpenSim.Framework.Servers.HttpServer
543 { 529 {
544 case null: 530 case null:
545 case "text/html": 531 case "text/html":
532
546 if (DebugLevel >= 3) 533 if (DebugLevel >= 3)
547 LogIncomingToContentTypeHandler(request); 534 m_log.DebugFormat(
535 "[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
536 request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
548 537
549 buffer = HandleHTTPRequest(request, response); 538 buffer = HandleHTTPRequest(request, response);
550 break; 539 break;
@@ -552,8 +541,11 @@ namespace OpenSim.Framework.Servers.HttpServer
552 case "application/llsd+xml": 541 case "application/llsd+xml":
553 case "application/xml+llsd": 542 case "application/xml+llsd":
554 case "application/llsd+json": 543 case "application/llsd+json":
544
555 if (DebugLevel >= 3) 545 if (DebugLevel >= 3)
556 LogIncomingToContentTypeHandler(request); 546 m_log.DebugFormat(
547 "[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
548 request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
557 549
558 buffer = HandleLLSDRequests(request, response); 550 buffer = HandleLLSDRequests(request, response);
559 break; 551 break;
@@ -572,7 +564,9 @@ namespace OpenSim.Framework.Servers.HttpServer
572 if (DoWeHaveALLSDHandler(request.RawUrl)) 564 if (DoWeHaveALLSDHandler(request.RawUrl))
573 { 565 {
574 if (DebugLevel >= 3) 566 if (DebugLevel >= 3)
575 LogIncomingToContentTypeHandler(request); 567 m_log.DebugFormat(
568 "[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
569 request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
576 570
577 buffer = HandleLLSDRequests(request, response); 571 buffer = HandleLLSDRequests(request, response);
578 } 572 }
@@ -580,14 +574,18 @@ namespace OpenSim.Framework.Servers.HttpServer
580 else if (DoWeHaveAHTTPHandler(request.RawUrl)) 574 else if (DoWeHaveAHTTPHandler(request.RawUrl))
581 { 575 {
582 if (DebugLevel >= 3) 576 if (DebugLevel >= 3)
583 LogIncomingToContentTypeHandler(request); 577 m_log.DebugFormat(
578 "[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
579 request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
584 580
585 buffer = HandleHTTPRequest(request, response); 581 buffer = HandleHTTPRequest(request, response);
586 } 582 }
587 else 583 else
588 { 584 {
589 if (DebugLevel >= 3) 585 if (DebugLevel >= 3)
590 LogIncomingToXmlRpcHandler(request); 586 m_log.DebugFormat(
587 "[BASE HTTP SERVER]: Assuming a generic XMLRPC request for {0} {1}",
588 request.HttpMethod, request.Url.PathAndQuery);
591 589
592 // generic login request. 590 // generic login request.
593 buffer = HandleXmlRpcRequests(request, response); 591 buffer = HandleXmlRpcRequests(request, response);
@@ -631,11 +629,11 @@ namespace OpenSim.Framework.Servers.HttpServer
631 } 629 }
632 catch (IOException e) 630 catch (IOException e)
633 { 631 {
634 m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.StackTrace), e); 632 m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.Message), e);
635 } 633 }
636 catch (Exception e) 634 catch (Exception e)
637 { 635 {
638 m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.StackTrace), e); 636 m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.Message), e);
639 SendHTML500(response); 637 SendHTML500(response);
640 } 638 }
641 finally 639 finally
@@ -646,93 +644,17 @@ namespace OpenSim.Framework.Servers.HttpServer
646 if (tickdiff > 3000 && (requestHandler == null || requestHandler.Name == null || requestHandler.Name != "GetTexture")) 644 if (tickdiff > 3000 && (requestHandler == null || requestHandler.Name == null || requestHandler.Name != "GetTexture"))
647 { 645 {
648 m_log.InfoFormat( 646 m_log.InfoFormat(
649 "[BASE HTTP SERVER]: Slow handling of {0} {1} {2} {3} {4} from {5} took {6}ms", 647 "[BASE HTTP SERVER]: Slow handling of {0} {1} {2} {3} from {4} took {5}ms",
650 RequestNumber,
651 requestMethod, 648 requestMethod,
652 uriString, 649 uriString,
653 requestHandler != null ? requestHandler.Name : "", 650 requestHandler != null ? requestHandler.Name : "",
654 requestHandler != null ? requestHandler.Description : "", 651 requestHandler != null ? requestHandler.Description : "",
655 request.RemoteIPEndPoint, 652 request.RemoteIPEndPoint.ToString(),
656 tickdiff);
657 }
658 else if (DebugLevel >= 4)
659 {
660 m_log.DebugFormat(
661 "[BASE HTTP SERVER]: HTTP IN {0} :{1} took {2}ms",
662 RequestNumber,
663 Port,
664 tickdiff); 653 tickdiff);
665 } 654 }
666 } 655 }
667 } 656 }
668 657
669 private void LogIncomingToStreamHandler(OSHttpRequest request, IRequestHandler requestHandler)
670 {
671 m_log.DebugFormat(
672 "[BASE HTTP SERVER]: HTTP IN {0} :{1} stream handler {2} {3} {4} {5} from {6}",
673 RequestNumber,
674 Port,
675 request.HttpMethod,
676 request.Url.PathAndQuery,
677 requestHandler.Name,
678 requestHandler.Description,
679 request.RemoteIPEndPoint);
680
681 if (DebugLevel >= 5)
682 LogIncomingInDetail(request);
683 }
684
685 private void LogIncomingToContentTypeHandler(OSHttpRequest request)
686 {
687 m_log.DebugFormat(
688 "[BASE HTTP SERVER]: HTTP IN {0} :{1} {2} content type handler {3} {4} from {5}",
689 RequestNumber,
690 Port,
691 (request.ContentType == null || request.ContentType == "") ? "not set" : request.ContentType,
692 request.HttpMethod,
693 request.Url.PathAndQuery,
694 request.RemoteIPEndPoint);
695
696 if (DebugLevel >= 5)
697 LogIncomingInDetail(request);
698 }
699
700 private void LogIncomingToXmlRpcHandler(OSHttpRequest request)
701 {
702 m_log.DebugFormat(
703 "[BASE HTTP SERVER]: HTTP IN {0} :{1} assumed generic XMLRPC request {2} {3} from {4}",
704 RequestNumber,
705 Port,
706 request.HttpMethod,
707 request.Url.PathAndQuery,
708 request.RemoteIPEndPoint);
709
710 if (DebugLevel >= 5)
711 LogIncomingInDetail(request);
712 }
713
714 private void LogIncomingInDetail(OSHttpRequest request)
715 {
716 using (StreamReader reader = new StreamReader(Util.Copy(request.InputStream), Encoding.UTF8))
717 {
718 string output;
719
720 if (DebugLevel == 5)
721 {
722 const int sampleLength = 80;
723 char[] sampleChars = new char[sampleLength];
724 reader.Read(sampleChars, 0, sampleLength);
725 output = new string(sampleChars);
726 }
727 else
728 {
729 output = reader.ReadToEnd();
730 }
731
732 m_log.DebugFormat("[BASE HTTP SERVER]: {0}...", output.Replace("\n", @"\n"));
733 }
734 }
735
736 private bool TryGetStreamHandler(string handlerKey, out IRequestHandler streamHandler) 658 private bool TryGetStreamHandler(string handlerKey, out IRequestHandler streamHandler)
737 { 659 {
738 string bestMatch = null; 660 string bestMatch = null;
@@ -825,24 +747,24 @@ namespace OpenSim.Framework.Servers.HttpServer
825 } 747 }
826 } 748 }
827 749
828// private bool TryGetAgentHandler(OSHttpRequest request, OSHttpResponse response, out IHttpAgentHandler agentHandler) 750 private bool TryGetAgentHandler(OSHttpRequest request, OSHttpResponse response, out IHttpAgentHandler agentHandler)
829// { 751 {
830// agentHandler = null; 752 agentHandler = null;
831// 753
832// lock (m_agentHandlers) 754 lock (m_agentHandlers)
833// { 755 {
834// foreach (IHttpAgentHandler handler in m_agentHandlers.Values) 756 foreach (IHttpAgentHandler handler in m_agentHandlers.Values)
835// { 757 {
836// if (handler.Match(request, response)) 758 if (handler.Match(request, response))
837// { 759 {
838// agentHandler = handler; 760 agentHandler = handler;
839// return true; 761 return true;
840// } 762 }
841// } 763 }
842// } 764 }
843// 765
844// return false; 766 return false;
845// } 767 }
846 768
847 /// <summary> 769 /// <summary>
848 /// Try all the registered xmlrpc handlers when an xmlrpc request is received. 770 /// Try all the registered xmlrpc handlers when an xmlrpc request is received.
@@ -1815,21 +1737,21 @@ namespace OpenSim.Framework.Servers.HttpServer
1815 m_pollHandlers.Remove(path); 1737 m_pollHandlers.Remove(path);
1816 } 1738 }
1817 1739
1818// public bool RemoveAgentHandler(string agent, IHttpAgentHandler handler) 1740 public bool RemoveAgentHandler(string agent, IHttpAgentHandler handler)
1819// { 1741 {
1820// lock (m_agentHandlers) 1742 lock (m_agentHandlers)
1821// { 1743 {
1822// IHttpAgentHandler foundHandler; 1744 IHttpAgentHandler foundHandler;
1823// 1745
1824// if (m_agentHandlers.TryGetValue(agent, out foundHandler) && foundHandler == handler) 1746 if (m_agentHandlers.TryGetValue(agent, out foundHandler) && foundHandler == handler)
1825// { 1747 {
1826// m_agentHandlers.Remove(agent); 1748 m_agentHandlers.Remove(agent);
1827// return true; 1749 return true;
1828// } 1750 }
1829// } 1751 }
1830// 1752
1831// return false; 1753 return false;
1832// } 1754 }
1833 1755
1834 public void RemoveXmlRPCHandler(string method) 1756 public void RemoveXmlRPCHandler(string method)
1835 { 1757 {
diff --git a/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs
index 0bd3aae..db58f6f 100644
--- a/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs
+++ b/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs
@@ -41,10 +41,10 @@ namespace OpenSim.Framework.Servers.HttpServer
41 uint Port { get; } 41 uint Port { get; }
42 bool UseSSL { get; } 42 bool UseSSL { get; }
43 43
44// // Note that the agent string is provided simply to differentiate 44 // Note that the agent string is provided simply to differentiate
45// // the handlers - it is NOT required to be an actual agent header 45 // the handlers - it is NOT required to be an actual agent header
46// // value. 46 // value.
47// bool AddAgentHandler(string agent, IHttpAgentHandler handler); 47 bool AddAgentHandler(string agent, IHttpAgentHandler handler);
48 48
49 /// <summary> 49 /// <summary>
50 /// Add a handler for an HTTP request. 50 /// Add a handler for an HTTP request.
@@ -106,13 +106,13 @@ namespace OpenSim.Framework.Servers.HttpServer
106 106
107 bool SetDefaultLLSDHandler(DefaultLLSDMethod handler); 107 bool SetDefaultLLSDHandler(DefaultLLSDMethod handler);
108 108
109// /// <summary> 109 /// <summary>
110// /// Remove the agent if it is registered. 110 /// Remove the agent if it is registered.
111// /// </summary> 111 /// </summary>
112// /// <param name="agent"></param> 112 /// <param name="agent"></param>
113// /// <param name="handler"></param> 113 /// <param name="handler"></param>
114// /// <returns></returns> 114 /// <returns></returns>
115// bool RemoveAgentHandler(string agent, IHttpAgentHandler handler); 115 bool RemoveAgentHandler(string agent, IHttpAgentHandler handler);
116 116
117 /// <summary> 117 /// <summary>
118 /// Remove an HTTP handler 118 /// Remove an HTTP handler
diff --git a/OpenSim/Framework/Servers/MainServer.cs b/OpenSim/Framework/Servers/MainServer.cs
index ae7d515..8dc0e3a 100644
--- a/OpenSim/Framework/Servers/MainServer.cs
+++ b/OpenSim/Framework/Servers/MainServer.cs
@@ -29,7 +29,6 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using System.Net; 31using System.Net;
32using System.Text;
33using log4net; 32using log4net;
34using OpenSim.Framework; 33using OpenSim.Framework;
35using OpenSim.Framework.Console; 34using OpenSim.Framework.Console;
@@ -48,12 +47,9 @@ namespace OpenSim.Framework.Servers
48 /// Control the printing of certain debug messages. 47 /// Control the printing of certain debug messages.
49 /// </summary> 48 /// </summary>
50 /// <remarks> 49 /// <remarks>
51 /// If DebugLevel >= 1 then short warnings are logged when receiving bad input data. 50 /// If DebugLevel >= 1, then short warnings are logged when receiving bad input data.
52 /// If DebugLevel >= 2 then long warnings are logged when receiving bad input data. 51 /// If DebugLevel >= 2, then long warnings are logged when receiving bad input data.
53 /// If DebugLevel >= 3 then short notices about all incoming non-poll HTTP requests are logged. 52 /// If DebugLevel >= 3, then short notices about all incoming non-poll HTTP requests are logged.
54 /// If DebugLevel >= 4 then the time taken to fulfill the request is logged.
55 /// If DebugLevel >= 5 then the start of the body of incoming non-poll HTTP requests will be logged.
56 /// If DebugLevel >= 6 then the entire body of incoming non-poll HTTP requests will be logged.
57 /// </remarks> 53 /// </remarks>
58 public static int DebugLevel 54 public static int DebugLevel
59 { 55 {
@@ -105,28 +101,17 @@ namespace OpenSim.Framework.Servers
105 get { return new Dictionary<uint, BaseHttpServer>(m_Servers); } 101 get { return new Dictionary<uint, BaseHttpServer>(m_Servers); }
106 } 102 }
107 103
104
108 public static void RegisterHttpConsoleCommands(ICommandConsole console) 105 public static void RegisterHttpConsoleCommands(ICommandConsole console)
109 { 106 {
110 console.Commands.AddCommand( 107 console.Commands.AddCommand(
111 "Comms", false, "show http-handlers", 108 "Debug", false, "debug http", "debug http [<level>]",
112 "show http-handlers", 109 "Turn on inbound non-poll http request debugging.",
113 "Show all registered http handlers", HandleShowHttpHandlersCommand); 110 "If level <= 0, then no extra logging is done.\n"
114 111 + "If level >= 1, then short warnings are logged when receiving bad input data.\n"
115 console.Commands.AddCommand( 112 + "If level >= 2, then long warnings are logged when receiving bad input data.\n"
116 "Debug", false, "debug http", "debug http <in|out|all> [<level>]", 113 + "If level >= 3, then short notices about all incoming non-poll HTTP requests are logged.\n"
117 "Turn on http request logging.", 114 + "If no level is specified then the current level is returned.",
118 "If in or all and\n"
119 + " level <= 0 then no extra logging is done.\n"
120 + " level >= 1 then short warnings are logged when receiving bad input data.\n"
121 + " level >= 2 then long warnings are logged when receiving bad input data.\n"
122 + " level >= 3 then short notices about all incoming non-poll HTTP requests are logged.\n"
123 + " level >= 4 then the time taken to fulfill the request is logged.\n"
124 + " level >= 5 then a sample from the beginning of the incoming data is logged.\n"
125 + " level >= 6 then the entire incoming data is logged.\n"
126 + " no level is specified then the current level is returned.\n\n"
127 + "If out or all and\n"
128 + " level >= 3 then short notices about all outgoing requests going through WebUtil are logged.\n"
129 + " level >= 4 then the time taken to fulfill the request is logged.\n",
130 HandleDebugHttpCommand); 115 HandleDebugHttpCommand);
131 } 116 }
132 117
@@ -134,120 +119,25 @@ namespace OpenSim.Framework.Servers
134 /// Turn on some debugging values for OpenSim. 119 /// Turn on some debugging values for OpenSim.
135 /// </summary> 120 /// </summary>
136 /// <param name="args"></param> 121 /// <param name="args"></param>
137 private static void HandleDebugHttpCommand(string module, string[] cmdparams) 122 private static void HandleDebugHttpCommand(string module, string[] args)
138 { 123 {
139 if (cmdparams.Length < 3) 124 if (args.Length == 3)
140 {
141 MainConsole.Instance.Output("Usage: debug http <in|out|all> 0..6");
142 return;
143 }
144
145 bool inReqs = false;
146 bool outReqs = false;
147 bool allReqs = false;
148
149 string subCommand = cmdparams[2];
150
151 if (subCommand.ToLower() == "in")
152 {
153 inReqs = true;
154 }
155 else if (subCommand.ToLower() == "out")
156 {
157 outReqs = true;
158 }
159 else if (subCommand.ToLower() == "all")
160 {
161 allReqs = true;
162 }
163 else
164 { 125 {
165 MainConsole.Instance.Output("You must specify in, out or all");
166 return;
167 }
168
169 if (cmdparams.Length >= 4)
170 {
171 string rawNewDebug = cmdparams[3];
172 int newDebug; 126 int newDebug;
173 127 if (int.TryParse(args[2], out newDebug))
174 if (!int.TryParse(rawNewDebug, out newDebug))
175 {
176 MainConsole.Instance.OutputFormat("{0} is not a valid debug level", rawNewDebug);
177 return;
178 }
179
180 if (newDebug < 0 || newDebug > 6)
181 {
182 MainConsole.Instance.OutputFormat("{0} is outside the valid debug level range of 0..6", newDebug);
183 return;
184 }
185
186 if (allReqs || inReqs)
187 { 128 {
188 MainServer.DebugLevel = newDebug; 129 MainServer.DebugLevel = newDebug;
189 MainConsole.Instance.OutputFormat("IN debug level set to {0}", newDebug); 130 MainConsole.Instance.OutputFormat("Debug http level set to {0}", newDebug);
190 }
191
192 if (allReqs || outReqs)
193 {
194 WebUtil.DebugLevel = newDebug;
195 MainConsole.Instance.OutputFormat("OUT debug level set to {0}", newDebug);
196 } 131 }
197 } 132 }
198 else 133 else if (args.Length == 2)
199 { 134 {
200 if (allReqs || inReqs) 135 MainConsole.Instance.OutputFormat("Current debug http level is {0}", MainServer.DebugLevel);
201 MainConsole.Instance.OutputFormat("Current IN debug level is {0}", MainServer.DebugLevel);
202
203 if (allReqs || outReqs)
204 MainConsole.Instance.OutputFormat("Current OUT debug level is {0}", WebUtil.DebugLevel);
205 } 136 }
206 } 137 else
207
208 private static void HandleShowHttpHandlersCommand(string module, string[] args)
209 {
210 if (args.Length != 2)
211 {
212 MainConsole.Instance.Output("Usage: show http-handlers");
213 return;
214 }
215
216 StringBuilder handlers = new StringBuilder();
217
218 lock (m_Servers)
219 { 138 {
220 foreach (BaseHttpServer httpServer in m_Servers.Values) 139 MainConsole.Instance.Output("Usage: debug http 0..3");
221 {
222 handlers.AppendFormat(
223 "Registered HTTP Handlers for server at {0}:{1}\n", httpServer.ListenIPAddress, httpServer.Port);
224
225 handlers.AppendFormat("* XMLRPC:\n");
226 foreach (String s in httpServer.GetXmlRpcHandlerKeys())
227 handlers.AppendFormat("\t{0}\n", s);
228
229 handlers.AppendFormat("* HTTP:\n");
230 List<String> poll = httpServer.GetPollServiceHandlerKeys();
231 foreach (String s in httpServer.GetHTTPHandlerKeys())
232 handlers.AppendFormat("\t{0} {1}\n", s, (poll.Contains(s) ? "(poll service)" : string.Empty));
233
234// handlers.AppendFormat("* Agent:\n");
235// foreach (String s in httpServer.GetAgentHandlerKeys())
236// handlers.AppendFormat("\t{0}\n", s);
237
238 handlers.AppendFormat("* LLSD:\n");
239 foreach (String s in httpServer.GetLLSDHandlerKeys())
240 handlers.AppendFormat("\t{0}\n", s);
241
242 handlers.AppendFormat("* StreamHandlers ({0}):\n", httpServer.GetStreamHandlerKeys().Count);
243 foreach (String s in httpServer.GetStreamHandlerKeys())
244 handlers.AppendFormat("\t{0}\n", s);
245
246 handlers.Append("\n");
247 }
248 } 140 }
249
250 MainConsole.Instance.Output(handlers.ToString());
251 } 141 }
252 142
253 /// <summary> 143 /// <summary>
diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs
index bb094ed..016a174 100644
--- a/OpenSim/Framework/Servers/VersionInfo.cs
+++ b/OpenSim/Framework/Servers/VersionInfo.cs
@@ -29,7 +29,7 @@ namespace OpenSim
29{ 29{
30 public class VersionInfo 30 public class VersionInfo
31 { 31 {
32 private const string VERSION_NUMBER = "0.7.5CM"; 32 private const string VERSION_NUMBER = "0.7.4CM";
33 private const Flavour VERSION_FLAVOUR = Flavour.Dev; 33 private const Flavour VERSION_FLAVOUR = Flavour.Dev;
34 34
35 public enum Flavour 35 public enum Flavour
diff --git a/OpenSim/Framework/TaskInventoryDictionary.cs b/OpenSim/Framework/TaskInventoryDictionary.cs
index 62ecbd1..4d07746 100644
--- a/OpenSim/Framework/TaskInventoryDictionary.cs
+++ b/OpenSim/Framework/TaskInventoryDictionary.cs
@@ -39,12 +39,10 @@ using OpenMetaverse;
39namespace OpenSim.Framework 39namespace OpenSim.Framework
40{ 40{
41 /// <summary> 41 /// <summary>
42 /// A dictionary containing task inventory items. Indexed by item UUID. 42 /// A dictionary for task inventory.
43 /// </summary> 43 /// </summary>
44 /// <remarks>
45 /// This class is not thread safe. Callers must synchronize on Dictionary methods or Clone() this object before 44 /// This class is not thread safe. Callers must synchronize on Dictionary methods or Clone() this object before
46 /// iterating over it. 45 /// iterating over it.
47 /// </remarks>
48 public class TaskInventoryDictionary : Dictionary<UUID, TaskInventoryItem>, 46 public class TaskInventoryDictionary : Dictionary<UUID, TaskInventoryItem>,
49 ICloneable, IXmlSerializable 47 ICloneable, IXmlSerializable
50 { 48 {
diff --git a/OpenSim/Framework/TaskInventoryItem.cs b/OpenSim/Framework/TaskInventoryItem.cs
index 574ee56..fb818ee 100644
--- a/OpenSim/Framework/TaskInventoryItem.cs
+++ b/OpenSim/Framework/TaskInventoryItem.cs
@@ -73,6 +73,9 @@ namespace OpenSim.Framework
73 73
74 private bool _ownerChanged = false; 74 private bool _ownerChanged = false;
75 75
76 // This used ONLY during copy. It can't be relied on at other times!
77 private bool _scriptRunning = true;
78
76 public UUID AssetID { 79 public UUID AssetID {
77 get { 80 get {
78 return _assetID; 81 return _assetID;
@@ -350,13 +353,14 @@ namespace OpenSim.Framework
350 } 353 }
351 } 354 }
352 355
353 /// <summary> 356 public bool ScriptRunning {
354 /// This used ONLY during copy. It can't be relied on at other times! 357 get {
355 /// </summary> 358 return _scriptRunning;
356 /// <remarks> 359 }
357 /// For true script running status, use IEntityInventory.TryGetScriptInstanceRunning() for now. 360 set {
358 /// </remarks> 361 _scriptRunning = value;
359 public bool ScriptRunning { get; set; } 362 }
363 }
360 364
361 // See ICloneable 365 // See ICloneable
362 366
@@ -384,7 +388,6 @@ namespace OpenSim.Framework
384 388
385 public TaskInventoryItem() 389 public TaskInventoryItem()
386 { 390 {
387 ScriptRunning = true;
388 CreationDate = (uint)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; 391 CreationDate = (uint)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
389 } 392 }
390 } 393 }
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index e76a37b..384f716 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -546,19 +546,6 @@ namespace OpenSim.Framework
546 } 546 }
547 547
548 /// <summary> 548 /// <summary>
549 /// Determines whether a point is inside a bounding box.
550 /// </summary>
551 /// <param name='v'></param>
552 /// <param name='min'></param>
553 /// <param name='max'></param>
554 /// <returns></returns>
555 public static bool IsInsideBox(Vector3 v, Vector3 min, Vector3 max)
556 {
557 return v.X >= min.X & v.Y >= min.Y && v.Z >= min.Z
558 && v.X <= max.X && v.Y <= max.Y && v.Z <= max.Z;
559 }
560
561 /// <summary>
562 /// Are the co-ordinates of the new region visible from the old region? 549 /// Are the co-ordinates of the new region visible from the old region?
563 /// </summary> 550 /// </summary>
564 /// <param name="oldx">Old region x-coord</param> 551 /// <param name="oldx">Old region x-coord</param>
@@ -875,12 +862,6 @@ namespace OpenSim.Framework
875 return Math.Min(Math.Max(x, min), max); 862 return Math.Min(Math.Max(x, min), max);
876 } 863 }
877 864
878 public static Vector3 Clip(Vector3 vec, float min, float max)
879 {
880 return new Vector3(Clip(vec.X, min, max), Clip(vec.Y, min, max),
881 Clip(vec.Z, min, max));
882 }
883
884 /// <summary> 865 /// <summary>
885 /// Convert an UUID to a raw uuid string. Right now this is a string without hyphens. 866 /// Convert an UUID to a raw uuid string. Right now this is a string without hyphens.
886 /// </summary> 867 /// </summary>
@@ -1032,38 +1013,6 @@ namespace OpenSim.Framework
1032 } 1013 }
1033 } 1014 }
1034 1015
1035 /// <summary>
1036 /// Copy data from one stream to another, leaving the read position of both streams at the beginning.
1037 /// </summary>
1038 /// <param name='inputStream'>
1039 /// Input stream. Must be seekable.
1040 /// </param>
1041 /// <exception cref='ArgumentException'>
1042 /// Thrown if the input stream is not seekable.
1043 /// </exception>
1044 public static Stream Copy(Stream inputStream)
1045 {
1046 if (!inputStream.CanSeek)
1047 throw new ArgumentException("Util.Copy(Stream inputStream) must receive an inputStream that can seek");
1048
1049 const int readSize = 256;
1050 byte[] buffer = new byte[readSize];
1051 MemoryStream ms = new MemoryStream();
1052
1053 int count = inputStream.Read(buffer, 0, readSize);
1054
1055 while (count > 0)
1056 {
1057 ms.Write(buffer, 0, count);
1058 count = inputStream.Read(buffer, 0, readSize);
1059 }
1060
1061 ms.Position = 0;
1062 inputStream.Position = 0;
1063
1064 return ms;
1065 }
1066
1067 public static XmlRpcResponse XmlRpcCommand(string url, string methodName, params object[] args) 1016 public static XmlRpcResponse XmlRpcCommand(string url, string methodName, params object[] args)
1068 { 1017 {
1069 return SendXmlRpcCommand(url, methodName, args); 1018 return SendXmlRpcCommand(url, methodName, args);
diff --git a/OpenSim/Framework/WebUtil.cs b/OpenSim/Framework/WebUtil.cs
index b85d93d..30a8c28 100644
--- a/OpenSim/Framework/WebUtil.cs
+++ b/OpenSim/Framework/WebUtil.cs
@@ -54,17 +54,9 @@ namespace OpenSim.Framework
54 MethodBase.GetCurrentMethod().DeclaringType); 54 MethodBase.GetCurrentMethod().DeclaringType);
55 55
56 /// <summary> 56 /// <summary>
57 /// Control the printing of certain debug messages.
58 /// </summary>
59 /// <remarks>
60 /// If DebugLevel >= 3 then short notices about outgoing HTTP requests are logged.
61 /// </remarks>
62 public static int DebugLevel { get; set; }
63
64 /// <summary>
65 /// Request number for diagnostic purposes. 57 /// Request number for diagnostic purposes.
66 /// </summary> 58 /// </summary>
67 public static int RequestNumber { get; internal set; } 59 public static int RequestNumber = 0;
68 60
69 /// <summary> 61 /// <summary>
70 /// this is the header field used to communicate the local request id 62 /// this is the header field used to communicate the local request id
@@ -154,11 +146,7 @@ namespace OpenSim.Framework
154 private static OSDMap ServiceOSDRequestWorker(string url, OSDMap data, string method, int timeout, bool compressed) 146 private static OSDMap ServiceOSDRequestWorker(string url, OSDMap data, string method, int timeout, bool compressed)
155 { 147 {
156 int reqnum = RequestNumber++; 148 int reqnum = RequestNumber++;
157 149 // m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method);
158 if (DebugLevel >= 3)
159 m_log.DebugFormat(
160 "[WEB UTIL]: HTTP OUT {0} ServiceOSD {1} {2} (timeout {3}, compressed {4})",
161 reqnum, method, url, timeout, compressed);
162 150
163 string errorMessage = "unknown error"; 151 string errorMessage = "unknown error";
164 int tickstart = Util.EnvironmentTickCount(); 152 int tickstart = Util.EnvironmentTickCount();
@@ -242,7 +230,7 @@ namespace OpenSim.Framework
242 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart); 230 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
243 if (tickdiff > LongCallTime) 231 if (tickdiff > LongCallTime)
244 m_log.InfoFormat( 232 m_log.InfoFormat(
245 "[WEB UTIL]: Slow ServiceOSD request {0} {1} {2} took {3}ms, {4}ms writing, {5}", 233 "[OSD REQUEST]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}",
246 reqnum, 234 reqnum,
247 method, 235 method,
248 url, 236 url,
@@ -251,14 +239,10 @@ namespace OpenSim.Framework
251 strBuffer != null 239 strBuffer != null
252 ? (strBuffer.Length > MaxRequestDiagLength ? strBuffer.Remove(MaxRequestDiagLength) : strBuffer) 240 ? (strBuffer.Length > MaxRequestDiagLength ? strBuffer.Remove(MaxRequestDiagLength) : strBuffer)
253 : ""); 241 : "");
254 else if (DebugLevel >= 4)
255 m_log.DebugFormat(
256 "[WEB UTIL]: HTTP OUT {0} took {1}ms, {2}ms writing",
257 reqnum, tickdiff, tickdata);
258 } 242 }
259 243
260 m_log.DebugFormat( 244 m_log.DebugFormat(
261 "[WEB UTIL]: ServiceOSD request {0} {1} {2} FAILED: {3}", reqnum, url, method, errorMessage); 245 "[WEB UTIL]: <{0}> osd request for {1}, method {2} FAILED: {3}", reqnum, url, method, errorMessage);
262 246
263 return ErrorResponseMap(errorMessage); 247 return ErrorResponseMap(errorMessage);
264 } 248 }
@@ -334,11 +318,7 @@ namespace OpenSim.Framework
334 { 318 {
335 int reqnum = RequestNumber++; 319 int reqnum = RequestNumber++;
336 string method = (data != null && data["RequestMethod"] != null) ? data["RequestMethod"] : "unknown"; 320 string method = (data != null && data["RequestMethod"] != null) ? data["RequestMethod"] : "unknown";
337 321 // m_log.DebugFormat("[WEB UTIL]: <{0}> start form request for {1}, method {2}",reqnum,url,method);
338 if (DebugLevel >= 3)
339 m_log.DebugFormat(
340 "[WEB UTIL]: HTTP OUT {0} ServiceForm {1} {2} (timeout {3})",
341 reqnum, method, url, timeout);
342 322
343 string errorMessage = "unknown error"; 323 string errorMessage = "unknown error";
344 int tickstart = Util.EnvironmentTickCount(); 324 int tickstart = Util.EnvironmentTickCount();
@@ -401,7 +381,7 @@ namespace OpenSim.Framework
401 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart); 381 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
402 if (tickdiff > LongCallTime) 382 if (tickdiff > LongCallTime)
403 m_log.InfoFormat( 383 m_log.InfoFormat(
404 "[WEB UTIL]: Slow ServiceForm request {0} {1} {2} took {3}ms, {4}ms writing, {5}", 384 "[SERVICE FORM]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}",
405 reqnum, 385 reqnum,
406 method, 386 method,
407 url, 387 url,
@@ -410,13 +390,9 @@ namespace OpenSim.Framework
410 queryString != null 390 queryString != null
411 ? (queryString.Length > MaxRequestDiagLength) ? queryString.Remove(MaxRequestDiagLength) : queryString 391 ? (queryString.Length > MaxRequestDiagLength) ? queryString.Remove(MaxRequestDiagLength) : queryString
412 : ""); 392 : "");
413 else if (DebugLevel >= 4)
414 m_log.DebugFormat(
415 "[WEB UTIL]: HTTP OUT {0} took {1}ms, {2}ms writing",
416 reqnum, tickdiff, tickdata);
417 } 393 }
418 394
419 m_log.WarnFormat("[WEB UTIL]: ServiceForm request {0} {1} {2} failed: {2}", reqnum, method, url, errorMessage); 395 m_log.WarnFormat("[SERVICE FORM]: <{0}> form request to {1} failed: {2}", reqnum, url, errorMessage);
420 396
421 return ErrorResponseMap(errorMessage); 397 return ErrorResponseMap(errorMessage);
422 } 398 }
@@ -668,6 +644,7 @@ namespace OpenSim.Framework
668 /// <returns></returns> 644 /// <returns></returns>
669 public static string[] GetPreferredImageTypes(string accept) 645 public static string[] GetPreferredImageTypes(string accept)
670 { 646 {
647
671 if (accept == null || accept == string.Empty) 648 if (accept == null || accept == string.Empty)
672 return new string[0]; 649 return new string[0];
673 650
@@ -726,16 +703,14 @@ namespace OpenSim.Framework
726 int maxConnections) 703 int maxConnections)
727 { 704 {
728 int reqnum = WebUtil.RequestNumber++; 705 int reqnum = WebUtil.RequestNumber++;
729 706 // m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method);
730 if (WebUtil.DebugLevel >= 3)
731 m_log.DebugFormat(
732 "[WEB UTIL]: HTTP OUT {0} AsynchronousRequestObject {1} {2}",
733 reqnum, verb, requestUrl);
734 707
735 int tickstart = Util.EnvironmentTickCount(); 708 int tickstart = Util.EnvironmentTickCount();
736// int tickdata = 0; 709// int tickdata = 0;
737 int tickdiff = 0; 710 int tickdiff = 0;
738 711
712// m_log.DebugFormat("[ASYNC REQUEST]: Starting {0} {1}", verb, requestUrl);
713
739 Type type = typeof(TRequest); 714 Type type = typeof(TRequest);
740 715
741 WebRequest request = WebRequest.Create(requestUrl); 716 WebRequest request = WebRequest.Create(requestUrl);
@@ -893,7 +868,7 @@ namespace OpenSim.Framework
893 } 868 }
894 869
895 m_log.InfoFormat( 870 m_log.InfoFormat(
896 "[ASYNC REQUEST]: Slow request {0} {1} {2} took {3}ms, {4}ms writing, {5}", 871 "[ASYNC REQUEST]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}",
897 reqnum, 872 reqnum,
898 verb, 873 verb,
899 requestUrl, 874 requestUrl,
@@ -908,12 +883,6 @@ namespace OpenSim.Framework
908 requestUrl, 883 requestUrl,
909 tickdiff); 884 tickdiff);
910 } 885 }
911 else if (WebUtil.DebugLevel >= 4)
912 {
913 m_log.DebugFormat(
914 "[WEB UTIL]: HTTP OUT {0} took {1}ms",
915 reqnum, tickdiff);
916 }
917 } 886 }
918 } 887 }
919 888
@@ -934,11 +903,7 @@ namespace OpenSim.Framework
934 public static string MakeRequest(string verb, string requestUrl, string obj) 903 public static string MakeRequest(string verb, string requestUrl, string obj)
935 { 904 {
936 int reqnum = WebUtil.RequestNumber++; 905 int reqnum = WebUtil.RequestNumber++;
937 906 // m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method);
938 if (WebUtil.DebugLevel >= 3)
939 m_log.DebugFormat(
940 "[WEB UTIL]: HTTP OUT {0} SynchronousRestForms {1} {2}",
941 reqnum, verb, requestUrl);
942 907
943 int tickstart = Util.EnvironmentTickCount(); 908 int tickstart = Util.EnvironmentTickCount();
944 int tickdata = 0; 909 int tickdata = 0;
@@ -1025,7 +990,7 @@ namespace OpenSim.Framework
1025 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart); 990 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
1026 if (tickdiff > WebUtil.LongCallTime) 991 if (tickdiff > WebUtil.LongCallTime)
1027 m_log.InfoFormat( 992 m_log.InfoFormat(
1028 "[FORMS]: Slow request {0} {1} {2} took {3}ms, {4}ms writing, {5}", 993 "[FORMS]: Slow request to <{0}> {1} {2} took {3}ms {4}ms writing {5}",
1029 reqnum, 994 reqnum,
1030 verb, 995 verb,
1031 requestUrl, 996 requestUrl,
@@ -1033,10 +998,6 @@ namespace OpenSim.Framework
1033 tickset, 998 tickset,
1034 tickdata, 999 tickdata,
1035 obj.Length > WebUtil.MaxRequestDiagLength ? obj.Remove(WebUtil.MaxRequestDiagLength) : obj); 1000 obj.Length > WebUtil.MaxRequestDiagLength ? obj.Remove(WebUtil.MaxRequestDiagLength) : obj);
1036 else if (WebUtil.DebugLevel >= 4)
1037 m_log.DebugFormat(
1038 "[WEB UTIL]: HTTP OUT {0} took {1}ms, {2}ms writing",
1039 reqnum, tickdiff, tickdata);
1040 1001
1041 return respstring; 1002 return respstring;
1042 } 1003 }
@@ -1071,11 +1032,7 @@ namespace OpenSim.Framework
1071 public static TResponse MakeRequest<TRequest, TResponse>(string verb, string requestUrl, TRequest obj, int pTimeout, int maxConnections) 1032 public static TResponse MakeRequest<TRequest, TResponse>(string verb, string requestUrl, TRequest obj, int pTimeout, int maxConnections)
1072 { 1033 {
1073 int reqnum = WebUtil.RequestNumber++; 1034 int reqnum = WebUtil.RequestNumber++;
1074 1035 // m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method);
1075 if (WebUtil.DebugLevel >= 3)
1076 m_log.DebugFormat(
1077 "[WEB UTIL]: HTTP OUT {0} SynchronousRestObject {1} {2}",
1078 reqnum, verb, requestUrl);
1079 1036
1080 int tickstart = Util.EnvironmentTickCount(); 1037 int tickstart = Util.EnvironmentTickCount();
1081 int tickdata = 0; 1038 int tickdata = 0;
@@ -1194,7 +1151,7 @@ namespace OpenSim.Framework
1194 } 1151 }
1195 1152
1196 m_log.InfoFormat( 1153 m_log.InfoFormat(
1197 "[SynchronousRestObjectRequester]: Slow request {0} {1} {2} took {3}ms, {4}ms writing, {5}", 1154 "[SynchronousRestObjectRequester]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}",
1198 reqnum, 1155 reqnum,
1199 verb, 1156 verb,
1200 requestUrl, 1157 requestUrl,
@@ -1202,12 +1159,6 @@ namespace OpenSim.Framework
1202 tickdata, 1159 tickdata,
1203 originalRequest); 1160 originalRequest);
1204 } 1161 }
1205 else if (WebUtil.DebugLevel >= 4)
1206 {
1207 m_log.DebugFormat(
1208 "[WEB UTIL]: HTTP OUT {0} took {1}ms, {2}ms writing",
1209 reqnum, tickdiff, tickdata);
1210 }
1211 1162
1212 return deserial; 1163 return deserial;
1213 } 1164 }
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index 5f07272..6255515 100644
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -35,7 +35,6 @@ using System.Text;
35using System.Text.RegularExpressions; 35using System.Text.RegularExpressions;
36using System.Timers; 36using System.Timers;
37using log4net; 37using log4net;
38using NDesk.Options;
39using Nini.Config; 38using Nini.Config;
40using OpenMetaverse; 39using OpenMetaverse;
41using OpenSim.Framework; 40using OpenSim.Framework;
@@ -254,14 +253,8 @@ namespace OpenSim
254 m_console.Commands.AddCommand("Debug", false, "debug teleport", "debug teleport", "Toggle teleport route debugging", Debug); 253 m_console.Commands.AddCommand("Debug", false, "debug teleport", "debug teleport", "Toggle teleport route debugging", Debug);
255 254
256 m_console.Commands.AddCommand("Debug", false, "debug scene", 255 m_console.Commands.AddCommand("Debug", false, "debug scene",
257 "debug scene active|collisions|physics|scripting|teleport true|false", 256 "debug scene <scripting> <collisions> <physics>",
258 "Turn on scene debugging.", 257 "Turn on scene debugging", Debug);
259 "If active is false then main scene update and maintenance loops are suspended.\n"
260 + "If collisions is false then collisions with other objects are turned off.\n"
261 + "If physics is false then all physics objects are non-physical.\n"
262 + "If scripting is false then no scripting operations happen.\n"
263 + "If teleport is true then some extra teleport debug information is logged.",
264 Debug);
265 258
266 m_console.Commands.AddCommand("General", false, "change region", 259 m_console.Commands.AddCommand("General", false, "change region",
267 "change region <region name>", 260 "change region <region name>",
@@ -298,7 +291,7 @@ namespace OpenSim
298 291
299 m_console.Commands.AddCommand("Archiving", false, "save oar", 292 m_console.Commands.AddCommand("Archiving", false, "save oar",
300 //"save oar [-v|--version=<N>] [-p|--profile=<url>] [<OAR path>]", 293 //"save oar [-v|--version=<N>] [-p|--profile=<url>] [<OAR path>]",
301 "save oar [-h|--home=<url>] [--noassets] [--publish] [--perm=<permissions>] [--all] [<OAR path>]", 294 "save oar [-h|--home=<url>] [--noassets] [--publish] [--perm=<permissions>] [<OAR path>]",
302 "Save a region's data to an OAR archive.", 295 "Save a region's data to an OAR archive.",
303// "-v|--version=<N> generates scene objects as per older versions of the serialization (e.g. -v=0)" + Environment.NewLine 296// "-v|--version=<N> generates scene objects as per older versions of the serialization (e.g. -v=0)" + Environment.NewLine
304 "-h|--home=<url> adds the url of the profile service to the saved user information.\n" 297 "-h|--home=<url> adds the url of the profile service to the saved user information.\n"
@@ -308,7 +301,6 @@ namespace OpenSim
308 + " this is useful if you're making oars generally available that might be reloaded to the same grid from which you published\n" 301 + " this is useful if you're making oars generally available that might be reloaded to the same grid from which you published\n"
309 + "--perm=<permissions> stops objects with insufficient permissions from being saved to the OAR.\n" 302 + "--perm=<permissions> stops objects with insufficient permissions from being saved to the OAR.\n"
310 + " <permissions> can contain one or more of these characters: \"C\" = Copy, \"T\" = Transfer\n" 303 + " <permissions> can contain one or more of these characters: \"C\" = Copy, \"T\" = Transfer\n"
311 + "--all saves all the regions in the simulator, instead of just the current region.\n"
312 + "The OAR path must be a filesystem path." 304 + "The OAR path must be a filesystem path."
313 + " If this is not given then the oar is saved to region.oar in the current directory.", 305 + " If this is not given then the oar is saved to region.oar in the current directory.",
314 SaveOar); 306 SaveOar);
@@ -318,11 +310,8 @@ namespace OpenSim
318 "Change the scale of a named prim", HandleEditScale); 310 "Change the scale of a named prim", HandleEditScale);
319 311
320 m_console.Commands.AddCommand("Users", false, "kick user", 312 m_console.Commands.AddCommand("Users", false, "kick user",
321 "kick user <first> <last> [--force] [message]", 313 "kick user <first> <last> [message]",
322 "Kick a user off the simulator", 314 "Kick a user off the simulator", KickUserCommand);
323 "The --force option will kick the user without any checks to see whether it's already in the process of closing\n"
324 + "Only use this option if you are sure the avatar is inactive and a normal kick user operation does not removed them",
325 KickUserCommand);
326 315
327 m_console.Commands.AddCommand("Users", false, "show users", 316 m_console.Commands.AddCommand("Users", false, "show users",
328 "show users [full]", 317 "show users [full]",
@@ -339,6 +328,10 @@ namespace OpenSim
339 "show circuits", 328 "show circuits",
340 "Show agent circuit data", HandleShow); 329 "Show agent circuit data", HandleShow);
341 330
331 m_console.Commands.AddCommand("Comms", false, "show http-handlers",
332 "show http-handlers",
333 "Show all registered http handlers", HandleShow);
334
342 m_console.Commands.AddCommand("Comms", false, "show pending-objects", 335 m_console.Commands.AddCommand("Comms", false, "show pending-objects",
343 "show pending-objects", 336 "show pending-objects",
344 "Show # of objects on the pending queues of all scene viewers", HandleShow); 337 "Show # of objects on the pending queues of all scene viewers", HandleShow);
@@ -423,7 +416,6 @@ namespace OpenSim
423 { 416 {
424 RunCommandScript(m_shutdownCommandsFile); 417 RunCommandScript(m_shutdownCommandsFile);
425 } 418 }
426
427 base.ShutdownSpecific(); 419 base.ShutdownSpecific();
428 } 420 }
429 421
@@ -461,17 +453,11 @@ namespace OpenSim
461 /// <param name="cmdparams">name of avatar to kick</param> 453 /// <param name="cmdparams">name of avatar to kick</param>
462 private void KickUserCommand(string module, string[] cmdparams) 454 private void KickUserCommand(string module, string[] cmdparams)
463 { 455 {
464 bool force = false; 456 if (cmdparams.Length < 4)
465
466 OptionSet options = new OptionSet().Add("f|force", delegate (string v) { force = v != null; });
467
468 List<string> mainParams = options.Parse(cmdparams);
469
470 if (mainParams.Count < 4)
471 return; 457 return;
472 458
473 string alert = null; 459 string alert = null;
474 if (mainParams.Count > 4) 460 if (cmdparams.Length > 4)
475 alert = String.Format("\n{0}\n", String.Join(" ", cmdparams, 4, cmdparams.Length - 4)); 461 alert = String.Format("\n{0}\n", String.Join(" ", cmdparams, 4, cmdparams.Length - 4));
476 462
477 IList agents = SceneManager.GetCurrentSceneAvatars(); 463 IList agents = SceneManager.GetCurrentSceneAvatars();
@@ -480,8 +466,8 @@ namespace OpenSim
480 { 466 {
481 RegionInfo regionInfo = presence.Scene.RegionInfo; 467 RegionInfo regionInfo = presence.Scene.RegionInfo;
482 468
483 if (presence.Firstname.ToLower().Contains(mainParams[2].ToLower()) && 469 if (presence.Firstname.ToLower().Contains(cmdparams[2].ToLower()) &&
484 presence.Lastname.ToLower().Contains(mainParams[3].ToLower())) 470 presence.Lastname.ToLower().Contains(cmdparams[3].ToLower()))
485 { 471 {
486 MainConsole.Instance.Output( 472 MainConsole.Instance.Output(
487 String.Format( 473 String.Format(
@@ -494,7 +480,7 @@ namespace OpenSim
494 else 480 else
495 presence.ControllingClient.Kick("\nYou have been logged out by an administrator.\n"); 481 presence.ControllingClient.Kick("\nYou have been logged out by an administrator.\n");
496 482
497 presence.Scene.IncomingCloseAgent(presence.UUID, force); 483 presence.Scene.IncomingCloseAgent(presence.UUID);
498 } 484 }
499 } 485 }
500 486
@@ -936,8 +922,7 @@ namespace OpenSim
936 } 922 }
937 else 923 else
938 { 924 {
939 MainConsole.Instance.Output( 925 MainConsole.Instance.Output("Usage: debug scene scripting|collisions|physics|teleport true|false");
940 "Usage: debug scene active|scripting|collisions|physics|teleport true|false");
941 } 926 }
942 927
943 break; 928 break;
@@ -1017,6 +1002,33 @@ namespace OpenSim
1017 HandleShowCircuits(); 1002 HandleShowCircuits();
1018 break; 1003 break;
1019 1004
1005 case "http-handlers":
1006 System.Text.StringBuilder handlers = new System.Text.StringBuilder("Registered HTTP Handlers:\n");
1007
1008 handlers.AppendFormat("* XMLRPC:\n");
1009 foreach (String s in HttpServer.GetXmlRpcHandlerKeys())
1010 handlers.AppendFormat("\t{0}\n", s);
1011
1012 handlers.AppendFormat("* HTTP:\n");
1013 List<String> poll = HttpServer.GetPollServiceHandlerKeys();
1014 foreach (String s in HttpServer.GetHTTPHandlerKeys())
1015 handlers.AppendFormat("\t{0} {1}\n", s, (poll.Contains(s) ? "(poll service)" : string.Empty));
1016
1017 handlers.AppendFormat("* Agent:\n");
1018 foreach (String s in HttpServer.GetAgentHandlerKeys())
1019 handlers.AppendFormat("\t{0}\n", s);
1020
1021 handlers.AppendFormat("* LLSD:\n");
1022 foreach (String s in HttpServer.GetLLSDHandlerKeys())
1023 handlers.AppendFormat("\t{0}\n", s);
1024
1025 handlers.AppendFormat("* StreamHandlers ({0}):\n", HttpServer.GetStreamHandlerKeys().Count);
1026 foreach (String s in HttpServer.GetStreamHandlerKeys())
1027 handlers.AppendFormat("\t{0}\n", s);
1028
1029 MainConsole.Instance.Output(handlers.ToString());
1030 break;
1031
1020 case "modules": 1032 case "modules":
1021 MainConsole.Instance.Output("The currently loaded shared modules are:"); 1033 MainConsole.Instance.Output("The currently loaded shared modules are:");
1022 foreach (IRegionModule module in m_moduleLoader.GetLoadedSharedModules) 1034 foreach (IRegionModule module in m_moduleLoader.GetLoadedSharedModules)
@@ -1111,7 +1123,7 @@ namespace OpenSim
1111 aCircuit.Name, 1123 aCircuit.Name,
1112 aCircuit.child ? "child" : "root", 1124 aCircuit.child ? "child" : "root",
1113 aCircuit.circuitcode.ToString(), 1125 aCircuit.circuitcode.ToString(),
1114 aCircuit.IPAddress != null ? aCircuit.IPAddress.ToString() : "not set", 1126 aCircuit.IPAddress.ToString(),
1115 aCircuit.Viewer); 1127 aCircuit.Viewer);
1116 }); 1128 });
1117 1129
diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs
index 7232383..d107b7a 100644
--- a/OpenSim/Region/Application/OpenSimBase.cs
+++ b/OpenSim/Region/Application/OpenSimBase.cs
@@ -232,6 +232,8 @@ namespace OpenSim
232 232
233 base.StartupSpecific(); 233 base.StartupSpecific();
234 234
235 m_stats = StatsManager.SimExtraStats;
236
235 // Create a ModuleLoader instance 237 // Create a ModuleLoader instance
236 m_moduleLoader = new ModuleLoader(m_config.Source); 238 m_moduleLoader = new ModuleLoader(m_config.Source);
237 239
@@ -247,51 +249,51 @@ namespace OpenSim
247 plugin.PostInitialise(); 249 plugin.PostInitialise();
248 } 250 }
249 251
250 if (m_console != null) 252 AddPluginCommands();
251 {
252 StatsManager.RegisterConsoleCommands(m_console);
253 AddPluginCommands(m_console);
254 }
255 } 253 }
256 254
257 protected virtual void AddPluginCommands(CommandConsole console) 255 protected virtual void AddPluginCommands()
258 { 256 {
259 List<string> topics = GetHelpTopics(); 257 // If console exists add plugin commands.
260 258 if (m_console != null)
261 foreach (string topic in topics)
262 { 259 {
263 string capitalizedTopic = char.ToUpper(topic[0]) + topic.Substring(1); 260 List<string> topics = GetHelpTopics();
264 261
265 // This is a hack to allow the user to enter the help command in upper or lowercase. This will go 262 foreach (string topic in topics)
266 // away at some point. 263 {
267 console.Commands.AddCommand(capitalizedTopic, false, "help " + topic, 264 string capitalizedTopic = char.ToUpper(topic[0]) + topic.Substring(1);
268 "help " + capitalizedTopic,
269 "Get help on plugin command '" + topic + "'",
270 HandleCommanderHelp);
271 console.Commands.AddCommand(capitalizedTopic, false, "help " + capitalizedTopic,
272 "help " + capitalizedTopic,
273 "Get help on plugin command '" + topic + "'",
274 HandleCommanderHelp);
275 265
276 ICommander commander = null; 266 // This is a hack to allow the user to enter the help command in upper or lowercase. This will go
267 // away at some point.
268 m_console.Commands.AddCommand(capitalizedTopic, false, "help " + topic,
269 "help " + capitalizedTopic,
270 "Get help on plugin command '" + topic + "'",
271 HandleCommanderHelp);
272 m_console.Commands.AddCommand(capitalizedTopic, false, "help " + capitalizedTopic,
273 "help " + capitalizedTopic,
274 "Get help on plugin command '" + topic + "'",
275 HandleCommanderHelp);
277 276
278 Scene s = SceneManager.CurrentOrFirstScene; 277 ICommander commander = null;
279 278
280 if (s != null && s.GetCommanders() != null) 279 Scene s = SceneManager.CurrentOrFirstScene;
281 {
282 if (s.GetCommanders().ContainsKey(topic))
283 commander = s.GetCommanders()[topic];
284 }
285 280
286 if (commander == null) 281 if (s != null && s.GetCommanders() != null)
287 continue; 282 {
283 if (s.GetCommanders().ContainsKey(topic))
284 commander = s.GetCommanders()[topic];
285 }
288 286
289 foreach (string command in commander.Commands.Keys) 287 if (commander == null)
290 { 288 continue;
291 console.Commands.AddCommand(capitalizedTopic, false, 289
292 topic + " " + command, 290 foreach (string command in commander.Commands.Keys)
293 topic + " " + commander.Commands[command].ShortHelp(), 291 {
294 String.Empty, HandleCommanderCommand); 292 m_console.Commands.AddCommand(capitalizedTopic, false,
293 topic + " " + command,
294 topic + " " + commander.Commands[command].ShortHelp(),
295 String.Empty, HandleCommanderCommand);
296 }
295 } 297 }
296 } 298 }
297 } 299 }
@@ -621,7 +623,7 @@ namespace OpenSim
621 if (account == null) 623 if (account == null)
622 { 624 {
623 m_log.ErrorFormat( 625 m_log.ErrorFormat(
624 "[OPENSIM]: Unable to store account. If this simulator is connected to a grid, you must create the estate owner account first at the grid level."); 626 "[OPENSIM]: Unable to store account. If this simulator is connected to a grid, you must create the estate owner account first.");
625 } 627 }
626 else 628 else
627 { 629 {
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
index f6146a9..650cd50 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
@@ -241,8 +241,8 @@ namespace OpenSim.Region.ClientStack.Linden
241 m_HostCapsObj.RegisterHandler( 241 m_HostCapsObj.RegisterHandler(
242 "SEED", new RestStreamHandler("POST", capsBase + m_requestPath, SeedCapRequest, "SEED", null)); 242 "SEED", new RestStreamHandler("POST", capsBase + m_requestPath, SeedCapRequest, "SEED", null));
243 243
244// m_log.DebugFormat( 244 m_log.DebugFormat(
245// "[CAPS]: Registered seed capability {0} for {1}", capsBase + m_requestPath, m_HostCapsObj.AgentID); 245 "[CAPS]: Registered seed capability {0} for {1}", capsBase + m_requestPath, m_HostCapsObj.AgentID);
246 246
247 //m_capsHandlers["MapLayer"] = 247 //m_capsHandlers["MapLayer"] =
248 // new LLSDStreamhandler<OSDMapRequest, OSDMapLayerResponse>("POST", 248 // new LLSDStreamhandler<OSDMapRequest, OSDMapLayerResponse>("POST",
@@ -337,12 +337,11 @@ namespace OpenSim.Region.ClientStack.Linden
337 public string SeedCapRequest(string request, string path, string param, 337 public string SeedCapRequest(string request, string path, string param,
338 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) 338 IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
339 { 339 {
340 m_log.DebugFormat( 340// m_log.Debug("[CAPS]: Seed Caps Request in region: " + m_regionName);
341 "[CAPS]: Received SEED caps request in {0} for agent {1}", m_regionName, m_HostCapsObj.AgentID);
342 341
343 if (!m_Scene.CheckClient(m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint)) 342 if (!m_Scene.CheckClient(m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint))
344 { 343 {
345 m_log.WarnFormat( 344 m_log.DebugFormat(
346 "[CAPS]: Unauthorized CAPS client {0} from {1}", 345 "[CAPS]: Unauthorized CAPS client {0} from {1}",
347 m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint); 346 m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint);
348 347
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
index 5bbdce8..e113c60 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
@@ -94,7 +94,7 @@ namespace OpenSim.Region.ClientStack.Linden
94 94
95 //scene.CommsManager.HttpServer.AddLLSDHandler("/CAPS/EQG/", EventQueueFallBack); 95 //scene.CommsManager.HttpServer.AddLLSDHandler("/CAPS/EQG/", EventQueueFallBack);
96 96
97// scene.EventManager.OnNewClient += OnNewClient; 97 scene.EventManager.OnNewClient += OnNewClient;
98 98
99 // TODO: Leaving these open, or closing them when we 99 // TODO: Leaving these open, or closing them when we
100 // become a child is incorrect. It messes up TP in a big 100 // become a child is incorrect. It messes up TP in a big
@@ -102,7 +102,6 @@ namespace OpenSim.Region.ClientStack.Linden
102 // circuit is there. 102 // circuit is there.
103 103
104 scene.EventManager.OnClientClosed += ClientClosed; 104 scene.EventManager.OnClientClosed += ClientClosed;
105
106 scene.EventManager.OnMakeChildAgent += MakeChildAgent; 105 scene.EventManager.OnMakeChildAgent += MakeChildAgent;
107 scene.EventManager.OnRegisterCaps += OnRegisterCaps; 106 scene.EventManager.OnRegisterCaps += OnRegisterCaps;
108 107
@@ -111,10 +110,10 @@ namespace OpenSim.Region.ClientStack.Linden
111 false, 110 false,
112 "debug eq", 111 "debug eq",
113 "debug eq [0|1|2]", 112 "debug eq [0|1|2]",
114 "Turn on event queue debugging\n" 113 "Turn on event queue debugging"
115 + " <= 0 - turns off all event queue logging\n" 114 + "<= 0 - turns off all event queue logging"
116 + " >= 1 - turns on outgoing event logging\n" 115 + ">= 1 - turns on outgoing event logging"
117 + " >= 2 - turns on poll notification", 116 + ">= 2 - turns on poll notification",
118 HandleDebugEq); 117 HandleDebugEq);
119 } 118 }
120 else 119 else
@@ -227,6 +226,16 @@ namespace OpenSim.Region.ClientStack.Linden
227 226
228 #endregion 227 #endregion
229 228
229 private void OnNewClient(IClientAPI client)
230 {
231 //client.OnLogout += ClientClosed;
232 }
233
234// private void ClientClosed(IClientAPI client)
235// {
236// ClientClosed(client.AgentId);
237// }
238
230 private void ClientClosed(UUID agentID, Scene scene) 239 private void ClientClosed(UUID agentID, Scene scene)
231 { 240 {
232// m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", agentID, m_scene.RegionInfo.RegionName); 241// m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", agentID, m_scene.RegionInfo.RegionName);
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
index d604cf6..cd70410 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
@@ -94,7 +94,7 @@ namespace OpenSim.Region.ClientStack.Linden.Tests
94 UUID spId = TestHelpers.ParseTail(0x1); 94 UUID spId = TestHelpers.ParseTail(0x1);
95 95
96 SceneHelpers.AddScenePresence(m_scene, spId); 96 SceneHelpers.AddScenePresence(m_scene, spId);
97 m_scene.IncomingCloseAgent(spId, false); 97 m_scene.IncomingCloseAgent(spId);
98 98
99 // TODO: Add more assertions for the other aspects of event queues 99 // TODO: Add more assertions for the other aspects of event queues
100 Assert.That(MainServer.Instance.GetPollServiceHandlerKeys().Count, Is.EqualTo(0)); 100 Assert.That(MainServer.Instance.GetPollServiceHandlerKeys().Count, Is.EqualTo(0));
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs
index fcac182..0a5ad0f 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs
@@ -109,7 +109,7 @@ namespace OpenSim.Region.ClientStack.Linden
109 109
110 UUID capID = UUID.Random(); 110 UUID capID = UUID.Random();
111 111
112// m_log.DebugFormat("[REGION CONSOLE]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName); 112 m_log.DebugFormat("[REGION CONSOLE]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName);
113 caps.RegisterHandler( 113 caps.RegisterHandler(
114 "SimConsoleAsync", 114 "SimConsoleAsync",
115 new ConsoleHandler("/CAPS/" + capID + "/", "SimConsoleAsync", agentID, this, m_scene)); 115 new ConsoleHandler("/CAPS/" + capID + "/", "SimConsoleAsync", agentID, this, m_scene));
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs b/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs
index e22670b..1b8535c 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs
@@ -45,12 +45,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
45 public Packet Packet; 45 public Packet Packet;
46 46
47 /// <summary> 47 /// <summary>
48 /// No arg constructor. 48 /// Default constructor
49 /// </summary>
50 public IncomingPacket() {}
51
52 /// <summary>
53 /// Constructor
54 /// </summary> 49 /// </summary>
55 /// <param name="client">Reference to the client this packet came from</param> 50 /// <param name="client">Reference to the client this packet came from</param>
56 /// <param name="packet">Packet data</param> 51 /// <param name="packet">Packet data</param>
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index c9aa4ca..ae9ed7f 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -47,7 +47,6 @@ using OpenSim.Region.Framework.Scenes;
47using OpenSim.Services.Interfaces; 47using OpenSim.Services.Interfaces;
48using Timer = System.Timers.Timer; 48using Timer = System.Timers.Timer;
49using AssetLandmark = OpenSim.Framework.AssetLandmark; 49using AssetLandmark = OpenSim.Framework.AssetLandmark;
50using RegionFlags = OpenMetaverse.RegionFlags;
51using Nini.Config; 50using Nini.Config;
52 51
53using System.IO; 52using System.IO;
@@ -356,17 +355,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
356 private bool m_deliverPackets = true; 355 private bool m_deliverPackets = true;
357 private int m_animationSequenceNumber = 1; 356 private int m_animationSequenceNumber = 1;
358 private bool m_SendLogoutPacketWhenClosing = true; 357 private bool m_SendLogoutPacketWhenClosing = true;
359 358 private AgentUpdateArgs lastarg;
360 /// <summary>
361 /// We retain a single AgentUpdateArgs so that we can constantly reuse it rather than construct a new one for
362 /// every single incoming AgentUpdate. Every client sends 10 AgentUpdate UDP messages per second, even if it
363 /// is doing absolutely nothing.
364 /// </summary>
365 /// <remarks>
366 /// This does mean that agent updates must be processed synchronously, at least for each client, and called methods
367 /// cannot retain a reference to it outside of that method.
368 /// </remarks>
369 private AgentUpdateArgs m_lastAgentUpdateArgs;
370 359
371 protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>(); 360 protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>();
372 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers 361 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers
@@ -521,18 +510,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
521 /// </summary> 510 /// </summary>
522 public void Close() 511 public void Close()
523 { 512 {
524 Close(true, false); 513 Close(true);
525 } 514 }
526 515
527 public void Close(bool sendStop, bool force) 516 /// <summary>
517 /// Shut down the client view
518 /// </summary>
519 public void Close(bool sendStop)
528 { 520 {
529 // We lock here to prevent race conditions between two threads calling close simultaneously (e.g. 521 // We lock here to prevent race conditions between two threads calling close simultaneously (e.g.
530 // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection. 522 // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection.
531 lock (CloseSyncLock) 523 lock (CloseSyncLock)
532 { 524 {
533 // We still perform a force close inside the sync lock since this is intended to attempt close where 525 if (!IsActive)
534 // there is some unidentified connection problem, not where we have issues due to deadlock
535 if (!IsActive && !force)
536 return; 526 return;
537 527
538 IsActive = false; 528 IsActive = false;
@@ -847,9 +837,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
847 OutPacket(mov, ThrottleOutPacketType.Unknown); 837 OutPacket(mov, ThrottleOutPacketType.Unknown);
848 } 838 }
849 839
850 public void SendChatMessage( 840 public void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName,
851 string message, byte type, Vector3 fromPos, string fromName, 841 UUID fromAgentID, byte source, byte audible)
852 UUID fromAgentID, UUID ownerID, byte source, byte audible)
853 { 842 {
854 ChatFromSimulatorPacket reply = (ChatFromSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.ChatFromSimulator); 843 ChatFromSimulatorPacket reply = (ChatFromSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.ChatFromSimulator);
855 reply.ChatData.Audible = audible; 844 reply.ChatData.Audible = audible;
@@ -858,7 +847,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
858 reply.ChatData.SourceType = source; 847 reply.ChatData.SourceType = source;
859 reply.ChatData.Position = fromPos; 848 reply.ChatData.Position = fromPos;
860 reply.ChatData.FromName = Util.StringToBytes256(fromName); 849 reply.ChatData.FromName = Util.StringToBytes256(fromName);
861 reply.ChatData.OwnerID = ownerID; 850 reply.ChatData.OwnerID = fromAgentID;
862 reply.ChatData.SourceID = fromAgentID; 851 reply.ChatData.SourceID = fromAgentID;
863 852
864 OutPacket(reply, ThrottleOutPacketType.Unknown); 853 OutPacket(reply, ThrottleOutPacketType.Unknown);
@@ -3996,8 +3985,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3996 { 3985 {
3997 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value; 3986 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value;
3998 3987
3999 ImprovedTerseObjectUpdatePacket packet 3988 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
4000 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
4001 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 3989 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4002 packet.RegionData.TimeDilation = timeDilation; 3990 packet.RegionData.TimeDilation = timeDilation;
4003 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; 3991 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
@@ -4042,9 +4030,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4042 { 4030 {
4043 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value; 4031 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
4044 4032
4045 ImprovedTerseObjectUpdatePacket packet 4033 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
4046 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
4047 PacketType.ImprovedTerseObjectUpdate);
4048 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 4034 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4049 packet.RegionData.TimeDilation = timeDilation; 4035 packet.RegionData.TimeDilation = timeDilation;
4050 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; 4036 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
@@ -4052,7 +4038,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4052 for (int i = 0; i < blocks.Count; i++) 4038 for (int i = 0; i < blocks.Count; i++)
4053 packet.ObjectData[i] = blocks[i]; 4039 packet.ObjectData[i] = blocks[i];
4054 4040
4055 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); }); 4041 OutPacket(packet, ThrottleOutPacketType.Task, true);
4056 } 4042 }
4057 4043
4058 #endregion Packet Sending 4044 #endregion Packet Sending
@@ -4549,7 +4535,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4549 { 4535 {
4550 returnblock[j] = new EstateOwnerMessagePacket.ParamListBlock(); 4536 returnblock[j] = new EstateOwnerMessagePacket.ParamListBlock();
4551 } 4537 }
4552 j = 0; 4538 j = 0;
4553 4539
4554 returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++; 4540 returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++;
4555 returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++; 4541 returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++;
@@ -5053,9 +5039,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5053 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Y, -64.0f, 64.0f), data, pos); pos += 2; 5039 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Y, -64.0f, 64.0f), data, pos); pos += 2;
5054 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Z, -64.0f, 64.0f), data, pos); pos += 2; 5040 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Z, -64.0f, 64.0f), data, pos); pos += 2;
5055 5041
5056 ImprovedTerseObjectUpdatePacket.ObjectDataBlock block 5042 ImprovedTerseObjectUpdatePacket.ObjectDataBlock block = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock();
5057 = PacketPool.Instance.GetDataBlock<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
5058
5059 block.Data = data; 5043 block.Data = data;
5060 5044
5061 if (textureEntry != null && textureEntry.Length > 0) 5045 if (textureEntry != null && textureEntry.Length > 0)
@@ -5305,18 +5289,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5305 protected virtual void RegisterLocalPacketHandlers() 5289 protected virtual void RegisterLocalPacketHandlers()
5306 { 5290 {
5307 AddLocalPacketHandler(PacketType.LogoutRequest, HandleLogout); 5291 AddLocalPacketHandler(PacketType.LogoutRequest, HandleLogout);
5308
5309 // If AgentUpdate is ever handled asynchronously, then we will also need to construct a new AgentUpdateArgs
5310 // for each AgentUpdate packet.
5311 AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate, false); 5292 AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate, false);
5312
5313 AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect, false); 5293 AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect, false);
5314 AddLocalPacketHandler(PacketType.AgentCachedTexture, HandleAgentTextureCached, false); 5294 AddLocalPacketHandler(PacketType.AgentCachedTexture, HandleAgentTextureCached, false);
5315 AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false); 5295 AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false);
5316 AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest, false); 5296 AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest, false);
5317 AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest, false); 5297 AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest, false);
5318 AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest); 5298 AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest, false);
5319 AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest); 5299 AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest, false);
5320 AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage); 5300 AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage);
5321 AddLocalPacketHandler(PacketType.AvatarPropertiesRequest, HandleAvatarPropertiesRequest); 5301 AddLocalPacketHandler(PacketType.AvatarPropertiesRequest, HandleAvatarPropertiesRequest);
5322 AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer); 5302 AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer);
@@ -5538,84 +5518,81 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5538 5518
5539 #region Scene/Avatar 5519 #region Scene/Avatar
5540 5520
5541 private bool HandleAgentUpdate(IClientAPI sener, Packet packet) 5521 private bool HandleAgentUpdate(IClientAPI sener, Packet Pack)
5542 { 5522 {
5543 if (OnAgentUpdate != null) 5523 if (OnAgentUpdate != null)
5544 { 5524 {
5545 AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet; 5525 bool update = false;
5526 AgentUpdatePacket agenUpdate = (AgentUpdatePacket)Pack;
5546 5527
5547 #region Packet Session and User Check 5528 #region Packet Session and User Check
5548 if (agentUpdate.AgentData.SessionID != SessionId || agentUpdate.AgentData.AgentID != AgentId) 5529 if (agenUpdate.AgentData.SessionID != SessionId || agenUpdate.AgentData.AgentID != AgentId)
5549 {
5550 PacketPool.Instance.ReturnPacket(packet);
5551 return false; 5530 return false;
5552 }
5553 #endregion 5531 #endregion
5554 5532
5555 bool update = false; 5533 AgentUpdatePacket.AgentDataBlock x = agenUpdate.AgentData;
5556 AgentUpdatePacket.AgentDataBlock x = agentUpdate.AgentData; 5534
5535 // We can only check when we have something to check
5536 // against.
5557 5537
5558 if (m_lastAgentUpdateArgs != null) 5538 if (lastarg != null)
5559 { 5539 {
5560 // These should be ordered from most-likely to
5561 // least likely to change. I've made an initial
5562 // guess at that.
5563 update = 5540 update =
5564 ( 5541 (
5565 (x.BodyRotation != m_lastAgentUpdateArgs.BodyRotation) || 5542 (x.BodyRotation != lastarg.BodyRotation) ||
5566 (x.CameraAtAxis != m_lastAgentUpdateArgs.CameraAtAxis) || 5543 (x.CameraAtAxis != lastarg.CameraAtAxis) ||
5567 (x.CameraCenter != m_lastAgentUpdateArgs.CameraCenter) || 5544 (x.CameraCenter != lastarg.CameraCenter) ||
5568 (x.CameraLeftAxis != m_lastAgentUpdateArgs.CameraLeftAxis) || 5545 (x.CameraLeftAxis != lastarg.CameraLeftAxis) ||
5569 (x.CameraUpAxis != m_lastAgentUpdateArgs.CameraUpAxis) || 5546 (x.CameraUpAxis != lastarg.CameraUpAxis) ||
5570 (x.ControlFlags != m_lastAgentUpdateArgs.ControlFlags) || 5547 (x.ControlFlags != lastarg.ControlFlags) ||
5571 (x.ControlFlags != 0) || 5548 (x.ControlFlags != 0) ||
5572 (x.Far != m_lastAgentUpdateArgs.Far) || 5549 (x.Far != lastarg.Far) ||
5573 (x.Flags != m_lastAgentUpdateArgs.Flags) || 5550 (x.Flags != lastarg.Flags) ||
5574 (x.State != m_lastAgentUpdateArgs.State) || 5551 (x.State != lastarg.State) ||
5575 (x.HeadRotation != m_lastAgentUpdateArgs.HeadRotation) || 5552 (x.HeadRotation != lastarg.HeadRotation) ||
5576 (x.SessionID != m_lastAgentUpdateArgs.SessionID) || 5553 (x.SessionID != lastarg.SessionID) ||
5577 (x.AgentID != m_lastAgentUpdateArgs.AgentID) 5554 (x.AgentID != lastarg.AgentID)
5578 ); 5555 );
5579 } 5556 }
5580 else 5557 else
5581 { 5558 {
5582 m_lastAgentUpdateArgs = new AgentUpdateArgs();
5583 update = true; 5559 update = true;
5584 } 5560 }
5585 5561
5562 // These should be ordered from most-likely to
5563 // least likely to change. I've made an initial
5564 // guess at that.
5565
5586 if (update) 5566 if (update)
5587 { 5567 {
5588// m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name); 5568// m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name);
5589 5569
5590 m_lastAgentUpdateArgs.AgentID = x.AgentID; 5570 AgentUpdateArgs arg = new AgentUpdateArgs();
5591 m_lastAgentUpdateArgs.BodyRotation = x.BodyRotation; 5571 arg.AgentID = x.AgentID;
5592 m_lastAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis; 5572 arg.BodyRotation = x.BodyRotation;
5593 m_lastAgentUpdateArgs.CameraCenter = x.CameraCenter; 5573 arg.CameraAtAxis = x.CameraAtAxis;
5594 m_lastAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis; 5574 arg.CameraCenter = x.CameraCenter;
5595 m_lastAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis; 5575 arg.CameraLeftAxis = x.CameraLeftAxis;
5596 m_lastAgentUpdateArgs.ControlFlags = x.ControlFlags; 5576 arg.CameraUpAxis = x.CameraUpAxis;
5597 m_lastAgentUpdateArgs.Far = x.Far; 5577 arg.ControlFlags = x.ControlFlags;
5598 m_lastAgentUpdateArgs.Flags = x.Flags; 5578 arg.Far = x.Far;
5599 m_lastAgentUpdateArgs.HeadRotation = x.HeadRotation; 5579 arg.Flags = x.Flags;
5600 m_lastAgentUpdateArgs.SessionID = x.SessionID; 5580 arg.HeadRotation = x.HeadRotation;
5601 m_lastAgentUpdateArgs.State = x.State; 5581 arg.SessionID = x.SessionID;
5602 5582 arg.State = x.State;
5603 UpdateAgent handlerAgentUpdate = OnAgentUpdate; 5583 UpdateAgent handlerAgentUpdate = OnAgentUpdate;
5604 UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate; 5584 UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate;
5605 5585 lastarg = arg; // save this set of arguments for nexttime
5606 if (handlerPreAgentUpdate != null) 5586 if (handlerPreAgentUpdate != null)
5607 OnPreAgentUpdate(this, m_lastAgentUpdateArgs); 5587 OnPreAgentUpdate(this, arg);
5608
5609 if (handlerAgentUpdate != null) 5588 if (handlerAgentUpdate != null)
5610 OnAgentUpdate(this, m_lastAgentUpdateArgs); 5589 OnAgentUpdate(this, arg);
5611 5590
5612 handlerAgentUpdate = null; 5591 handlerAgentUpdate = null;
5613 handlerPreAgentUpdate = null; 5592 handlerPreAgentUpdate = null;
5614 } 5593 }
5615 } 5594 }
5616 5595
5617 PacketPool.Instance.ReturnPacket(packet);
5618
5619 return true; 5596 return true;
5620 } 5597 }
5621 5598
@@ -5987,8 +5964,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5987 msgpack.MessageBlock.ID, 5964 msgpack.MessageBlock.ID,
5988 msgpack.MessageBlock.Offline != 0 ? true : false, 5965 msgpack.MessageBlock.Offline != 0 ? true : false,
5989 msgpack.MessageBlock.Position, 5966 msgpack.MessageBlock.Position,
5990 msgpack.MessageBlock.BinaryBucket, 5967 msgpack.MessageBlock.BinaryBucket);
5991 true);
5992 5968
5993 handlerInstantMessage(this, im); 5969 handlerInstantMessage(this, im);
5994 } 5970 }
@@ -9275,9 +9251,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9275 } 9251 }
9276 #endregion 9252 #endregion
9277 9253
9278 string method = Utils.BytesToString(messagePacket.MethodData.Method); 9254 switch (Utils.BytesToString(messagePacket.MethodData.Method))
9279
9280 switch (method)
9281 { 9255 {
9282 case "getinfo": 9256 case "getinfo":
9283 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) 9257 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
@@ -9593,17 +9567,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9593 return true; 9567 return true;
9594 9568
9595 default: 9569 default:
9596 m_log.WarnFormat( 9570 m_log.Error("EstateOwnerMessage: Unknown method requested\n" + messagePacket);
9597 "[LLCLIENTVIEW]: EstateOwnerMessage: Unknown method {0} requested for {1} in {2}",
9598 method, Name, Scene.Name);
9599
9600 for (int i = 0; i < messagePacket.ParamList.Length; i++)
9601 {
9602 EstateOwnerMessagePacket.ParamListBlock block = messagePacket.ParamList[i];
9603 string data = (string)Utils.BytesToString(block.Parameter);
9604 m_log.DebugFormat("[LLCLIENTVIEW]: Param {0}={1}", i, data);
9605 }
9606
9607 return true; 9571 return true;
9608 } 9572 }
9609 9573
@@ -11996,7 +11960,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11996 logPacket = false; 11960 logPacket = false;
11997 11961
11998 if (DebugPacketLevel <= 50 11962 if (DebugPacketLevel <= 50
11999 && (packet.Type == PacketType.ImprovedTerseObjectUpdate || packet.Type == PacketType.ObjectUpdate)) 11963 & (packet.Type == PacketType.ImprovedTerseObjectUpdate || packet.Type == PacketType.ObjectUpdate))
12000 logPacket = false; 11964 logPacket = false;
12001 11965
12002 if (DebugPacketLevel <= 25 && packet.Type == PacketType.ObjectPropertiesFamily) 11966 if (DebugPacketLevel <= 25 && packet.Type == PacketType.ObjectPropertiesFamily)
@@ -12070,6 +12034,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12070 12034
12071 if (!ProcessPacketMethod(packet)) 12035 if (!ProcessPacketMethod(packet))
12072 m_log.Warn("[CLIENT]: unhandled packet " + packet.Type); 12036 m_log.Warn("[CLIENT]: unhandled packet " + packet.Type);
12037
12038 PacketPool.Instance.ReturnPacket(packet);
12073 } 12039 }
12074 12040
12075 private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket) 12041 private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket)
@@ -12238,7 +12204,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12238 { 12204 {
12239 Kick(reason); 12205 Kick(reason);
12240 Thread.Sleep(1000); 12206 Thread.Sleep(1000);
12241 Disconnect(); 12207 Close();
12242 } 12208 }
12243 12209
12244 public void Disconnect() 12210 public void Disconnect()
@@ -12526,10 +12492,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12526 ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f); 12492 ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f);
12527 12493
12528 12494
12529 ImprovedTerseObjectUpdatePacket packet 12495 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
12530 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
12531 PacketType.ImprovedTerseObjectUpdate);
12532
12533 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 12496 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
12534 packet.RegionData.TimeDilation = timeDilation; 12497 packet.RegionData.TimeDilation = timeDilation;
12535 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; 12498 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1];
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index b8951d9..d6513c5 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -37,7 +37,6 @@ using log4net;
37using Nini.Config; 37using Nini.Config;
38using OpenMetaverse.Packets; 38using OpenMetaverse.Packets;
39using OpenSim.Framework; 39using OpenSim.Framework;
40using OpenSim.Framework.Console;
41using OpenSim.Framework.Monitoring; 40using OpenSim.Framework.Monitoring;
42using OpenSim.Region.Framework.Scenes; 41using OpenSim.Region.Framework.Scenes;
43using OpenMetaverse; 42using OpenMetaverse;
@@ -101,11 +100,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
101 100
102 /// <summary>The measured resolution of Environment.TickCount</summary> 101 /// <summary>The measured resolution of Environment.TickCount</summary>
103 public readonly float TickCountResolution; 102 public readonly float TickCountResolution;
104
105 /// <summary>Number of prim updates to put on the queue each time the 103 /// <summary>Number of prim updates to put on the queue each time the
106 /// OnQueueEmpty event is triggered for updates</summary> 104 /// OnQueueEmpty event is triggered for updates</summary>
107 public readonly int PrimUpdatesPerCallback; 105 public readonly int PrimUpdatesPerCallback;
108
109 /// <summary>Number of texture packets to put on the queue each time the 106 /// <summary>Number of texture packets to put on the queue each time the
110 /// OnQueueEmpty event is triggered for textures</summary> 107 /// OnQueueEmpty event is triggered for textures</summary>
111 public readonly int TextureSendLimit; 108 public readonly int TextureSendLimit;
@@ -127,37 +124,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP
127 124
128 /// <summary>Manages authentication for agent circuits</summary> 125 /// <summary>Manages authentication for agent circuits</summary>
129 private AgentCircuitManager m_circuitManager; 126 private AgentCircuitManager m_circuitManager;
130
131 /// <summary>Reference to the scene this UDP server is attached to</summary> 127 /// <summary>Reference to the scene this UDP server is attached to</summary>
132 protected Scene m_scene; 128 protected Scene m_scene;
133
134 /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary> 129 /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary>
135 private Location m_location; 130 private Location m_location;
136
137 /// <summary>The size of the receive buffer for the UDP socket. This value 131 /// <summary>The size of the receive buffer for the UDP socket. This value
138 /// is passed up to the operating system and used in the system networking 132 /// is passed up to the operating system and used in the system networking
139 /// stack. Use zero to leave this value as the default</summary> 133 /// stack. Use zero to leave this value as the default</summary>
140 private int m_recvBufferSize; 134 private int m_recvBufferSize;
141
142 /// <summary>Flag to process packets asynchronously or synchronously</summary> 135 /// <summary>Flag to process packets asynchronously or synchronously</summary>
143 private bool m_asyncPacketHandling; 136 private bool m_asyncPacketHandling;
144
145 /// <summary>Tracks whether or not a packet was sent each round so we know 137 /// <summary>Tracks whether or not a packet was sent each round so we know
146 /// whether or not to sleep</summary> 138 /// whether or not to sleep</summary>
147 private bool m_packetSent; 139 private bool m_packetSent;
148 140
149 /// <summary>Environment.TickCount of the last time that packet stats were reported to the scene</summary> 141 /// <summary>Environment.TickCount of the last time that packet stats were reported to the scene</summary>
150 private int m_elapsedMSSinceLastStatReport = 0; 142 private int m_elapsedMSSinceLastStatReport = 0;
151
152 /// <summary>Environment.TickCount of the last time the outgoing packet handler executed</summary> 143 /// <summary>Environment.TickCount of the last time the outgoing packet handler executed</summary>
153 private int m_tickLastOutgoingPacketHandler; 144 private int m_tickLastOutgoingPacketHandler;
154
155 /// <summary>Keeps track of the number of elapsed milliseconds since the last time the outgoing packet handler looped</summary> 145 /// <summary>Keeps track of the number of elapsed milliseconds since the last time the outgoing packet handler looped</summary>
156 private int m_elapsedMSOutgoingPacketHandler; 146 private int m_elapsedMSOutgoingPacketHandler;
157
158 /// <summary>Keeps track of the number of 100 millisecond periods elapsed in the outgoing packet handler executed</summary> 147 /// <summary>Keeps track of the number of 100 millisecond periods elapsed in the outgoing packet handler executed</summary>
159 private int m_elapsed100MSOutgoingPacketHandler; 148 private int m_elapsed100MSOutgoingPacketHandler;
160
161 /// <summary>Keeps track of the number of 500 millisecond periods elapsed in the outgoing packet handler executed</summary> 149 /// <summary>Keeps track of the number of 500 millisecond periods elapsed in the outgoing packet handler executed</summary>
162 private int m_elapsed500MSOutgoingPacketHandler; 150 private int m_elapsed500MSOutgoingPacketHandler;
163 151
@@ -171,9 +159,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
171 protected bool m_sendPing; 159 protected bool m_sendPing;
172 160
173 private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>(); 161 private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>();
174 private Pool<IncomingPacket> m_incomingPacketPool;
175
176 private Stat m_incomingPacketPoolStat;
177 162
178 private int m_defaultRTO = 0; 163 private int m_defaultRTO = 0;
179 private int m_maxRTO = 0; 164 private int m_maxRTO = 0;
@@ -195,9 +180,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
195 /// </summary> 180 /// </summary>
196 private IClientAPI m_currentIncomingClient; 181 private IClientAPI m_currentIncomingClient;
197 182
198 public LLUDPServer( 183 public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager)
199 IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port,
200 IConfigSource configSource, AgentCircuitManager circuitManager)
201 : base(listenIP, (int)port) 184 : base(listenIP, (int)port)
202 { 185 {
203 #region Environment.TickCount Measurement 186 #region Environment.TickCount Measurement
@@ -219,7 +202,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
219 202
220 m_circuitManager = circuitManager; 203 m_circuitManager = circuitManager;
221 int sceneThrottleBps = 0; 204 int sceneThrottleBps = 0;
222 bool usePools = false;
223 205
224 IConfig config = configSource.Configs["ClientStack.LindenUDP"]; 206 IConfig config = configSource.Configs["ClientStack.LindenUDP"];
225 if (config != null) 207 if (config != null)
@@ -245,16 +227,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
245 m_pausedAckTimeout = 1000 * 300; // 5 minutes 227 m_pausedAckTimeout = 1000 * 300; // 5 minutes
246 } 228 }
247 229
248 // FIXME: This actually only needs to be done once since the PacketPool is shared across all servers.
249 // However, there is no harm in temporarily doing it multiple times.
250 IConfig packetConfig = configSource.Configs["PacketPool"];
251 if (packetConfig != null)
252 {
253 PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true);
254 PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true);
255 usePools = packetConfig.GetBoolean("RecycleBaseUDPPackets", usePools);
256 }
257
258 #region BinaryStats 230 #region BinaryStats
259 config = configSource.Configs["Statistics.Binary"]; 231 config = configSource.Configs["Statistics.Binary"];
260 m_shouldCollectStats = false; 232 m_shouldCollectStats = false;
@@ -282,28 +254,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
282 254
283 m_throttle = new TokenBucket(null, sceneThrottleBps); 255 m_throttle = new TokenBucket(null, sceneThrottleBps);
284 ThrottleRates = new ThrottleRates(configSource); 256 ThrottleRates = new ThrottleRates(configSource);
285
286 if (usePools)
287 EnablePools();
288 } 257 }
289 258
290 public void Start() 259 public void Start()
291 { 260 {
292 StartInbound(); 261 if (m_scene == null)
293 StartOutbound(); 262 throw new InvalidOperationException("[LLUDPSERVER]: Cannot LLUDPServer.Start() without an IScene reference");
294 263
295 m_elapsedMSSinceLastStatReport = Environment.TickCount;
296 }
297
298 private void StartInbound()
299 {
300 m_log.InfoFormat( 264 m_log.InfoFormat(
301 "[LLUDPSERVER]: Starting inbound packet processing for the LLUDP server in {0} mode with UsePools = {1}", 265 "[LLUDPSERVER]: Starting the LLUDP server in {0} mode",
302 m_asyncPacketHandling ? "asynchronous" : "synchronous", UsePools); 266 m_asyncPacketHandling ? "asynchronous" : "synchronous");
303 267
304 base.StartInbound(m_recvBufferSize, m_asyncPacketHandling); 268 base.Start(m_recvBufferSize, m_asyncPacketHandling);
305 269
306 // This thread will process the packets received that are placed on the packetInbox 270 // Start the packet processing threads
307 Watchdog.StartThread( 271 Watchdog.StartThread(
308 IncomingPacketHandler, 272 IncomingPacketHandler,
309 string.Format("Incoming Packets ({0})", m_scene.RegionInfo.RegionName), 273 string.Format("Incoming Packets ({0})", m_scene.RegionInfo.RegionName),
@@ -312,13 +276,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
312 true, 276 true,
313 GetWatchdogIncomingAlarmData, 277 GetWatchdogIncomingAlarmData,
314 Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); 278 Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS);
315 }
316
317 private new void StartOutbound()
318 {
319 m_log.Info("[LLUDPSERVER]: Starting outbound packet processing for the LLUDP server");
320
321 base.StartOutbound();
322 279
323 Watchdog.StartThread( 280 Watchdog.StartThread(
324 OutgoingPacketHandler, 281 OutgoingPacketHandler,
@@ -328,57 +285,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
328 true, 285 true,
329 GetWatchdogOutgoingAlarmData, 286 GetWatchdogOutgoingAlarmData,
330 Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); 287 Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS);
331 }
332
333 public void Stop()
334 {
335 m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName);
336 base.StopOutbound();
337 base.StopInbound();
338 }
339 288
340 protected override bool EnablePools() 289 m_elapsedMSSinceLastStatReport = Environment.TickCount;
341 {
342 if (!UsePools)
343 {
344 base.EnablePools();
345
346 m_incomingPacketPool = new Pool<IncomingPacket>(() => new IncomingPacket(), 500);
347
348 m_incomingPacketPoolStat
349 = new Stat(
350 "IncomingPacketPoolCount",
351 "Objects within incoming packet pool",
352 "The number of objects currently stored within the incoming packet pool",
353 "",
354 "clientstack",
355 "packetpool",
356 StatType.Pull,
357 stat => stat.Value = m_incomingPacketPool.Count,
358 StatVerbosity.Debug);
359
360 StatsManager.RegisterStat(m_incomingPacketPoolStat);
361
362 return true;
363 }
364
365 return false;
366 }
367
368 protected override bool DisablePools()
369 {
370 if (UsePools)
371 {
372 base.DisablePools();
373
374 StatsManager.DeregisterStat(m_incomingPacketPoolStat);
375
376 // We won't null out the pool to avoid a race condition with code that may be in the middle of using it.
377
378 return true;
379 }
380
381 return false;
382 } 290 }
383 291
384 /// <summary> 292 /// <summary>
@@ -403,6 +311,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
403 m_currentOutgoingClient != null ? m_currentOutgoingClient.Name : "none"); 311 m_currentOutgoingClient != null ? m_currentOutgoingClient.Name : "none");
404 } 312 }
405 313
314 public new void Stop()
315 {
316 m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName);
317 base.Stop();
318 }
319
406 public void AddScene(IScene scene) 320 public void AddScene(IScene scene)
407 { 321 {
408 if (m_scene != null) 322 if (m_scene != null)
@@ -419,117 +333,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
419 333
420 m_scene = (Scene)scene; 334 m_scene = (Scene)scene;
421 m_location = new Location(m_scene.RegionInfo.RegionHandle); 335 m_location = new Location(m_scene.RegionInfo.RegionHandle);
422
423 MainConsole.Instance.Commands.AddCommand(
424 "Debug",
425 false,
426 "debug lludp start",
427 "debug lludp start <in|out|all>",
428 "Control LLUDP packet processing.",
429 "No effect if packet processing has already started.\n"
430 + "in - start inbound processing.\n"
431 + "out - start outbound processing.\n"
432 + "all - start in and outbound processing.\n",
433 HandleStartCommand);
434
435 MainConsole.Instance.Commands.AddCommand(
436 "Debug",
437 false,
438 "debug lludp stop",
439 "debug lludp stop <in|out|all>",
440 "Stop LLUDP packet processing.",
441 "No effect if packet processing has already stopped.\n"
442 + "in - stop inbound processing.\n"
443 + "out - stop outbound processing.\n"
444 + "all - stop in and outbound processing.\n",
445 HandleStopCommand);
446
447 MainConsole.Instance.Commands.AddCommand(
448 "Debug",
449 false,
450 "debug lludp pool",
451 "debug lludp pool <on|off>",
452 "Turn object pooling within the lludp component on or off.",
453 HandlePoolCommand);
454
455 MainConsole.Instance.Commands.AddCommand(
456 "Debug",
457 false,
458 "debug lludp status",
459 "debug lludp status",
460 "Return status of LLUDP packet processing.",
461 HandleStatusCommand);
462 }
463
464 private void HandleStartCommand(string module, string[] args)
465 {
466 if (args.Length != 4)
467 {
468 MainConsole.Instance.Output("Usage: debug lludp start <in|out|all>");
469 return;
470 }
471
472 string subCommand = args[3];
473
474 if (subCommand == "in" || subCommand == "all")
475 StartInbound();
476
477 if (subCommand == "out" || subCommand == "all")
478 StartOutbound();
479 }
480
481 private void HandleStopCommand(string module, string[] args)
482 {
483 if (args.Length != 4)
484 {
485 MainConsole.Instance.Output("Usage: debug lludp stop <in|out|all>");
486 return;
487 }
488
489 string subCommand = args[3];
490
491 if (subCommand == "in" || subCommand == "all")
492 StopInbound();
493
494 if (subCommand == "out" || subCommand == "all")
495 StopOutbound();
496 }
497
498 private void HandlePoolCommand(string module, string[] args)
499 {
500 if (args.Length != 4)
501 {
502 MainConsole.Instance.Output("Usage: debug lludp pool <on|off>");
503 return;
504 }
505
506 string enabled = args[3];
507
508 if (enabled == "on")
509 {
510 if (EnablePools())
511 MainConsole.Instance.OutputFormat("Packet pools enabled on {0}", m_scene.Name);
512 }
513 else if (enabled == "off")
514 {
515 if (DisablePools())
516 MainConsole.Instance.OutputFormat("Packet pools disabled on {0}", m_scene.Name);
517 }
518 else
519 {
520 MainConsole.Instance.Output("Usage: debug lludp pool <on|off>");
521 }
522 }
523
524 private void HandleStatusCommand(string module, string[] args)
525 {
526 MainConsole.Instance.OutputFormat(
527 "IN LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningInbound ? "enabled" : "disabled");
528
529 MainConsole.Instance.OutputFormat(
530 "OUT LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningOutbound ? "enabled" : "disabled");
531
532 MainConsole.Instance.OutputFormat("LLUDP pools in {0} are {1}", m_scene.Name, UsePools ? "on" : "off");
533 } 336 }
534 337
535 public bool HandlesRegion(Location x) 338 public bool HandlesRegion(Location x)
@@ -613,8 +416,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
613 byte[] data = packet.ToBytes(); 416 byte[] data = packet.ToBytes();
614 SendPacketData(udpClient, data, packet.Type, category, method); 417 SendPacketData(udpClient, data, packet.Type, category, method);
615 } 418 }
616
617 PacketPool.Instance.ReturnPacket(packet);
618 } 419 }
619 420
620 /// <summary> 421 /// <summary>
@@ -899,7 +700,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
899 LLUDPClient udpClient = null; 700 LLUDPClient udpClient = null;
900 Packet packet = null; 701 Packet packet = null;
901 int packetEnd = buffer.DataLength - 1; 702 int packetEnd = buffer.DataLength - 1;
902 IPEndPoint endPoint = (IPEndPoint)buffer.RemoteEndPoint; 703 IPEndPoint address = (IPEndPoint)buffer.RemoteEndPoint;
903 704
904 #region Decoding 705 #region Decoding
905 706
@@ -909,7 +710,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
909// "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}", 710// "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}",
910// buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); 711// buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
911 712
912 return; // Drop undersized packet 713 return; // Drop undersizd packet
913 } 714 }
914 715
915 int headerLen = 7; 716 int headerLen = 7;
@@ -932,13 +733,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
932 733
933 try 734 try
934 { 735 {
935// packet = Packet.BuildPacket(buffer.Data, ref packetEnd, 736 packet = Packet.BuildPacket(buffer.Data, ref packetEnd,
936// // Only allocate a buffer for zerodecoding if the packet is zerocoded
937// ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null);
938 // If OpenSimUDPBase.UsePool == true (which is currently separate from the PacketPool) then we
939 // assume that packet construction does not retain a reference to byte[] buffer.Data (instead, all
940 // bytes are copied out).
941 packet = PacketPool.Instance.GetPacket(buffer.Data, ref packetEnd,
942 // Only allocate a buffer for zerodecoding if the packet is zerocoded 737 // Only allocate a buffer for zerodecoding if the packet is zerocoded
943 ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); 738 ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null);
944 } 739 }
@@ -953,13 +748,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
953 748
954 return; // Drop short packet 749 return; // Drop short packet
955 } 750 }
956 catch (Exception e) 751 catch(Exception e)
957 { 752 {
958 if (m_malformedCount < 100) 753 if (m_malformedCount < 100)
959 m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString()); 754 m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString());
960
961 m_malformedCount++; 755 m_malformedCount++;
962
963 if ((m_malformedCount % 100000) == 0) 756 if ((m_malformedCount % 100000) == 0)
964 m_log.DebugFormat("[LLUDPSERVER]: Received {0} malformed packets so far, probable network attack.", m_malformedCount); 757 m_log.DebugFormat("[LLUDPSERVER]: Received {0} malformed packets so far, probable network attack.", m_malformedCount);
965 } 758 }
@@ -979,7 +772,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
979 772
980 // If there is already a client for this endpoint, don't process UseCircuitCode 773 // If there is already a client for this endpoint, don't process UseCircuitCode
981 IClientAPI client = null; 774 IClientAPI client = null;
982 if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView)) 775 if (!m_scene.TryGetClient(address, out client))
983 { 776 {
984 // UseCircuitCode handling 777 // UseCircuitCode handling
985 if (packet.Type == PacketType.UseCircuitCode) 778 if (packet.Type == PacketType.UseCircuitCode)
@@ -987,15 +780,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
987 // And if there is a UseCircuitCode pending, also drop it 780 // And if there is a UseCircuitCode pending, also drop it
988 lock (m_pendingCache) 781 lock (m_pendingCache)
989 { 782 {
990 if (m_pendingCache.Contains(endPoint)) 783 if (m_pendingCache.Contains(address))
991 return; 784 return;
992 785
993 m_pendingCache.AddOrUpdate(endPoint, new Queue<UDPPacketBuffer>(), 60); 786 m_pendingCache.AddOrUpdate(address, new Queue<UDPPacketBuffer>(), 60);
994 } 787 }
995 788
996 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the 789 object[] array = new object[] { buffer, packet };
997 // buffer.
998 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
999 790
1000 Util.FireAndForget(HandleUseCircuitCode, array); 791 Util.FireAndForget(HandleUseCircuitCode, array);
1001 792
@@ -1007,7 +798,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1007 lock (m_pendingCache) 798 lock (m_pendingCache)
1008 { 799 {
1009 Queue<UDPPacketBuffer> queue; 800 Queue<UDPPacketBuffer> queue;
1010 if (m_pendingCache.TryGetValue(endPoint, out queue)) 801 if (m_pendingCache.TryGetValue(address, out queue))
1011 { 802 {
1012 //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type); 803 //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type);
1013 queue.Enqueue(buffer); 804 queue.Enqueue(buffer);
@@ -1043,10 +834,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1043 // Handle appended ACKs 834 // Handle appended ACKs
1044 if (packet.Header.AppendedAcks && packet.Header.AckList != null) 835 if (packet.Header.AppendedAcks && packet.Header.AckList != null)
1045 { 836 {
1046// m_log.DebugFormat(
1047// "[LLUDPSERVER]: Handling {0} appended acks from {1} in {2}",
1048// packet.Header.AckList.Length, client.Name, m_scene.Name);
1049
1050 for (int i = 0; i < packet.Header.AckList.Length; i++) 837 for (int i = 0; i < packet.Header.AckList.Length; i++)
1051 udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent); 838 udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent);
1052 } 839 }
@@ -1056,10 +843,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1056 { 843 {
1057 PacketAckPacket ackPacket = (PacketAckPacket)packet; 844 PacketAckPacket ackPacket = (PacketAckPacket)packet;
1058 845
1059// m_log.DebugFormat(
1060// "[LLUDPSERVER]: Handling {0} packet acks for {1} in {2}",
1061// ackPacket.Packets.Length, client.Name, m_scene.Name);
1062
1063 for (int i = 0; i < ackPacket.Packets.Length; i++) 846 for (int i = 0; i < ackPacket.Packets.Length; i++)
1064 udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent); 847 udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent);
1065 848
@@ -1073,10 +856,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1073 856
1074 if (packet.Header.Reliable) 857 if (packet.Header.Reliable)
1075 { 858 {
1076// m_log.DebugFormat(
1077// "[LLUDPSERVER]: Adding ack request for {0} {1} from {2} in {3}",
1078// packet.Type, packet.Header.Sequence, client.Name, m_scene.Name);
1079
1080 udpClient.PendingAcks.Enqueue(packet.Header.Sequence); 859 udpClient.PendingAcks.Enqueue(packet.Header.Sequence);
1081 860
1082 // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out, 861 // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out,
@@ -1123,8 +902,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1123 902
1124 if (packet.Type == PacketType.StartPingCheck) 903 if (packet.Type == PacketType.StartPingCheck)
1125 { 904 {
1126// m_log.DebugFormat("[LLUDPSERVER]: Handling ping from {0} in {1}", client.Name, m_scene.Name);
1127
1128 // We don't need to do anything else with ping checks 905 // We don't need to do anything else with ping checks
1129 StartPingCheckPacket startPing = (StartPingCheckPacket)packet; 906 StartPingCheckPacket startPing = (StartPingCheckPacket)packet;
1130 CompletePing(udpClient, startPing.PingID.PingID); 907 CompletePing(udpClient, startPing.PingID.PingID);
@@ -1144,25 +921,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1144 921
1145 #endregion Ping Check Handling 922 #endregion Ping Check Handling
1146 923
1147 IncomingPacket incomingPacket;
1148
1149 // Inbox insertion 924 // Inbox insertion
1150 if (UsePools) 925 if (packet.Type == PacketType.AgentUpdate ||
1151 { 926 packet.Type == PacketType.ChatFromViewer)
1152 incomingPacket = m_incomingPacketPool.GetObject(); 927 packetInbox.EnqueueHigh(new IncomingPacket((LLClientView)client, packet));
1153 incomingPacket.Client = (LLClientView)client;
1154 incomingPacket.Packet = packet;
1155 }
1156 else
1157 {
1158 incomingPacket = new IncomingPacket((LLClientView)client, packet);
1159 }
1160
1161 if (incomingPacket.Packet.Type == PacketType.AgentUpdate ||
1162 incomingPacket.Packet.Type == PacketType.ChatFromViewer)
1163 packetInbox.EnqueueHigh(incomingPacket);
1164 else 928 else
1165 packetInbox.EnqueueLow(incomingPacket); 929 packetInbox.EnqueueLow(new IncomingPacket((LLClientView)client, packet));
930// packetInbox.Enqueue(new IncomingPacket((LLClientView)client, packet));
1166 } 931 }
1167 932
1168 #region BinaryStats 933 #region BinaryStats
@@ -1248,19 +1013,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1248 1013
1249 private void HandleUseCircuitCode(object o) 1014 private void HandleUseCircuitCode(object o)
1250 { 1015 {
1251 IPEndPoint endPoint = null; 1016 IPEndPoint remoteEndPoint = null;
1252 IClientAPI client = null; 1017 IClientAPI client = null;
1253 1018
1254 try 1019 try
1255 { 1020 {
1256 // DateTime startTime = DateTime.Now; 1021 // DateTime startTime = DateTime.Now;
1257 object[] array = (object[])o; 1022 object[] array = (object[])o;
1258 endPoint = (IPEndPoint)array[0]; 1023 UDPPacketBuffer buffer = (UDPPacketBuffer)array[0];
1259 UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1]; 1024 UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1];
1260 1025
1261 m_log.DebugFormat( 1026 m_log.DebugFormat(
1262 "[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}", 1027 "[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}",
1263 uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, endPoint); 1028 uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, buffer.RemoteEndPoint);
1029
1030 remoteEndPoint = (IPEndPoint)buffer.RemoteEndPoint;
1264 1031
1265 AuthenticateResponse sessionInfo; 1032 AuthenticateResponse sessionInfo;
1266 if (IsClientAuthorized(uccp, out sessionInfo)) 1033 if (IsClientAuthorized(uccp, out sessionInfo))
@@ -1271,13 +1038,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1271 uccp.CircuitCode.Code, 1038 uccp.CircuitCode.Code,
1272 uccp.CircuitCode.ID, 1039 uccp.CircuitCode.ID,
1273 uccp.CircuitCode.SessionID, 1040 uccp.CircuitCode.SessionID,
1274 endPoint, 1041 remoteEndPoint,
1275 sessionInfo); 1042 sessionInfo);
1276 1043
1277 // Send ack straight away to let the viewer know that the connection is active. 1044 // Send ack straight away to let the viewer know that the connection is active.
1278 // The client will be null if it already exists (e.g. if on a region crossing the client sends a use 1045 // The client will be null if it already exists (e.g. if on a region crossing the client sends a use
1279 // circuit code to the existing child agent. This is not particularly obvious. 1046 // circuit code to the existing child agent. This is not particularly obvious.
1280 SendAckImmediate(endPoint, uccp.Header.Sequence); 1047 SendAckImmediate(remoteEndPoint, uccp.Header.Sequence);
1281 1048
1282 // We only want to send initial data to new clients, not ones which are being converted from child to root. 1049 // We only want to send initial data to new clients, not ones which are being converted from child to root.
1283 if (client != null) 1050 if (client != null)
@@ -1291,12 +1058,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1291 1058
1292 lock (m_pendingCache) 1059 lock (m_pendingCache)
1293 { 1060 {
1294 if (!m_pendingCache.TryGetValue(endPoint, out queue)) 1061 if (!m_pendingCache.TryGetValue(remoteEndPoint, out queue))
1295 { 1062 {
1296 m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present"); 1063 m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present");
1297 return; 1064 return;
1298 } 1065 }
1299 m_pendingCache.Remove(endPoint); 1066 m_pendingCache.Remove(remoteEndPoint);
1300 } 1067 }
1301 1068
1302 m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count); 1069 m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count);
@@ -1314,9 +1081,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1314 // Don't create clients for unauthorized requesters. 1081 // Don't create clients for unauthorized requesters.
1315 m_log.WarnFormat( 1082 m_log.WarnFormat(
1316 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", 1083 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}",
1317 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint); 1084 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, remoteEndPoint);
1318 lock (m_pendingCache) 1085 lock (m_pendingCache)
1319 m_pendingCache.Remove(endPoint); 1086 m_pendingCache.Remove(remoteEndPoint);
1320 } 1087 }
1321 1088
1322 // m_log.DebugFormat( 1089 // m_log.DebugFormat(
@@ -1328,7 +1095,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1328 { 1095 {
1329 m_log.ErrorFormat( 1096 m_log.ErrorFormat(
1330 "[LLUDPSERVER]: UseCircuitCode handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}", 1097 "[LLUDPSERVER]: UseCircuitCode handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}",
1331 endPoint != null ? endPoint.ToString() : "n/a", 1098 remoteEndPoint != null ? remoteEndPoint.ToString() : "n/a",
1332 client != null ? client.Name : "unknown", 1099 client != null ? client.Name : "unknown",
1333 client != null ? client.AgentId.ToString() : "unknown", 1100 client != null ? client.AgentId.ToString() : "unknown",
1334 e.Message, 1101 e.Message,
@@ -1393,20 +1160,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1393 { 1160 {
1394 IClientAPI client = null; 1161 IClientAPI client = null;
1395 1162
1396 // We currently synchronize this code across the whole scene to avoid issues such as 1163 // In priciple there shouldn't be more than one thread here, ever.
1397 // http://opensimulator.org/mantis/view.php?id=5365 However, once locking per agent circuit can be done 1164 // But in case that happens, we need to synchronize this piece of code
1398 // consistently, this lock could probably be removed. 1165 // because it's too important
1399 lock (this) 1166 lock (this)
1400 { 1167 {
1401 if (!m_scene.TryGetClient(agentID, out client)) 1168 if (!m_scene.TryGetClient(agentID, out client))
1402 { 1169 {
1403 LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); 1170 LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO);
1404 1171
1405 client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); 1172 client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode);
1406 client.OnLogout += LogoutHandler; 1173 client.OnLogout += LogoutHandler;
1407 1174
1408 ((LLClientView)client).DisableFacelights = m_disableFacelights; 1175 ((LLClientView)client).DisableFacelights = m_disableFacelights;
1409 1176
1410 client.Start(); 1177 client.Start();
1411 } 1178 }
1412 } 1179 }
@@ -1445,7 +1212,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1445 // on to en-US to avoid number parsing issues 1212 // on to en-US to avoid number parsing issues
1446 Culture.SetCurrentCulture(); 1213 Culture.SetCurrentCulture();
1447 1214
1448 while (IsRunningInbound) 1215 while (base.IsRunning)
1449 { 1216 {
1450 m_scene.ThreadAlive(1); 1217 m_scene.ThreadAlive(1);
1451 try 1218 try
@@ -1461,12 +1228,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1461 } 1228 }
1462 1229
1463 if (packetInbox.Dequeue(100, ref incomingPacket)) 1230 if (packetInbox.Dequeue(100, ref incomingPacket))
1464 {
1465 ProcessInPacket(incomingPacket);//, incomingPacket); Util.FireAndForget(ProcessInPacket, incomingPacket); 1231 ProcessInPacket(incomingPacket);//, incomingPacket); Util.FireAndForget(ProcessInPacket, incomingPacket);
1466
1467 if (UsePools)
1468 m_incomingPacketPool.ReturnObject(incomingPacket);
1469 }
1470 } 1232 }
1471 catch (Exception ex) 1233 catch (Exception ex)
1472 { 1234 {
@@ -1493,7 +1255,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1493 // Action generic every round 1255 // Action generic every round
1494 Action<IClientAPI> clientPacketHandler = ClientOutgoingPacketHandler; 1256 Action<IClientAPI> clientPacketHandler = ClientOutgoingPacketHandler;
1495 1257
1496 while (base.IsRunningOutbound) 1258 while (base.IsRunning)
1497 { 1259 {
1498 m_scene.ThreadAlive(2); 1260 m_scene.ThreadAlive(2);
1499 try 1261 try
@@ -1761,7 +1523,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1761 if (!client.IsLoggingOut) 1523 if (!client.IsLoggingOut)
1762 { 1524 {
1763 client.IsLoggingOut = true; 1525 client.IsLoggingOut = true;
1764 client.Close(false, false); 1526 client.Close(false);
1765 } 1527 }
1766 } 1528 }
1767 } 1529 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
index 8bd3461..cfe7c9d 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
@@ -30,8 +30,6 @@ using System.Net;
30using System.Net.Sockets; 30using System.Net.Sockets;
31using System.Threading; 31using System.Threading;
32using log4net; 32using log4net;
33using OpenSim.Framework;
34using OpenSim.Framework.Monitoring;
35 33
36namespace OpenMetaverse 34namespace OpenMetaverse
37{ 35{
@@ -60,31 +58,17 @@ namespace OpenMetaverse
60 /// <summary>Flag to process packets asynchronously or synchronously</summary> 58 /// <summary>Flag to process packets asynchronously or synchronously</summary>
61 private bool m_asyncPacketHandling; 59 private bool m_asyncPacketHandling;
62 60
63 /// <summary> 61 /// <summary>The all important shutdown flag</summary>
64 /// Pool to use for handling data. May be null if UsePools = false; 62 private volatile bool m_shutdownFlag = true;
65 /// </summary>
66 protected OpenSim.Framework.Pool<UDPPacketBuffer> m_pool;
67
68 /// <summary>
69 /// Are we to use object pool(s) to reduce memory churn when receiving data?
70 /// </summary>
71 public bool UsePools { get; protected set; }
72
73 /// <summary>Returns true if the server is currently listening for inbound packets, otherwise false</summary>
74 public bool IsRunningInbound { get; private set; }
75 63
76 /// <summary>Returns true if the server is currently sending outbound packets, otherwise false</summary> 64 /// <summary>Returns true if the server is currently listening, otherwise false</summary>
77 /// <remarks>If IsRunningOut = false, then any request to send a packet is simply dropped.</remarks> 65 public bool IsRunning { get { return !m_shutdownFlag; } }
78 public bool IsRunningOutbound { get; private set; }
79
80 private Stat m_poolCountStat;
81 66
82 /// <summary> 67 /// <summary>
83 /// Default constructor 68 /// Default constructor
84 /// </summary> 69 /// </summary>
85 /// <param name="bindAddress">Local IP address to bind the server to</param> 70 /// <param name="bindAddress">Local IP address to bind the server to</param>
86 /// <param name="port">Port to listening for incoming UDP packets on</param> 71 /// <param name="port">Port to listening for incoming UDP packets on</param>
87 /// /// <param name="usePool">Are we to use an object pool to get objects for handing inbound data?</param>
88 public OpenSimUDPBase(IPAddress bindAddress, int port) 72 public OpenSimUDPBase(IPAddress bindAddress, int port)
89 { 73 {
90 m_localBindAddress = bindAddress; 74 m_localBindAddress = bindAddress;
@@ -92,7 +76,7 @@ namespace OpenMetaverse
92 } 76 }
93 77
94 /// <summary> 78 /// <summary>
95 /// Start inbound UDP packet handling. 79 /// Start the UDP server
96 /// </summary> 80 /// </summary>
97 /// <param name="recvBufferSize">The size of the receive buffer for 81 /// <param name="recvBufferSize">The size of the receive buffer for
98 /// the UDP socket. This value is passed up to the operating system 82 /// the UDP socket. This value is passed up to the operating system
@@ -107,11 +91,11 @@ namespace OpenMetaverse
107 /// manner (not throwing an exception when the remote side resets the 91 /// manner (not throwing an exception when the remote side resets the
108 /// connection). This call is ignored on Mono where the flag is not 92 /// connection). This call is ignored on Mono where the flag is not
109 /// necessary</remarks> 93 /// necessary</remarks>
110 public void StartInbound(int recvBufferSize, bool asyncPacketHandling) 94 public void Start(int recvBufferSize, bool asyncPacketHandling)
111 { 95 {
112 m_asyncPacketHandling = asyncPacketHandling; 96 m_asyncPacketHandling = asyncPacketHandling;
113 97
114 if (!IsRunningInbound) 98 if (m_shutdownFlag)
115 { 99 {
116 const int SIO_UDP_CONNRESET = -1744830452; 100 const int SIO_UDP_CONNRESET = -1744830452;
117 101
@@ -139,7 +123,8 @@ namespace OpenMetaverse
139 123
140 m_udpSocket.Bind(ipep); 124 m_udpSocket.Bind(ipep);
141 125
142 IsRunningInbound = true; 126 // we're not shutting down, we're starting up
127 m_shutdownFlag = false;
143 128
144 // kick off an async receive. The Start() method will return, the 129 // kick off an async receive. The Start() method will return, the
145 // actual receives will occur asynchronously and will be caught in 130 // actual receives will occur asynchronously and will be caught in
@@ -149,84 +134,28 @@ namespace OpenMetaverse
149 } 134 }
150 135
151 /// <summary> 136 /// <summary>
152 /// Start outbound UDP packet handling. 137 /// Stops the UDP server
153 /// </summary> 138 /// </summary>
154 public void StartOutbound() 139 public void Stop()
155 {
156 IsRunningOutbound = true;
157 }
158
159 public void StopInbound()
160 { 140 {
161 if (IsRunningInbound) 141 if (!m_shutdownFlag)
162 { 142 {
163 // wait indefinitely for a writer lock. Once this is called, the .NET runtime 143 // wait indefinitely for a writer lock. Once this is called, the .NET runtime
164 // will deny any more reader locks, in effect blocking all other send/receive 144 // will deny any more reader locks, in effect blocking all other send/receive
165 // threads. Once we have the lock, we set IsRunningInbound = false to inform the other 145 // threads. Once we have the lock, we set shutdownFlag to inform the other
166 // threads that the socket is closed. 146 // threads that the socket is closed.
167 IsRunningInbound = false; 147 m_shutdownFlag = true;
168 m_udpSocket.Close(); 148 m_udpSocket.Close();
169 } 149 }
170 } 150 }
171 151
172 public void StopOutbound()
173 {
174 IsRunningOutbound = false;
175 }
176
177 protected virtual bool EnablePools()
178 {
179 if (!UsePools)
180 {
181 m_pool = new Pool<UDPPacketBuffer>(() => new UDPPacketBuffer(), 500);
182
183 m_poolCountStat
184 = new Stat(
185 "UDPPacketBufferPoolCount",
186 "Objects within the UDPPacketBuffer pool",
187 "The number of objects currently stored within the UDPPacketBuffer pool",
188 "",
189 "clientstack",
190 "packetpool",
191 StatType.Pull,
192 stat => stat.Value = m_pool.Count,
193 StatVerbosity.Debug);
194
195 StatsManager.RegisterStat(m_poolCountStat);
196
197 UsePools = true;
198
199 return true;
200 }
201
202 return false;
203 }
204
205 protected virtual bool DisablePools()
206 {
207 if (UsePools)
208 {
209 UsePools = false;
210 StatsManager.DeregisterStat(m_poolCountStat);
211
212 // We won't null out the pool to avoid a race condition with code that may be in the middle of using it.
213
214 return true;
215 }
216
217 return false;
218 }
219
220 private void AsyncBeginReceive() 152 private void AsyncBeginReceive()
221 { 153 {
222 UDPPacketBuffer buf; 154 // allocate a packet buffer
223 155 //WrappedObject<UDPPacketBuffer> wrappedBuffer = Pool.CheckOut();
224 if (UsePools) 156 UDPPacketBuffer buf = new UDPPacketBuffer();
225 buf = m_pool.GetObject();
226 else
227 buf = new UDPPacketBuffer();
228 157
229 if (IsRunningInbound) 158 if (!m_shutdownFlag)
230 { 159 {
231 try 160 try
232 { 161 {
@@ -279,7 +208,7 @@ namespace OpenMetaverse
279 { 208 {
280 // Asynchronous receive operations will complete here through the call 209 // Asynchronous receive operations will complete here through the call
281 // to AsyncBeginReceive 210 // to AsyncBeginReceive
282 if (IsRunningInbound) 211 if (!m_shutdownFlag)
283 { 212 {
284 // Asynchronous mode will start another receive before the 213 // Asynchronous mode will start another receive before the
285 // callback for this packet is even fired. Very parallel :-) 214 // callback for this packet is even fired. Very parallel :-)
@@ -288,6 +217,8 @@ namespace OpenMetaverse
288 217
289 // get the buffer that was created in AsyncBeginReceive 218 // get the buffer that was created in AsyncBeginReceive
290 // this is the received data 219 // this is the received data
220 //WrappedObject<UDPPacketBuffer> wrappedBuffer = (WrappedObject<UDPPacketBuffer>)iar.AsyncState;
221 //UDPPacketBuffer buffer = wrappedBuffer.Instance;
291 UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState; 222 UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState;
292 223
293 try 224 try
@@ -304,8 +235,7 @@ namespace OpenMetaverse
304 catch (ObjectDisposedException) { } 235 catch (ObjectDisposedException) { }
305 finally 236 finally
306 { 237 {
307 if (UsePools) 238 //wrappedBuffer.Dispose();
308 m_pool.ReturnObject(buffer);
309 239
310 // Synchronous mode waits until the packet callback completes 240 // Synchronous mode waits until the packet callback completes
311 // before starting the receive to fetch another packet 241 // before starting the receive to fetch another packet
@@ -318,7 +248,7 @@ namespace OpenMetaverse
318 248
319 public void AsyncBeginSend(UDPPacketBuffer buf) 249 public void AsyncBeginSend(UDPPacketBuffer buf)
320 { 250 {
321 if (IsRunningOutbound) 251 if (!m_shutdownFlag)
322 { 252 {
323 try 253 try
324 { 254 {
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs
index 556df30..109a8e1 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs
@@ -43,7 +43,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
43 /// This will contain basic tests for the LindenUDP client stack 43 /// This will contain basic tests for the LindenUDP client stack
44 /// </summary> 44 /// </summary>
45 [TestFixture] 45 [TestFixture]
46 public class BasicCircuitTests : OpenSimTestCase 46 public class BasicCircuitTests
47 { 47 {
48 private Scene m_scene; 48 private Scene m_scene;
49 private TestLLUDPServer m_udpServer; 49 private TestLLUDPServer m_udpServer;
@@ -65,9 +65,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
65 } 65 }
66 66
67 [SetUp] 67 [SetUp]
68 public override void SetUp() 68 public void SetUp()
69 { 69 {
70 base.SetUp();
71 m_scene = new SceneHelpers().SetupScene(); 70 m_scene = new SceneHelpers().SetupScene();
72 } 71 }
73 72
@@ -144,7 +143,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
144 public void TestAddClient() 143 public void TestAddClient()
145 { 144 {
146 TestHelpers.InMethod(); 145 TestHelpers.InMethod();
147// TestHelpers.EnableLogging(); 146// XmlConfigurator.Configure();
148 147
149 AddUdpServer(); 148 AddUdpServer();
150 149
diff --git a/OpenSim/Region/ClientStack/RegionApplicationBase.cs b/OpenSim/Region/ClientStack/RegionApplicationBase.cs
index 853b72d..4672f8a 100644
--- a/OpenSim/Region/ClientStack/RegionApplicationBase.cs
+++ b/OpenSim/Region/ClientStack/RegionApplicationBase.cs
@@ -76,7 +76,7 @@ namespace OpenSim.Region.ClientStack
76 76
77 protected override void StartupSpecific() 77 protected override void StartupSpecific()
78 { 78 {
79 SceneManager = SceneManager.Instance; 79 SceneManager = new SceneManager();
80 m_clientStackManager = CreateClientStackManager(); 80 m_clientStackManager = CreateClientStackManager();
81 81
82 Initialize(); 82 Initialize();
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
index da1ff2e..8a4fd8f 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
@@ -57,36 +57,39 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
57 } 57 }
58 58
59 /// <summary> 59 /// <summary>
60 /// Return the xfer uploader for the given transaction. 60 /// Return a xfer uploader if one does not already exist.
61 /// </summary> 61 /// </summary>
62 /// <remarks>
63 /// If an uploader does not already exist for this transaction then it is created, otherwise the existing
64 /// uploader is returned.
65 /// </remarks>
66 /// <param name="transactionID"></param> 62 /// <param name="transactionID"></param>
67 /// <returns>The asset xfer uploader</returns> 63 /// <param name="assetID">
68 public AssetXferUploader RequestXferUploader(UUID transactionID) 64 /// We must transfer the new asset ID into the uploader on creation, otherwise
65 /// we can see race conditions with other threads which can retrieve an item before it is updated with the new
66 /// asset id.
67 /// </param>
68 /// <returns>
69 /// The xfer uploader requested. Null if one is already in existence.
70 /// FIXME: This is a bizarre thing to do, and is probably meant to signal an error condition if multiple
71 /// transfers are made. Needs to be corrected.
72 /// </returns>
73 public AssetXferUploader RequestXferUploader(UUID transactionID, UUID assetID)
69 { 74 {
70 AssetXferUploader uploader;
71
72 lock (XferUploaders) 75 lock (XferUploaders)
73 { 76 {
74 if (!XferUploaders.ContainsKey(transactionID)) 77 if (!XferUploaders.ContainsKey(transactionID))
75 { 78 {
76 uploader = new AssetXferUploader(this, m_Scene, transactionID, m_dumpAssetsToFile); 79 AssetXferUploader uploader = new AssetXferUploader(this, m_Scene, assetID, m_dumpAssetsToFile);
77 80
78// m_log.DebugFormat( 81// m_log.DebugFormat(
79// "[AGENT ASSETS TRANSACTIONS]: Adding asset xfer uploader {0} since it didn't previously exist", transactionID); 82// "[AGENT ASSETS TRANSACTIONS]: Adding asset xfer uploader {0} since it didn't previously exist", transactionID);
80 83
81 XferUploaders.Add(transactionID, uploader); 84 XferUploaders.Add(transactionID, uploader);
82 } 85
83 else 86 return uploader;
84 {
85 uploader = XferUploaders[transactionID];
86 } 87 }
87 } 88 }
88 89
89 return uploader; 90 m_log.WarnFormat("[AGENT ASSETS TRANSACTIONS]: Ignoring request for asset xfer uploader {0} since it already exists", transactionID);
91
92 return null;
90 } 93 }
91 94
92 public void HandleXfer(ulong xferID, uint packetID, byte[] data) 95 public void HandleXfer(ulong xferID, uint packetID, byte[] data)
@@ -148,30 +151,117 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
148 string description, string name, sbyte invType, 151 string description, string name, sbyte invType,
149 sbyte type, byte wearableType, uint nextOwnerMask) 152 sbyte type, byte wearableType, uint nextOwnerMask)
150 { 153 {
151 AssetXferUploader uploader = RequestXferUploader(transactionID); 154 AssetXferUploader uploader = null;
155
156 lock (XferUploaders)
157 {
158 if (XferUploaders.ContainsKey(transactionID))
159 uploader = XferUploaders[transactionID];
160 }
152 161
153 uploader.RequestCreateInventoryItem( 162 if (uploader != null)
154 remoteClient, folderID, callbackID, 163 {
155 description, name, invType, type, wearableType, nextOwnerMask); 164 uploader.RequestCreateInventoryItem(
165 remoteClient, transactionID, folderID,
166 callbackID, description, name, invType, type,
167 wearableType, nextOwnerMask);
156 168
157 return true; 169 return true;
170 }
171
172 return false;
173 }
174
175 /// <summary>
176 /// Get an uploaded asset. If the data is successfully retrieved,
177 /// the transaction will be removed.
178 /// </summary>
179 /// <param name="transactionID"></param>
180 /// <returns>The asset if the upload has completed, null if it has not.</returns>
181 private AssetBase GetTransactionAsset(UUID transactionID)
182 {
183 lock (XferUploaders)
184 {
185 if (XferUploaders.ContainsKey(transactionID))
186 {
187 AssetXferUploader uploader = XferUploaders[transactionID];
188 AssetBase asset = uploader.GetAssetData();
189 RemoveXferUploader(transactionID);
190
191 return asset;
192 }
193 }
194
195 return null;
158 } 196 }
159 197
160 public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient, 198 public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient,
161 SceneObjectPart part, UUID transactionID, 199 SceneObjectPart part, UUID transactionID,
162 TaskInventoryItem item) 200 TaskInventoryItem item)
163 { 201 {
164 AssetXferUploader uploader = RequestXferUploader(transactionID); 202 AssetXferUploader uploader = null;
203
204 lock (XferUploaders)
205 {
206 if (XferUploaders.ContainsKey(transactionID))
207 uploader = XferUploaders[transactionID];
208 }
209
210 if (uploader != null)
211 {
212 AssetBase asset = GetTransactionAsset(transactionID);
213
214 // Only legacy viewers use this, and they prefer CAPS, which
215 // we have, so this really never runs.
216 // Allow it, but only for "safe" types.
217 if ((InventoryType)item.InvType != InventoryType.Notecard &&
218 (InventoryType)item.InvType != InventoryType.LSL)
219 return;
165 220
166 uploader.RequestUpdateTaskInventoryItem(remoteClient, item); 221 if (asset != null)
222 {
223// m_log.DebugFormat(
224// "[AGENT ASSETS TRANSACTIONS]: Updating item {0} in {1} for transaction {2}",
225// item.Name, part.Name, transactionID);
226
227 asset.FullID = UUID.Random();
228 asset.Name = item.Name;
229 asset.Description = item.Description;
230 asset.Type = (sbyte)item.Type;
231 item.AssetID = asset.FullID;
232
233 m_Scene.AssetService.Store(asset);
234 }
235 }
236 else
237 {
238 m_log.ErrorFormat(
239 "[AGENT ASSET TRANSACTIONS]: Could not find uploader with transaction ID {0} when handling request to update task inventory item {1} in {2}",
240 transactionID, item.Name, part.Name);
241 }
167 } 242 }
168 243
169 public void RequestUpdateInventoryItem(IClientAPI remoteClient, 244 public void RequestUpdateInventoryItem(IClientAPI remoteClient,
170 UUID transactionID, InventoryItemBase item) 245 UUID transactionID, InventoryItemBase item)
171 { 246 {
172 AssetXferUploader uploader = RequestXferUploader(transactionID); 247 AssetXferUploader uploader = null;
248
249 lock (XferUploaders)
250 {
251 if (XferUploaders.ContainsKey(transactionID))
252 uploader = XferUploaders[transactionID];
253 }
173 254
174 uploader.RequestUpdateInventoryItem(remoteClient, item); 255 if (uploader != null)
256 {
257 uploader.RequestUpdateInventoryItem(remoteClient, transactionID, item);
258 }
259 else
260 {
261 m_log.ErrorFormat(
262 "[AGENT ASSET TRANSACTIONS]: Could not find uploader with transaction ID {0} when handling request to update inventory item {1} for {2}",
263 transactionID, item.Name, remoteClient.Name);
264 }
175 } 265 }
176 } 266 }
177} 267}
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
index 4bb8986..441c4ff 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
@@ -215,7 +215,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
215 IClientAPI remoteClient, SceneObjectPart part, UUID transactionID, TaskInventoryItem item) 215 IClientAPI remoteClient, SceneObjectPart part, UUID transactionID, TaskInventoryItem item)
216 { 216 {
217 m_log.DebugFormat( 217 m_log.DebugFormat(
218 "[ASSET TRANSACTION MODULE] Called HandleTaskItemUpdateFromTransaction with item {0} in {1} for {2} in {3}", 218 "[TRANSACTIONS MANAGER] Called HandleTaskItemUpdateFromTransaction with item {0} in {1} for {2} in {3}",
219 item.Name, part.Name, remoteClient.Name, m_Scene.RegionInfo.RegionName); 219 item.Name, part.Name, remoteClient.Name, m_Scene.RegionInfo.RegionName);
220 220
221 AgentAssetTransactions transactions = 221 AgentAssetTransactions transactions =
@@ -274,8 +274,13 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
274 } 274 }
275 275
276 AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); 276 AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId);
277 AssetXferUploader uploader = transactions.RequestXferUploader(transaction); 277 AssetXferUploader uploader = transactions.RequestXferUploader(transaction, assetID);
278 uploader.StartUpload(remoteClient, assetID, transaction, type, data, storeLocal, tempFile); 278
279 if (uploader != null)
280 {
281 uploader.Initialise(remoteClient, assetID, transaction, type,
282 data, storeLocal, tempFile);
283 }
279 } 284 }
280 285
281 /// <summary> 286 /// <summary>
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
index f6dd5af..4cedfe6 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
@@ -49,75 +49,39 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50 50
51 /// <summary> 51 /// <summary>
52 /// Upload state.
53 /// </summary>
54 /// <remarks>
55 /// New -> Uploading -> Complete
56 /// </remarks>
57 private enum UploadState
58 {
59 New,
60 Uploading,
61 Complete
62 }
63
64 /// <summary>
65 /// Reference to the object that holds this uploader. Used to remove ourselves from it's list if we 52 /// Reference to the object that holds this uploader. Used to remove ourselves from it's list if we
66 /// are performing a delayed update. 53 /// are performing a delayed update.
67 /// </summary> 54 /// </summary>
68 AgentAssetTransactions m_transactions; 55 AgentAssetTransactions m_transactions;
69 56
70 private UploadState m_uploadState = UploadState.New;
71
72 private AssetBase m_asset; 57 private AssetBase m_asset;
73 private UUID InventFolder = UUID.Zero; 58 private UUID InventFolder = UUID.Zero;
74 private sbyte invType = 0; 59 private sbyte invType = 0;
75 60
76 private bool m_createItem; 61 private bool m_createItem = false;
77 private uint m_createItemCallback; 62 private uint m_createItemCallback = 0;
78 63 private bool m_updateItem = false;
79 private bool m_updateItem;
80 private InventoryItemBase m_updateItemData; 64 private InventoryItemBase m_updateItemData;
81 65
82 private bool m_updateTaskItem;
83 private TaskInventoryItem m_updateTaskItemData;
84
85 private string m_description = String.Empty; 66 private string m_description = String.Empty;
86 private bool m_dumpAssetToFile; 67 private bool m_dumpAssetToFile;
68 private bool m_finished = false;
87 private string m_name = String.Empty; 69 private string m_name = String.Empty;
88// private bool m_storeLocal; 70 private bool m_storeLocal;
89 private uint nextPerm = 0; 71 private uint nextPerm = 0;
90 private IClientAPI ourClient; 72 private IClientAPI ourClient;
91 73 private UUID TransactionID = UUID.Zero;
92 private UUID m_transactionID;
93
94 private sbyte type = 0; 74 private sbyte type = 0;
95 private byte wearableType = 0; 75 private byte wearableType = 0;
96 private byte[] m_oldData = null; 76 private byte[] m_oldData = null;
97 public ulong XferID; 77 public ulong XferID;
98 private Scene m_Scene; 78 private Scene m_Scene;
99 79
100 /// <summary> 80 public AssetXferUploader(AgentAssetTransactions transactions, Scene scene, UUID assetID, bool dumpAssetToFile)
101 /// AssetXferUploader constructor
102 /// </summary>
103 /// <param name='transactions'>/param>
104 /// <param name='scene'></param>
105 /// <param name='transactionID'></param>
106 /// <param name='dumpAssetToFile'>
107 /// If true then when the asset is uploaded it is dumped to a file with the format
108 /// String.Format("{6}_{7}_{0:d2}{1:d2}{2:d2}_{3:d2}{4:d2}{5:d2}.dat",
109 /// now.Year, now.Month, now.Day, now.Hour, now.Minute,
110 /// now.Second, m_asset.Name, m_asset.Type);
111 /// for debugging purposes.
112 /// </param>
113 public AssetXferUploader(
114 AgentAssetTransactions transactions, Scene scene, UUID transactionID, bool dumpAssetToFile)
115 { 81 {
116 m_asset = new AssetBase();
117
118 m_transactions = transactions; 82 m_transactions = transactions;
119 m_transactionID = transactionID;
120 m_Scene = scene; 83 m_Scene = scene;
84 m_asset = new AssetBase() { FullID = assetID };
121 m_dumpAssetToFile = dumpAssetToFile; 85 m_dumpAssetToFile = dumpAssetToFile;
122 } 86 }
123 87
@@ -163,50 +127,30 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
163 } 127 }
164 128
165 /// <summary> 129 /// <summary>
166 /// Start asset transfer from the client 130 /// Initialise asset transfer from the client
167 /// </summary> 131 /// </summary>
168 /// <param name="remoteClient"></param> 132 /// <param name="xferID"></param>
169 /// <param name="assetID"></param> 133 /// <param name="packetID"></param>
170 /// <param name="transaction"></param> 134 /// <param name="data"></param>
171 /// <param name="type"></param> 135 public void Initialise(IClientAPI remoteClient, UUID assetID,
172 /// <param name="data"> 136 UUID transaction, sbyte type, byte[] data, bool storeLocal,
173 /// Optional data. If present then the asset is created immediately with this data 137 bool tempFile)
174 /// rather than requesting an upload from the client. The data must be longer than 2 bytes.
175 /// </param>
176 /// <param name="storeLocal"></param>
177 /// <param name="tempFile"></param>
178 public void StartUpload(
179 IClientAPI remoteClient, UUID assetID, UUID transaction, sbyte type, byte[] data, bool storeLocal,
180 bool tempFile)
181 { 138 {
182// m_log.DebugFormat( 139// m_log.DebugFormat(
183// "[ASSET XFER UPLOADER]: Initialised xfer from {0}, asset {1}, transaction {2}, type {3}, storeLocal {4}, tempFile {5}, already received data length {6}", 140// "[ASSET XFER UPLOADER]: Initialised xfer from {0}, asset {1}, transaction {2}, type {3}, storeLocal {4}, tempFile {5}, already received data length {6}",
184// remoteClient.Name, assetID, transaction, type, storeLocal, tempFile, data.Length); 141// remoteClient.Name, assetID, transaction, type, storeLocal, tempFile, data.Length);
185 142
186 lock (this)
187 {
188 if (m_uploadState != UploadState.New)
189 {
190 m_log.WarnFormat(
191 "[ASSET XFER UPLOADER]: Tried to start upload of asset {0}, transaction {1} for {2} but this is already in state {3}. Aborting.",
192 assetID, transaction, remoteClient.Name, m_uploadState);
193
194 return;
195 }
196
197 m_uploadState = UploadState.Uploading;
198 }
199
200 ourClient = remoteClient; 143 ourClient = remoteClient;
201 144 m_asset.Name = "blank";
202 m_asset.FullID = assetID; 145 m_asset.Description = "empty";
203 m_asset.Type = type; 146 m_asset.Type = type;
204 m_asset.CreatorID = remoteClient.AgentId.ToString(); 147 m_asset.CreatorID = remoteClient.AgentId.ToString();
205 m_asset.Data = data; 148 m_asset.Data = data;
206 m_asset.Local = storeLocal; 149 m_asset.Local = storeLocal;
207 m_asset.Temporary = tempFile; 150 m_asset.Temporary = tempFile;
208 151
209// m_storeLocal = storeLocal; 152 TransactionID = transaction;
153 m_storeLocal = storeLocal;
210 154
211 if (m_asset.Data.Length > 2) 155 if (m_asset.Data.Length > 2)
212 { 156 {
@@ -231,35 +175,36 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
231 175
232 protected void SendCompleteMessage() 176 protected void SendCompleteMessage()
233 { 177 {
178 ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true,
179 m_asset.FullID);
180
234 // We must lock in order to avoid a race with a separate thread dealing with an inventory item or create 181 // We must lock in order to avoid a race with a separate thread dealing with an inventory item or create
235 // message from other client UDP. 182 // message from other client UDP.
236 lock (this) 183 lock (this)
237 { 184 {
238 m_uploadState = UploadState.Complete; 185 m_finished = true;
239
240 ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true, m_asset.FullID);
241
242 if (m_createItem) 186 if (m_createItem)
243 { 187 {
244 CompleteCreateItem(m_createItemCallback); 188 DoCreateItem(m_createItemCallback);
245 } 189 }
246 else if (m_updateItem) 190 else if (m_updateItem)
247 { 191 {
248 CompleteItemUpdate(m_updateItemData); 192 StoreAssetForItemUpdate(m_updateItemData);
193
194 // Remove ourselves from the list of transactions if completion was delayed until the transaction
195 // was complete.
196 // TODO: Should probably do the same for create item.
197 m_transactions.RemoveXferUploader(TransactionID);
249 } 198 }
250 else if (m_updateTaskItem) 199 else if (m_storeLocal)
251 { 200 {
252 CompleteTaskItemUpdate(m_updateTaskItemData); 201 m_Scene.AssetService.Store(m_asset);
253 } 202 }
254// else if (m_storeLocal)
255// {
256// m_Scene.AssetService.Store(m_asset);
257// }
258 } 203 }
259 204
260 m_log.DebugFormat( 205 m_log.DebugFormat(
261 "[ASSET XFER UPLOADER]: Uploaded asset {0} for transaction {1}", 206 "[ASSET XFER UPLOADER]: Uploaded asset {0} for transaction {1}",
262 m_asset.FullID, m_transactionID); 207 m_asset.FullID, TransactionID);
263 208
264 if (m_dumpAssetToFile) 209 if (m_dumpAssetToFile)
265 { 210 {
@@ -287,37 +232,40 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
287 } 232 }
288 233
289 public void RequestCreateInventoryItem(IClientAPI remoteClient, 234 public void RequestCreateInventoryItem(IClientAPI remoteClient,
290 UUID folderID, uint callbackID, 235 UUID transactionID, UUID folderID, uint callbackID,
291 string description, string name, sbyte invType, 236 string description, string name, sbyte invType,
292 sbyte type, byte wearableType, uint nextOwnerMask) 237 sbyte type, byte wearableType, uint nextOwnerMask)
293 { 238 {
294 InventFolder = folderID; 239 if (TransactionID == transactionID)
295 m_name = name;
296 m_description = description;
297 this.type = type;
298 this.invType = invType;
299 this.wearableType = wearableType;
300 nextPerm = nextOwnerMask;
301 m_asset.Name = name;
302 m_asset.Description = description;
303 m_asset.Type = type;
304
305 // We must lock to avoid a race with a separate thread uploading the asset.
306 lock (this)
307 { 240 {
308 if (m_uploadState == UploadState.Complete) 241 InventFolder = folderID;
242 m_name = name;
243 m_description = description;
244 this.type = type;
245 this.invType = invType;
246 this.wearableType = wearableType;
247 nextPerm = nextOwnerMask;
248 m_asset.Name = name;
249 m_asset.Description = description;
250 m_asset.Type = type;
251
252 // We must lock to avoid a race with a separate thread uploading the asset.
253 lock (this)
309 { 254 {
310 CompleteCreateItem(callbackID); 255 if (m_finished)
311 } 256 {
312 else 257 DoCreateItem(callbackID);
313 { 258 }
314 m_createItem = true; //set flag so the inventory item is created when upload is complete 259 else
315 m_createItemCallback = callbackID; 260 {
261 m_createItem = true; //set flag so the inventory item is created when upload is complete
262 m_createItemCallback = callbackID;
263 }
316 } 264 }
317 } 265 }
318 } 266 }
319 267
320 public void RequestUpdateInventoryItem(IClientAPI remoteClient, InventoryItemBase item) 268 public void RequestUpdateInventoryItem(IClientAPI remoteClient, UUID transactionID, InventoryItemBase item)
321 { 269 {
322 // We must lock to avoid a race with a separate thread uploading the asset. 270 // We must lock to avoid a race with a separate thread uploading the asset.
323 lock (this) 271 lock (this)
@@ -332,9 +280,9 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
332 item.AssetID = m_asset.FullID; 280 item.AssetID = m_asset.FullID;
333 m_Scene.InventoryService.UpdateItem(item); 281 m_Scene.InventoryService.UpdateItem(item);
334 282
335 if (m_uploadState == UploadState.Complete) 283 if (m_finished)
336 { 284 {
337 CompleteItemUpdate(item); 285 StoreAssetForItemUpdate(item);
338 } 286 }
339 else 287 else
340 { 288 {
@@ -348,59 +296,20 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
348 } 296 }
349 } 297 }
350 298
351 public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient, TaskInventoryItem taskItem)
352 {
353 // We must lock to avoid a race with a separate thread uploading the asset.
354 lock (this)
355 {
356 m_asset.Name = taskItem.Name;
357 m_asset.Description = taskItem.Description;
358 m_asset.Type = (sbyte)taskItem.Type;
359 taskItem.AssetID = m_asset.FullID;
360
361 if (m_uploadState == UploadState.Complete)
362 {
363 CompleteTaskItemUpdate(taskItem);
364 }
365 else
366 {
367 m_updateTaskItem = true;
368 m_updateTaskItemData = taskItem;
369 }
370 }
371 }
372
373 /// <summary> 299 /// <summary>
374 /// Store the asset for the given item when it has been uploaded. 300 /// Store the asset for the given item.
375 /// </summary> 301 /// </summary>
376 /// <param name="item"></param> 302 /// <param name="item"></param>
377 private void CompleteItemUpdate(InventoryItemBase item) 303 private void StoreAssetForItemUpdate(InventoryItemBase item)
378 { 304 {
379// m_log.DebugFormat( 305// m_log.DebugFormat(
380// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier item update for {1} for {2}", 306// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier item update for {1} for {2}",
381// m_asset.FullID, item.Name, ourClient.Name); 307// m_asset.FullID, item.Name, ourClient.Name);
382 308
383 m_Scene.AssetService.Store(m_asset); 309 m_Scene.AssetService.Store(m_asset);
384
385 m_transactions.RemoveXferUploader(m_transactionID);
386 }
387
388 /// <summary>
389 /// Store the asset for the given task item when it has been uploaded.
390 /// </summary>
391 /// <param name="taskItem"></param>
392 private void CompleteTaskItemUpdate(TaskInventoryItem taskItem)
393 {
394// m_log.DebugFormat(
395// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier task item update for {1} for {2}",
396// m_asset.FullID, taskItem.Name, ourClient.Name);
397
398 m_Scene.AssetService.Store(m_asset);
399
400 m_transactions.RemoveXferUploader(m_transactionID);
401 } 310 }
402 311
403 private void CompleteCreateItem(uint callbackID) 312 private void DoCreateItem(uint callbackID)
404 { 313 {
405 ValidateAssets(); 314 ValidateAssets();
406 m_Scene.AssetService.Store(m_asset); 315 m_Scene.AssetService.Store(m_asset);
@@ -430,8 +339,6 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
430 ourClient.SendInventoryItemCreateUpdate(item, callbackID); 339 ourClient.SendInventoryItemCreateUpdate(item, callbackID);
431 else 340 else
432 ourClient.SendAlertMessage("Unable to create inventory item"); 341 ourClient.SendAlertMessage("Unable to create inventory item");
433
434 m_transactions.RemoveXferUploader(m_transactionID);
435 } 342 }
436 343
437 private void ValidateAssets() 344 private void ValidateAssets()
@@ -509,7 +416,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
509 /// <returns>null if the asset has not finished uploading</returns> 416 /// <returns>null if the asset has not finished uploading</returns>
510 public AssetBase GetAssetData() 417 public AssetBase GetAssetData()
511 { 418 {
512 if (m_uploadState == UploadState.Complete) 419 if (m_finished)
513 { 420 {
514 ValidateAssets(); 421 ValidateAssets();
515 return m_asset; 422 return m_asset;
@@ -562,3 +469,4 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
562 } 469 }
563 } 470 }
564} 471}
472
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
index d1a563c..7d7176f 100644
--- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
@@ -52,7 +52,7 @@ using OpenSim.Services.Interfaces;
52[assembly: Addin("FlotsamAssetCache", "1.1")] 52[assembly: Addin("FlotsamAssetCache", "1.1")]
53[assembly: AddinDependency("OpenSim", "0.5")] 53[assembly: AddinDependency("OpenSim", "0.5")]
54 54
55namespace OpenSim.Region.CoreModules.Asset 55namespace Flotsam.RegionModules.AssetCache
56{ 56{
57 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] 57 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
58 public class FlotsamAssetCache : ISharedRegionModule, IImprovedAssetCache, IAssetService 58 public class FlotsamAssetCache : ISharedRegionModule, IImprovedAssetCache, IAssetService
@@ -107,6 +107,8 @@ namespace OpenSim.Region.CoreModules.Asset
107 private IAssetService m_AssetService; 107 private IAssetService m_AssetService;
108 private List<Scene> m_Scenes = new List<Scene>(); 108 private List<Scene> m_Scenes = new List<Scene>();
109 109
110 private bool m_DeepScanBeforePurge;
111
110 public FlotsamAssetCache() 112 public FlotsamAssetCache()
111 { 113 {
112 m_InvalidChars.AddRange(Path.GetInvalidPathChars()); 114 m_InvalidChars.AddRange(Path.GetInvalidPathChars());
@@ -168,6 +170,8 @@ namespace OpenSim.Region.CoreModules.Asset
168 m_CacheDirectoryTierLen = assetConfig.GetInt("CacheDirectoryTierLength", m_CacheDirectoryTierLen); 170 m_CacheDirectoryTierLen = assetConfig.GetInt("CacheDirectoryTierLength", m_CacheDirectoryTierLen);
169 171
170 m_CacheWarnAt = assetConfig.GetInt("CacheWarnAt", m_CacheWarnAt); 172 m_CacheWarnAt = assetConfig.GetInt("CacheWarnAt", m_CacheWarnAt);
173
174 m_DeepScanBeforePurge = assetConfig.GetBoolean("DeepScanBeforePurge", m_DeepScanBeforePurge);
171 } 175 }
172 176
173 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory {0}", m_CacheDirectory); 177 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory {0}", m_CacheDirectory);
@@ -515,10 +519,13 @@ namespace OpenSim.Region.CoreModules.Asset
515 // Purge all files last accessed prior to this point 519 // Purge all files last accessed prior to this point
516 DateTime purgeLine = DateTime.Now - m_FileExpiration; 520 DateTime purgeLine = DateTime.Now - m_FileExpiration;
517 521
518 // An asset cache may contain local non-temporary assets that are not in the asset service. Therefore, 522 // An optional deep scan at this point will ensure assets present in scenes,
519 // before cleaning up expired files we must scan the objects in the scene to make sure that we retain 523 // or referenced by objects in the scene, but not recently accessed
520 // such local assets if they have not been recently accessed. 524 // are not purged.
521 TouchAllSceneAssets(false); 525 if (m_DeepScanBeforePurge)
526 {
527 CacheScenes();
528 }
522 529
523 foreach (string dir in Directory.GetDirectories(m_CacheDirectory)) 530 foreach (string dir in Directory.GetDirectories(m_CacheDirectory))
524 { 531 {
@@ -711,14 +718,11 @@ namespace OpenSim.Region.CoreModules.Asset
711 718
712 /// <summary> 719 /// <summary>
713 /// Iterates through all Scenes, doing a deep scan through assets 720 /// Iterates through all Scenes, doing a deep scan through assets
714 /// to update the access time of all assets present in the scene or referenced by assets 721 /// to cache all assets present in the scene or referenced by assets
715 /// in the scene. 722 /// in the scene
716 /// </summary> 723 /// </summary>
717 /// <param name="storeUncached"> 724 /// <returns></returns>
718 /// If true, then assets scanned which are not found in cache are added to the cache. 725 private int CacheScenes()
719 /// </param>
720 /// <returns>Number of distinct asset references found in the scene.</returns>
721 private int TouchAllSceneAssets(bool storeUncached)
722 { 726 {
723 UuidGatherer gatherer = new UuidGatherer(m_AssetService); 727 UuidGatherer gatherer = new UuidGatherer(m_AssetService);
724 728
@@ -741,7 +745,7 @@ namespace OpenSim.Region.CoreModules.Asset
741 { 745 {
742 File.SetLastAccessTime(filename, DateTime.Now); 746 File.SetLastAccessTime(filename, DateTime.Now);
743 } 747 }
744 else if (storeUncached) 748 else
745 { 749 {
746 m_AssetService.Get(assetID.ToString()); 750 m_AssetService.Get(assetID.ToString());
747 } 751 }
@@ -869,14 +873,13 @@ namespace OpenSim.Region.CoreModules.Asset
869 873
870 break; 874 break;
871 875
876
872 case "assets": 877 case "assets":
873 m_log.Info("[FLOTSAM ASSET CACHE]: Ensuring assets are cached for all scenes."); 878 m_log.Info("[FLOTSAM ASSET CACHE]: Caching all assets, in all scenes.");
874 879
875 Util.FireAndForget(delegate { 880 Util.FireAndForget(delegate {
876 int assetReferenceTotal = TouchAllSceneAssets(true); 881 int assetsCached = CacheScenes();
877 m_log.InfoFormat( 882 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Completed Scene Caching, {0} assets found.", assetsCached);
878 "[FLOTSAM ASSET CACHE]: Completed check with {0} assets.",
879 assetReferenceTotal);
880 }); 883 });
881 884
882 break; 885 break;
diff --git a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
index 1c2bfd0..c91b25f 100644
--- a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
+++ b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
@@ -35,6 +35,7 @@ using Nini.Config;
35using NUnit.Framework; 35using NUnit.Framework;
36using OpenMetaverse; 36using OpenMetaverse;
37using OpenMetaverse.Assets; 37using OpenMetaverse.Assets;
38using Flotsam.RegionModules.AssetCache;
38using OpenSim.Framework; 39using OpenSim.Framework;
39using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
40using OpenSim.Region.Framework.Scenes.Serialization; 41using OpenSim.Region.Framework.Scenes.Serialization;
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index acd156e..951afd7 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -286,20 +286,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
286 286
287 public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp) 287 public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp)
288 { 288 {
289 if (!Enabled)
290 return false;
291
292 if (AttachObjectInternal(sp, group, attachmentPt, silent, useAttachData, temp))
293 {
294 m_scene.EventManager.TriggerOnAttach(group.LocalId, group.FromItemID, sp.UUID);
295 return true;
296 }
297
298 return false;
299 }
300
301 private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp)
302 {
303 lock (sp.AttachmentsSyncLock) 289 lock (sp.AttachmentsSyncLock)
304 { 290 {
305// m_log.DebugFormat( 291// m_log.DebugFormat(
@@ -475,11 +461,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
475 461
476 public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId) 462 public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId)
477 { 463 {
478 DetachSingleAttachmentToGround(sp, soLocalId, sp.AbsolutePosition, Quaternion.Identity);
479 }
480
481 public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId, Vector3 absolutePos, Quaternion absoluteRot)
482 {
483 if (!Enabled) 464 if (!Enabled)
484 return; 465 return;
485 466
@@ -521,11 +502,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
521 so.FromItemID = UUID.Zero; 502 so.FromItemID = UUID.Zero;
522 503
523 SceneObjectPart rootPart = so.RootPart; 504 SceneObjectPart rootPart = so.RootPart;
524 so.AbsolutePosition = absolutePos; 505 so.AbsolutePosition = sp.AbsolutePosition;
525 if (absoluteRot != Quaternion.Identity)
526 {
527 so.UpdateGroupRotationR(absoluteRot);
528 }
529 so.AttachedAvatar = UUID.Zero; 506 so.AttachedAvatar = UUID.Zero;
530 rootPart.SetParentLocalId(0); 507 rootPart.SetParentLocalId(0);
531 so.ClearPartAttachmentData(); 508 so.ClearPartAttachmentData();
@@ -639,9 +616,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
639 616
640 if (grp.HasGroupChanged) 617 if (grp.HasGroupChanged)
641 { 618 {
642 m_log.DebugFormat( 619// m_log.DebugFormat(
643 "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}", 620// "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}",
644 grp.UUID, grp.AttachmentPoint); 621// grp.UUID, grp.AttachmentPoint);
645 622
646 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp, scriptedState); 623 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp, scriptedState);
647 624
@@ -885,7 +862,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
885 // This will throw if the attachment fails 862 // This will throw if the attachment fails
886 try 863 try
887 { 864 {
888 AttachObjectInternal(sp, objatt, attachmentPt, false, false, false); 865 AttachObject(sp, objatt, attachmentPt, false, false, false);
889 } 866 }
890 catch (Exception e) 867 catch (Exception e)
891 { 868 {
@@ -956,9 +933,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
956 933
957 InventoryItemBase item = new InventoryItemBase(itemID, sp.UUID); 934 InventoryItemBase item = new InventoryItemBase(itemID, sp.UUID);
958 item = m_scene.InventoryService.GetItem(item); 935 item = m_scene.InventoryService.GetItem(item);
959 if (item == null)
960 return;
961
962 bool changed = sp.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID); 936 bool changed = sp.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID);
963 if (changed && m_scene.AvatarFactory != null) 937 if (changed && m_scene.AvatarFactory != null)
964 { 938 {
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
index 4e9d3f9..d9a619d 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
@@ -62,10 +62,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
62 public class AttachmentsModuleTests : OpenSimTestCase 62 public class AttachmentsModuleTests : OpenSimTestCase
63 { 63 {
64 private AutoResetEvent m_chatEvent = new AutoResetEvent(false); 64 private AutoResetEvent m_chatEvent = new AutoResetEvent(false);
65// private OSChatMessage m_osChatMessageReceived; 65 private OSChatMessage m_osChatMessageReceived;
66
67 // Used to test whether the operations have fired the attach event. Must be reset after each test.
68 private int m_numberOfAttachEventsFired;
69 66
70 [TestFixtureSetUp] 67 [TestFixtureSetUp]
71 public void FixtureInit() 68 public void FixtureInit()
@@ -86,7 +83,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
86 { 83 {
87// Console.WriteLine("Got chat [{0}]", oscm.Message); 84// Console.WriteLine("Got chat [{0}]", oscm.Message);
88 85
89// m_osChatMessageReceived = oscm; 86 m_osChatMessageReceived = oscm;
90 m_chatEvent.Set(); 87 m_chatEvent.Set();
91 } 88 }
92 89
@@ -102,8 +99,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
102 "attachments-test-scene", TestHelpers.ParseTail(999), 1000, 1000, config); 99 "attachments-test-scene", TestHelpers.ParseTail(999), 1000, 1000, config);
103 SceneHelpers.SetupSceneModules(scene, config, modules.ToArray()); 100 SceneHelpers.SetupSceneModules(scene, config, modules.ToArray());
104 101
105 scene.EventManager.OnAttach += (localID, itemID, avatarID) => m_numberOfAttachEventsFired++;
106
107 return scene; 102 return scene;
108 } 103 }
109 104
@@ -186,8 +181,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
186 TestHelpers.InMethod(); 181 TestHelpers.InMethod();
187// TestHelpers.EnableLogging(); 182// TestHelpers.EnableLogging();
188 183
189 m_numberOfAttachEventsFired = 0;
190
191 Scene scene = CreateTestScene(); 184 Scene scene = CreateTestScene();
192 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); 185 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
193 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1); 186 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1);
@@ -196,7 +189,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
196 189
197 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID); 190 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID);
198 191
199 m_numberOfAttachEventsFired = 0;
200 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false, false); 192 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false, false);
201 193
202 // Check status on scene presence 194 // Check status on scene presence
@@ -224,8 +216,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
224 216
225 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 217 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
226 218
227 // Check events 219// TestHelpers.DisableLogging();
228 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1));
229 } 220 }
230 221
231 /// <summary> 222 /// <summary>
@@ -237,8 +228,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
237 TestHelpers.InMethod(); 228 TestHelpers.InMethod();
238// TestHelpers.EnableLogging(); 229// TestHelpers.EnableLogging();
239 230
240 m_numberOfAttachEventsFired = 0;
241
242 Scene scene = CreateTestScene(); 231 Scene scene = CreateTestScene();
243 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); 232 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
244 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1); 233 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1);
@@ -258,9 +247,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
258 247
259 Assert.That(sp.HasAttachments(), Is.False); 248 Assert.That(sp.HasAttachments(), Is.False);
260 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 249 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
261
262 // Check events
263 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0));
264 } 250 }
265 251
266 [Test] 252 [Test]
@@ -275,7 +261,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
275 261
276 InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20); 262 InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20);
277 263
278 m_numberOfAttachEventsFired = 0;
279 scene.AttachmentsModule.RezSingleAttachmentFromInventory( 264 scene.AttachmentsModule.RezSingleAttachmentFromInventory(
280 sp, attItem.ID, (uint)AttachmentPoint.Chest); 265 sp, attItem.ID, (uint)AttachmentPoint.Chest);
281 266
@@ -295,9 +280,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
295 Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); 280 Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
296 281
297 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 282 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
298
299 // Check events
300 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1));
301 } 283 }
302 284
303 /// <summary> 285 /// <summary>
@@ -356,8 +338,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
356 ISceneEntity so 338 ISceneEntity so
357 = scene.AttachmentsModule.RezSingleAttachmentFromInventory( 339 = scene.AttachmentsModule.RezSingleAttachmentFromInventory(
358 sp, attItem.ID, (uint)AttachmentPoint.Chest); 340 sp, attItem.ID, (uint)AttachmentPoint.Chest);
359
360 m_numberOfAttachEventsFired = 0;
361 scene.AttachmentsModule.DetachSingleAttachmentToGround(sp, so.LocalId); 341 scene.AttachmentsModule.DetachSingleAttachmentToGround(sp, so.LocalId);
362 342
363 // Check scene presence status 343 // Check scene presence status
@@ -373,9 +353,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
373 353
374 // Check object in scene 354 // Check object in scene
375 Assert.That(scene.GetSceneObjectGroup("att"), Is.Not.Null); 355 Assert.That(scene.GetSceneObjectGroup("att"), Is.Not.Null);
376
377 // Check events
378 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1));
379 } 356 }
380 357
381 [Test] 358 [Test]
@@ -392,8 +369,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
392 SceneObjectGroup so 369 SceneObjectGroup so
393 = (SceneObjectGroup)scene.AttachmentsModule.RezSingleAttachmentFromInventory( 370 = (SceneObjectGroup)scene.AttachmentsModule.RezSingleAttachmentFromInventory(
394 sp, attItem.ID, (uint)AttachmentPoint.Chest); 371 sp, attItem.ID, (uint)AttachmentPoint.Chest);
395
396 m_numberOfAttachEventsFired = 0;
397 scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, so); 372 scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, so);
398 373
399 // Check status on scene presence 374 // Check status on scene presence
@@ -405,9 +380,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
405 Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo(0)); 380 Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo(0));
406 381
407 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(0)); 382 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(0));
408
409 // Check events
410 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1));
411 } 383 }
412 384
413 /// <summary> 385 /// <summary>
@@ -489,14 +461,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
489 461
490 SceneObjectGroup rezzedAtt = presence.GetAttachments()[0]; 462 SceneObjectGroup rezzedAtt = presence.GetAttachments()[0];
491 463
492 m_numberOfAttachEventsFired = 0; 464 scene.IncomingCloseAgent(presence.UUID);
493 scene.IncomingCloseAgent(presence.UUID, false);
494 465
495 // Check that we can't retrieve this attachment from the scene. 466 // Check that we can't retrieve this attachment from the scene.
496 Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null); 467 Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null);
497
498 // Check events
499 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0));
500 } 468 }
501 469
502 [Test] 470 [Test]
@@ -512,8 +480,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
512 AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID); 480 AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID);
513 acd.Appearance = new AvatarAppearance(); 481 acd.Appearance = new AvatarAppearance();
514 acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID); 482 acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID);
515
516 m_numberOfAttachEventsFired = 0;
517 ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd); 483 ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd);
518 484
519 Assert.That(presence.HasAttachments(), Is.True); 485 Assert.That(presence.HasAttachments(), Is.True);
@@ -536,9 +502,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
536 Assert.That(presence.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); 502 Assert.That(presence.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
537 503
538 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 504 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
539
540 // Check events. We expect OnAttach to fire on login.
541 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1));
542 } 505 }
543 506
544 [Test] 507 [Test]
@@ -559,14 +522,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
559 522
560 Vector3 newPosition = new Vector3(1, 2, 4); 523 Vector3 newPosition = new Vector3(1, 2, 4);
561 524
562 m_numberOfAttachEventsFired = 0;
563 scene.SceneGraph.UpdatePrimGroupPosition(attSo.LocalId, newPosition, sp.ControllingClient); 525 scene.SceneGraph.UpdatePrimGroupPosition(attSo.LocalId, newPosition, sp.ControllingClient);
564 526
565 Assert.That(attSo.AbsolutePosition, Is.EqualTo(sp.AbsolutePosition)); 527 Assert.That(attSo.AbsolutePosition, Is.EqualTo(sp.AbsolutePosition));
566 Assert.That(attSo.RootPart.AttachedPos, Is.EqualTo(newPosition)); 528 Assert.That(attSo.RootPart.AttachedPos, Is.EqualTo(newPosition));
567
568 // Check events
569 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0));
570 } 529 }
571 530
572 [Test] 531 [Test]
@@ -615,7 +574,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
615 Vector3 teleportPosition = new Vector3(10, 11, 12); 574 Vector3 teleportPosition = new Vector3(10, 11, 12);
616 Vector3 teleportLookAt = new Vector3(20, 21, 22); 575 Vector3 teleportLookAt = new Vector3(20, 21, 22);
617 576
618 m_numberOfAttachEventsFired = 0;
619 sceneA.RequestTeleportLocation( 577 sceneA.RequestTeleportLocation(
620 beforeTeleportSp.ControllingClient, 578 beforeTeleportSp.ControllingClient,
621 sceneB.RegionInfo.RegionHandle, 579 sceneB.RegionInfo.RegionHandle,
@@ -658,9 +616,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
658 Assert.That(actualSceneAAttachments.Count, Is.EqualTo(0)); 616 Assert.That(actualSceneAAttachments.Count, Is.EqualTo(0));
659 617
660 Assert.That(sceneA.GetSceneObjectGroups().Count, Is.EqualTo(0)); 618 Assert.That(sceneA.GetSceneObjectGroups().Count, Is.EqualTo(0));
661
662 // Check events
663 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0));
664 } 619 }
620
621 // I'm commenting this test because scene setup NEEDS InventoryService to
622 // be non-null
623 //[Test]
624// public void T032_CrossAttachments()
625// {
626// TestHelpers.InMethod();
627//
628// ScenePresence presence = scene.GetScenePresence(agent1);
629// ScenePresence presence2 = scene2.GetScenePresence(agent1);
630// presence2.AddAttachment(sog1);
631// presence2.AddAttachment(sog2);
632//
633// ISharedRegionModule serialiser = new SerialiserModule();
634// SceneHelpers.SetupSceneModules(scene, new IniConfigSource(), serialiser);
635// SceneHelpers.SetupSceneModules(scene2, new IniConfigSource(), serialiser);
636//
637// Assert.That(presence.HasAttachments(), Is.False, "Presence has attachments before cross");
638//
639// //Assert.That(presence2.CrossAttachmentsIntoNewRegion(region1, true), Is.True, "Cross was not successful");
640// Assert.That(presence2.HasAttachments(), Is.False, "Presence2 objects were not deleted");
641// Assert.That(presence.HasAttachments(), Is.True, "Presence has not received new objects");
642// }
665 } 643 }
666} 644}
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index e3bf997..4cb4370 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -533,7 +533,6 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
533 // Ignore ruth's assets 533 // Ignore ruth's assets
534 if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID) 534 if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID)
535 continue; 535 continue;
536
537 InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID); 536 InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID);
538 baseItem = invService.GetItem(baseItem); 537 baseItem = invService.GetItem(baseItem);
539 538
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
index 4407e40..dbbb0ae 100644
--- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
@@ -197,7 +197,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
197 string fromName = c.From; 197 string fromName = c.From;
198 string fromNamePrefix = ""; 198 string fromNamePrefix = "";
199 UUID fromID = UUID.Zero; 199 UUID fromID = UUID.Zero;
200 UUID ownerID = UUID.Zero;
201 string message = c.Message; 200 string message = c.Message;
202 IScene scene = c.Scene; 201 IScene scene = c.Scene;
203 UUID destination = c.Destination; 202 UUID destination = c.Destination;
@@ -225,16 +224,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
225 fromNamePrefix = m_adminPrefix; 224 fromNamePrefix = m_adminPrefix;
226 } 225 }
227 destination = UUID.Zero; // Avatars cant "SayTo" 226 destination = UUID.Zero; // Avatars cant "SayTo"
228 ownerID = c.Sender.AgentId;
229
230 break; 227 break;
231 228
232 case ChatSourceType.Object: 229 case ChatSourceType.Object:
233 fromID = c.SenderUUID; 230 fromID = c.SenderUUID;
234 231
235 if (c.SenderObject != null && c.SenderObject is SceneObjectPart)
236 ownerID = ((SceneObjectPart)c.SenderObject).OwnerID;
237
238 break; 232 break;
239 } 233 }
240 234
@@ -268,16 +262,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
268 // objects on a parcel with access restrictions 262 // objects on a parcel with access restrictions
269 if (c.Sender == null || Presencecheck.IsEitherBannedOrRestricted(c.Sender.AgentId) != true) 263 if (c.Sender == null || Presencecheck.IsEitherBannedOrRestricted(c.Sender.AgentId) != true)
270 { 264 {
271 if (destination != UUID.Zero) 265 if (TrySendChatMessage(presence, fromPos, regionPos, fromID, fromNamePrefix + fromName, c.Type, message, sourceType))
272 { 266 receiverIDs.Add(presence.UUID);
273 if (TrySendChatMessage(presence, fromPos, regionPos, fromID, ownerID, fromNamePrefix + fromName, c.Type, message, sourceType, true))
274 receiverIDs.Add(presence.UUID);
275 }
276 else
277 {
278 if (TrySendChatMessage(presence, fromPos, regionPos, fromID, ownerID, fromNamePrefix + fromName, c.Type, message, sourceType, false))
279 receiverIDs.Add(presence.UUID);
280 }
281 } 267 }
282 } 268 }
283 } 269 }
@@ -338,7 +324,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
338 (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId)) 324 (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId))
339 return; 325 return;
340 326
341 client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, fromID, 327 client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID,
342 (byte)sourceType, (byte)ChatAudibleLevel.Fully); 328 (byte)sourceType, (byte)ChatAudibleLevel.Fully);
343 receiverIDs.Add(client.AgentId); 329 receiverIDs.Add(client.AgentId);
344 } 330 }
@@ -355,20 +341,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
355 /// <param name="fromPos"></param> 341 /// <param name="fromPos"></param>
356 /// <param name="regionPos">/param> 342 /// <param name="regionPos">/param>
357 /// <param name="fromAgentID"></param> 343 /// <param name="fromAgentID"></param>
358 /// <param name='ownerID'>
359 /// Owner of the message. For at least some messages from objects, this has to be correctly filled with the owner's UUID.
360 /// This is the case for script error messages in viewer 3 since LLViewer change EXT-7762
361 /// </param>
362 /// <param name="fromName"></param> 344 /// <param name="fromName"></param>
363 /// <param name="type"></param> 345 /// <param name="type"></param>
364 /// <param name="message"></param> 346 /// <param name="message"></param>
365 /// <param name="src"></param> 347 /// <param name="src"></param>
366 /// <returns>true if the message was sent to the receiver, false if it was not sent due to failing a 348 /// <returns>true if the message was sent to the receiver, false if it was not sent due to failing a
367 /// precondition</returns> 349 /// precondition</returns>
368 protected virtual bool TrySendChatMessage( 350 protected virtual bool TrySendChatMessage(ScenePresence presence, Vector3 fromPos, Vector3 regionPos,
369 ScenePresence presence, Vector3 fromPos, Vector3 regionPos, 351 UUID fromAgentID, string fromName, ChatTypeEnum type,
370 UUID fromAgentID, UUID ownerID, string fromName, ChatTypeEnum type, 352 string message, ChatSourceType src)
371 string message, ChatSourceType src, bool ignoreDistance)
372 { 353 {
373 // don't send chat to child agents 354 // don't send chat to child agents
374 if (presence.IsChildAgent) return false; 355 if (presence.IsChildAgent) return false;
@@ -388,9 +369,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
388 } 369 }
389 370
390 // TODO: should change so the message is sent through the avatar rather than direct to the ClientView 371 // TODO: should change so the message is sent through the avatar rather than direct to the ClientView
391 presence.ControllingClient.SendChatMessage( 372 presence.ControllingClient.SendChatMessage(message, (byte) type, fromPos, fromName,
392 message, (byte) type, fromPos, fromName, 373 fromAgentID, (byte)src, (byte)ChatAudibleLevel.Fully);
393 fromAgentID, ownerID, (byte)src, (byte)ChatAudibleLevel.Fully);
394 374
395 return true; 375 return true;
396 } 376 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs
index 5ec0ea9..d942e87 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs
@@ -141,7 +141,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
141 client.FirstName+" "+client.LastName, 141 client.FirstName+" "+client.LastName,
142 destID, (byte)211, false, 142 destID, (byte)211, false,
143 String.Empty, 143 String.Empty,
144 transactionID, false, new Vector3(), new byte[0], true), 144 transactionID, false, new Vector3(), new byte[0]),
145 delegate(bool success) {} ); 145 delegate(bool success) {} );
146 } 146 }
147 } 147 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
index f1903c3..24ec435 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
@@ -28,7 +28,6 @@
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Linq;
32using System.Reflection; 31using System.Reflection;
33using System.Threading; 32using System.Threading;
34using log4net; 33using log4net;
@@ -483,9 +482,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
483 Util.FireAndForget( 482 Util.FireAndForget(
484 delegate 483 delegate
485 { 484 {
486// m_log.DebugFormat( 485 m_log.DebugFormat(
487// "[FRIENDS MODULE]: Notifying {0} friends of {1} of online status {2}", 486 "[FRIENDS MODULE]: Notifying {0} friends of {1} of online status {2}",
488// friendList.Count, agentID, online); 487 friendList.Count, agentID, online);
489 488
490 // Notify about this user status 489 // Notify about this user status
491 StatusNotify(friendList, agentID, online); 490 StatusNotify(friendList, agentID, online);
@@ -496,36 +495,42 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
496 495
497 protected virtual void StatusNotify(List<FriendInfo> friendList, UUID userID, bool online) 496 protected virtual void StatusNotify(List<FriendInfo> friendList, UUID userID, bool online)
498 { 497 {
499 List<string> friendStringIds = friendList.ConvertAll<string>(friend => friend.Friend); 498 foreach (FriendInfo friend in friendList)
500 List<string> remoteFriendStringIds = new List<string>();
501 foreach (string friendStringId in friendStringIds)
502 { 499 {
503 UUID friendUuid; 500 UUID friendID;
504 if (UUID.TryParse(friendStringId, out friendUuid)) 501 if (UUID.TryParse(friend.Friend, out friendID))
505 { 502 {
506 if (LocalStatusNotification(userID, friendUuid, online)) 503 // Try local
504 if (LocalStatusNotification(userID, friendID, online))
507 continue; 505 continue;
508 506
509 remoteFriendStringIds.Add(friendStringId); 507 // The friend is not here [as root]. Let's forward.
508 PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() });
509 if (friendSessions != null && friendSessions.Length > 0)
510 {
511 PresenceInfo friendSession = null;
512 foreach (PresenceInfo pinfo in friendSessions)
513 {
514 if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad
515 {
516 friendSession = pinfo;
517 break;
518 }
519 }
520
521 if (friendSession != null)
522 {
523 GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
524 //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName);
525 m_FriendsSimConnector.StatusNotify(region, userID, friendID, online);
526 }
527 }
528
529 // Friend is not online. Ignore.
510 } 530 }
511 else 531 else
512 { 532 {
513 m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friendStringId); 533 m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friend.Friend);
514 }
515 }
516
517 // We do this regrouping so that we can efficiently send a single request rather than one for each
518 // friend in what may be a very large friends list.
519 PresenceInfo[] friendSessions = PresenceService.GetAgents(remoteFriendStringIds.ToArray());
520
521 foreach (PresenceInfo friendSession in friendSessions)
522 {
523 // let's guard against sessions-gone-bad
524 if (friendSession.RegionID != UUID.Zero)
525 {
526 GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID);
527 //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName);
528 m_FriendsSimConnector.StatusNotify(region, userID, friendSession.UserID, online);
529 } 534 }
530 } 535 }
531 } 536 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
index 82816d9..716cc69 100644
--- a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
@@ -206,7 +206,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
206 transferModule.SendInstantMessage(new GridInstantMessage( 206 transferModule.SendInstantMessage(new GridInstantMessage(
207 m_scene, godID, "God", agentID, (byte)250, false, 207 m_scene, godID, "God", agentID, (byte)250, false,
208 Utils.BytesToString(reason), UUID.Zero, true, 208 Utils.BytesToString(reason), UUID.Zero, true,
209 new Vector3(), new byte[] {(byte)kickflags}, true), 209 new Vector3(), new byte[] {(byte)kickflags}),
210 delegate(bool success) {} ); 210 delegate(bool success) {} );
211 } 211 }
212 return; 212 return;
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
index d0e88f6..6587ead 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
@@ -166,7 +166,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
166 166
167 if (options.ContainsKey("verbose")) 167 if (options.ContainsKey("verbose"))
168 m_log.InfoFormat( 168 m_log.InfoFormat(
169 "[INVENTORY ARCHIVER]: Saving item {0} {1} (asset UUID {2})", 169 "[INVENTORY ARCHIVER]: Saving item {0} {1} with asset {2}",
170 inventoryItem.ID, inventoryItem.Name, inventoryItem.AssetID); 170 inventoryItem.ID, inventoryItem.Name, inventoryItem.AssetID);
171 171
172 string filename = path + CreateArchiveItemName(inventoryItem); 172 string filename = path + CreateArchiveItemName(inventoryItem);
@@ -337,14 +337,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
337 { 337 {
338 m_log.DebugFormat("[INVENTORY ARCHIVER]: Saving {0} assets for items", m_assetUuids.Count); 338 m_log.DebugFormat("[INVENTORY ARCHIVER]: Saving {0} assets for items", m_assetUuids.Count);
339 339
340 AssetsRequest ar 340 new AssetsRequest(
341 = new AssetsRequest( 341 new AssetsArchiver(m_archiveWriter),
342 new AssetsArchiver(m_archiveWriter), 342 m_assetUuids, m_scene.AssetService,
343 m_assetUuids, m_scene.AssetService, 343 m_scene.UserAccountService, m_scene.RegionInfo.ScopeID,
344 m_scene.UserAccountService, m_scene.RegionInfo.ScopeID, 344 options, ReceivedAllAssets).Execute();
345 options, ReceivedAllAssets);
346
347 Util.FireAndForget(o => ar.Execute());
348 } 345 }
349 else 346 else
350 { 347 {
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
index 765b960..7d1fe68 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
@@ -35,7 +35,6 @@ using Nini.Config;
35using OpenMetaverse; 35using OpenMetaverse;
36using OpenSim.Framework; 36using OpenSim.Framework;
37using OpenSim.Framework.Communications; 37using OpenSim.Framework.Communications;
38using OpenSim.Framework.Console;
39using OpenSim.Region.Framework.Interfaces; 38using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Region.Framework.Scenes; 39using OpenSim.Region.Framework.Scenes;
41using OpenSim.Services.Interfaces; 40using OpenSim.Services.Interfaces;
@@ -210,9 +209,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
210 Guid id, string firstName, string lastName, string invPath, string pass, string savePath, 209 Guid id, string firstName, string lastName, string invPath, string pass, string savePath,
211 Dictionary<string, object> options) 210 Dictionary<string, object> options)
212 { 211 {
213// if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, savePath))
214// return false;
215
216 if (m_scenes.Count > 0) 212 if (m_scenes.Count > 0)
217 { 213 {
218 UserAccount userInfo = GetUserInfo(firstName, lastName, pass); 214 UserAccount userInfo = GetUserInfo(firstName, lastName, pass);
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs
index 00727a4..1056865 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs
@@ -82,25 +82,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
82 82
83 protected string m_item1Name = "Ray Gun Item"; 83 protected string m_item1Name = "Ray Gun Item";
84 protected string m_coaItemName = "Coalesced Item"; 84 protected string m_coaItemName = "Coalesced Item";
85 85
86 [TestFixtureSetUp]
87 public void FixtureSetup()
88 {
89 // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread.
90 Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest;
91
92 ConstructDefaultIarBytesForTestLoad();
93 }
94
95 [TestFixtureTearDown]
96 public void TearDown()
97 {
98 // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple
99 // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression
100 // tests really shouldn't).
101 Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod;
102 }
103
104 [SetUp] 86 [SetUp]
105 public override void SetUp() 87 public override void SetUp()
106 { 88 {
@@ -108,6 +90,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
108 m_iarStream = new MemoryStream(m_iarStreamBytes); 90 m_iarStream = new MemoryStream(m_iarStreamBytes);
109 } 91 }
110 92
93 [TestFixtureSetUp]
94 public void FixtureSetup()
95 {
96 ConstructDefaultIarBytesForTestLoad();
97 }
98
111 protected void ConstructDefaultIarBytesForTestLoad() 99 protected void ConstructDefaultIarBytesForTestLoad()
112 { 100 {
113// log4net.Config.XmlConfigurator.Configure(); 101// log4net.Config.XmlConfigurator.Configure();
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
index 06f6e49..b112b6d 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs
@@ -49,7 +49,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
49{ 49{
50 [TestFixture] 50 [TestFixture]
51 public class InventoryArchiverTests : InventoryArchiveTestCase 51 public class InventoryArchiverTests : InventoryArchiveTestCase
52 { 52 {
53 protected TestScene m_scene; 53 protected TestScene m_scene;
54 protected InventoryArchiverModule m_archiverModule; 54 protected InventoryArchiverModule m_archiverModule;
55 55
@@ -69,7 +69,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
69 public void TestLoadCoalesecedItem() 69 public void TestLoadCoalesecedItem()
70 { 70 {
71 TestHelpers.InMethod(); 71 TestHelpers.InMethod();
72// TestHelpers.EnableLogging(); 72// log4net.Config.XmlConfigurator.Configure();
73 73
74 UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL1, "password"); 74 UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL1, "password");
75 m_archiverModule.DearchiveInventory(m_uaLL1.FirstName, m_uaLL1.LastName, "/", "password", m_iarStream); 75 m_archiverModule.DearchiveInventory(m_uaLL1.FirstName, m_uaLL1.LastName, "/", "password", m_iarStream);
@@ -350,38 +350,38 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
350 Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL1.PrincipalID)); 350 Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL1.PrincipalID));
351 } 351 }
352 352
353// /// <summary> 353 /// <summary>
354// /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where 354 /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where
355// /// an account exists with the same name as the creator, though not the same id. 355 /// an account exists with the same name as the creator, though not the same id.
356// /// </summary> 356 /// </summary>
357// [Test] 357 [Test]
358// public void TestLoadIarV0_1SameNameCreator() 358 public void TestLoadIarV0_1SameNameCreator()
359// { 359 {
360// TestHelpers.InMethod(); 360 TestHelpers.InMethod();
361// TestHelpers.EnableLogging(); 361// log4net.Config.XmlConfigurator.Configure();
362// 362
363// UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood"); 363 UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood");
364// UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire"); 364 UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire");
365// 365
366// m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream); 366 m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream);
367// InventoryItemBase foundItem1 367 InventoryItemBase foundItem1
368// = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name); 368 = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name);
369// 369
370// Assert.That( 370 Assert.That(
371// foundItem1.CreatorId, Is.EqualTo(m_uaLL2.PrincipalID.ToString()), 371 foundItem1.CreatorId, Is.EqualTo(m_uaLL2.PrincipalID.ToString()),
372// "Loaded item non-uuid creator doesn't match original"); 372 "Loaded item non-uuid creator doesn't match original");
373// Assert.That( 373 Assert.That(
374// foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL2.PrincipalID), 374 foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL2.PrincipalID),
375// "Loaded item uuid creator doesn't match original"); 375 "Loaded item uuid creator doesn't match original");
376// Assert.That(foundItem1.Owner, Is.EqualTo(m_uaMT.PrincipalID), 376 Assert.That(foundItem1.Owner, Is.EqualTo(m_uaMT.PrincipalID),
377// "Loaded item owner doesn't match inventory reciever"); 377 "Loaded item owner doesn't match inventory reciever");
378// 378
379// AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); 379 AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString());
380// string xmlData = Utils.BytesToString(asset1.Data); 380 string xmlData = Utils.BytesToString(asset1.Data);
381// SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); 381 SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
382// 382
383// Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL2.PrincipalID)); 383 Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL2.PrincipalID));
384// } 384 }
385 385
386 /// <summary> 386 /// <summary>
387 /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where 387 /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
index e26beec..8176989 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
@@ -38,15 +38,15 @@ using OpenSim.Services.Interfaces;
38 38
39namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer 39namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
40{ 40{
41 public class InventoryTransferModule : ISharedRegionModule 41 public class InventoryTransferModule : IInventoryTransferModule, ISharedRegionModule
42 { 42 {
43 private static readonly ILog m_log 43 private static readonly ILog m_log
44 = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45 45
46 /// <summary> 46 /// <summary>
47 private List<Scene> m_Scenelist = new List<Scene>(); 47 private List<Scene> m_Scenelist = new List<Scene>();
48// private Dictionary<UUID, Scene> m_AgentRegions = 48 private Dictionary<UUID, Scene> m_AgentRegions =
49// new Dictionary<UUID, Scene>(); 49 new Dictionary<UUID, Scene>();
50 50
51 private IMessageTransferModule m_TransferModule = null; 51 private IMessageTransferModule m_TransferModule = null;
52 private bool m_Enabled = true; 52 private bool m_Enabled = true;
@@ -76,12 +76,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
76 76
77 m_Scenelist.Add(scene); 77 m_Scenelist.Add(scene);
78 78
79// scene.RegisterModuleInterface<IInventoryTransferModule>(this); 79 scene.RegisterModuleInterface<IInventoryTransferModule>(this);
80 80
81 scene.EventManager.OnNewClient += OnNewClient; 81 scene.EventManager.OnNewClient += OnNewClient;
82// scene.EventManager.OnClientClosed += ClientLoggedOut; 82 scene.EventManager.OnClientClosed += ClientLoggedOut;
83 scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; 83 scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage;
84// scene.EventManager.OnSetRootAgentScene += OnSetRootAgentScene; 84 scene.EventManager.OnSetRootAgentScene += OnSetRootAgentScene;
85 } 85 }
86 86
87 public void RegionLoaded(Scene scene) 87 public void RegionLoaded(Scene scene)
@@ -96,9 +96,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
96 96
97 m_Scenelist.Clear(); 97 m_Scenelist.Clear();
98 scene.EventManager.OnNewClient -= OnNewClient; 98 scene.EventManager.OnNewClient -= OnNewClient;
99// scene.EventManager.OnClientClosed -= ClientLoggedOut; 99 scene.EventManager.OnClientClosed -= ClientLoggedOut;
100 scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; 100 scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage;
101// scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene; 101 scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene;
102 } 102 }
103 } 103 }
104 } 104 }
@@ -106,9 +106,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
106 public void RemoveRegion(Scene scene) 106 public void RemoveRegion(Scene scene)
107 { 107 {
108 scene.EventManager.OnNewClient -= OnNewClient; 108 scene.EventManager.OnNewClient -= OnNewClient;
109// scene.EventManager.OnClientClosed -= ClientLoggedOut; 109 scene.EventManager.OnClientClosed -= ClientLoggedOut;
110 scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; 110 scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage;
111// scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene; 111 scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene;
112 m_Scenelist.Remove(scene); 112 m_Scenelist.Remove(scene);
113 } 113 }
114 114
@@ -138,10 +138,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
138 client.OnInstantMessage += OnInstantMessage; 138 client.OnInstantMessage += OnInstantMessage;
139 } 139 }
140 140
141// protected void OnSetRootAgentScene(UUID id, Scene scene) 141 protected void OnSetRootAgentScene(UUID id, Scene scene)
142// { 142 {
143// m_AgentRegions[id] = scene; 143 m_AgentRegions[id] = scene;
144// } 144 }
145 145
146 private Scene FindClientScene(UUID agentId) 146 private Scene FindClientScene(UUID agentId)
147 { 147 {
@@ -313,11 +313,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
313 m_TransferModule.SendInstantMessage(im, delegate(bool success) {}); 313 m_TransferModule.SendInstantMessage(im, delegate(bool success) {});
314 } 314 }
315 } 315 }
316
317 // XXX: This code was placed here to try and accomdate RLV which moves given folders named #RLV/~<name>
318 // to a folder called name in #RLV. However, this approach may not be ultimately correct - from analysis
319 // of Firestorm 4.2.2 on sending an InventoryOffered instead of TaskInventoryOffered (as was previously
320 // done), the viewer itself would appear to move and rename the folder, rather than the simulator doing it here.
321 else if (im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted) 316 else if (im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted)
322 { 317 {
323 UUID destinationFolderID = UUID.Zero; 318 UUID destinationFolderID = UUID.Zero;
@@ -329,16 +324,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
329 324
330 if (destinationFolderID != UUID.Zero) 325 if (destinationFolderID != UUID.Zero)
331 { 326 {
332 InventoryFolderBase destinationFolder = new InventoryFolderBase(destinationFolderID, client.AgentId);
333 if (destinationFolder == null)
334 {
335 m_log.WarnFormat(
336 "[INVENTORY TRANSFER]: TaskInventoryAccepted message from {0} in {1} specified folder {2} which does not exist",
337 client.Name, scene.Name, destinationFolderID);
338
339 return;
340 }
341
342 IInventoryService invService = scene.InventoryService; 327 IInventoryService invService = scene.InventoryService;
343 328
344 UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip 329 UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip
@@ -346,11 +331,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
346 InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId); 331 InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId);
347 item = invService.GetItem(item); 332 item = invService.GetItem(item);
348 InventoryFolderBase folder = null; 333 InventoryFolderBase folder = null;
349 UUID? previousParentFolderID = null;
350 334
351 if (item != null) // It's an item 335 if (item != null) // It's an item
352 { 336 {
353 previousParentFolderID = item.Folder;
354 item.Folder = destinationFolderID; 337 item.Folder = destinationFolderID;
355 338
356 invService.DeleteItems(item.Owner, new List<UUID>() { item.ID }); 339 invService.DeleteItems(item.Owner, new List<UUID>() { item.ID });
@@ -363,22 +346,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
363 346
364 if (folder != null) // It's a folder 347 if (folder != null) // It's a folder
365 { 348 {
366 previousParentFolderID = folder.ParentID;
367 folder.ParentID = destinationFolderID; 349 folder.ParentID = destinationFolderID;
368 invService.MoveFolder(folder); 350 invService.MoveFolder(folder);
369 } 351 }
370 } 352 }
371
372 // Tell client about updates to original parent and new parent (this should probably be factored with existing move item/folder code).
373 if (previousParentFolderID != null)
374 {
375 InventoryFolderBase previousParentFolder
376 = new InventoryFolderBase((UUID)previousParentFolderID, client.AgentId);
377 previousParentFolder = invService.GetFolder(previousParentFolder);
378 scene.SendInventoryUpdate(client, previousParentFolder, true, true);
379
380 scene.SendInventoryUpdate(client, destinationFolder, true, true);
381 }
382 } 353 }
383 } 354 }
384 else if ( 355 else if (
@@ -399,11 +370,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
399 InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId); 370 InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId);
400 item = invService.GetItem(item); 371 item = invService.GetItem(item);
401 InventoryFolderBase folder = null; 372 InventoryFolderBase folder = null;
402 UUID? previousParentFolderID = null;
403 373
404 if (item != null && trashFolder != null) 374 if (item != null && trashFolder != null)
405 { 375 {
406 previousParentFolderID = item.Folder;
407 item.Folder = trashFolder.ID; 376 item.Folder = trashFolder.ID;
408 377
409 // Diva comment: can't we just update this item??? 378 // Diva comment: can't we just update this item???
@@ -419,7 +388,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
419 388
420 if (folder != null & trashFolder != null) 389 if (folder != null & trashFolder != null)
421 { 390 {
422 previousParentFolderID = folder.ParentID;
423 folder.ParentID = trashFolder.ID; 391 folder.ParentID = trashFolder.ID;
424 invService.MoveFolder(folder); 392 invService.MoveFolder(folder);
425 client.SendBulkUpdateInventory(folder); 393 client.SendBulkUpdateInventory(folder);
@@ -440,16 +408,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
440 client.SendAgentAlertMessage("Unable to delete "+ 408 client.SendAgentAlertMessage("Unable to delete "+
441 "received inventory" + reason, false); 409 "received inventory" + reason, false);
442 } 410 }
443 // Tell client about updates to original parent and new parent (this should probably be factored with existing move item/folder code).
444 else if (previousParentFolderID != null)
445 {
446 InventoryFolderBase previousParentFolder
447 = new InventoryFolderBase((UUID)previousParentFolderID, client.AgentId);
448 previousParentFolder = invService.GetFolder(previousParentFolder);
449 scene.SendInventoryUpdate(client, previousParentFolder, true, true);
450
451 scene.SendInventoryUpdate(client, trashFolder, true, true);
452 }
453 411
454 if (im.dialog == (byte)InstantMessageDialog.InventoryDeclined) 412 if (im.dialog == (byte)InstantMessageDialog.InventoryDeclined)
455 { 413 {
@@ -468,69 +426,69 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
468 } 426 }
469 } 427 }
470 428
471// public bool NeedSceneCacheClear(UUID agentID, Scene scene) 429 public bool NeedSceneCacheClear(UUID agentID, Scene scene)
472// { 430 {
473// if (!m_AgentRegions.ContainsKey(agentID)) 431 if (!m_AgentRegions.ContainsKey(agentID))
474// { 432 {
475// // Since we can get here two ways, we need to scan 433 // Since we can get here two ways, we need to scan
476// // the scenes here. This is somewhat more expensive 434 // the scenes here. This is somewhat more expensive
477// // but helps avoid a nasty bug 435 // but helps avoid a nasty bug
478// // 436 //
479// 437
480// foreach (Scene s in m_Scenelist) 438 foreach (Scene s in m_Scenelist)
481// { 439 {
482// ScenePresence presence; 440 ScenePresence presence;
483// 441
484// if (s.TryGetScenePresence(agentID, out presence)) 442 if (s.TryGetScenePresence(agentID, out presence))
485// { 443 {
486// // If the agent is in this scene, then we 444 // If the agent is in this scene, then we
487// // are being called twice in a single 445 // are being called twice in a single
488// // teleport. This is wasteful of cycles 446 // teleport. This is wasteful of cycles
489// // but harmless due to this 2nd level check 447 // but harmless due to this 2nd level check
490// // 448 //
491// // If the agent is found in another scene 449 // If the agent is found in another scene
492// // then the list wasn't current 450 // then the list wasn't current
493// // 451 //
494// // If the agent is totally unknown, then what 452 // If the agent is totally unknown, then what
495// // are we even doing here?? 453 // are we even doing here??
496// // 454 //
497// if (s == scene) 455 if (s == scene)
498// { 456 {
499// //m_log.Debug("[INVTRANSFERMOD]: s == scene. Returning true in " + scene.RegionInfo.RegionName); 457 //m_log.Debug("[INVTRANSFERMOD]: s == scene. Returning true in " + scene.RegionInfo.RegionName);
500// return true; 458 return true;
501// } 459 }
502// else 460 else
503// { 461 {
504// //m_log.Debug("[INVTRANSFERMOD]: s != scene. Returning false in " + scene.RegionInfo.RegionName); 462 //m_log.Debug("[INVTRANSFERMOD]: s != scene. Returning false in " + scene.RegionInfo.RegionName);
505// return false; 463 return false;
506// } 464 }
507// } 465 }
508// } 466 }
509// //m_log.Debug("[INVTRANSFERMOD]: agent not in scene. Returning true in " + scene.RegionInfo.RegionName); 467 //m_log.Debug("[INVTRANSFERMOD]: agent not in scene. Returning true in " + scene.RegionInfo.RegionName);
510// return true; 468 return true;
511// } 469 }
512// 470
513// // The agent is left in current Scene, so we must be 471 // The agent is left in current Scene, so we must be
514// // going to another instance 472 // going to another instance
515// // 473 //
516// if (m_AgentRegions[agentID] == scene) 474 if (m_AgentRegions[agentID] == scene)
517// { 475 {
518// //m_log.Debug("[INVTRANSFERMOD]: m_AgentRegions[agentID] == scene. Returning true in " + scene.RegionInfo.RegionName); 476 //m_log.Debug("[INVTRANSFERMOD]: m_AgentRegions[agentID] == scene. Returning true in " + scene.RegionInfo.RegionName);
519// m_AgentRegions.Remove(agentID); 477 m_AgentRegions.Remove(agentID);
520// return true; 478 return true;
521// } 479 }
522// 480
523// // Another region has claimed the agent 481 // Another region has claimed the agent
524// // 482 //
525// //m_log.Debug("[INVTRANSFERMOD]: last resort. Returning false in " + scene.RegionInfo.RegionName); 483 //m_log.Debug("[INVTRANSFERMOD]: last resort. Returning false in " + scene.RegionInfo.RegionName);
526// return false; 484 return false;
527// } 485 }
528// 486
529// public void ClientLoggedOut(UUID agentID, Scene scene) 487 public void ClientLoggedOut(UUID agentID, Scene scene)
530// { 488 {
531// if (m_AgentRegions.ContainsKey(agentID)) 489 if (m_AgentRegions.ContainsKey(agentID))
532// m_AgentRegions.Remove(agentID); 490 m_AgentRegions.Remove(agentID);
533// } 491 }
534 492
535 /// <summary> 493 /// <summary>
536 /// 494 ///
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
index 9c369f6..92cf9d1 100644
--- a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
@@ -186,7 +186,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
186 client.FirstName+" "+client.LastName, targetid, 186 client.FirstName+" "+client.LastName, targetid,
187 (byte)InstantMessageDialog.RequestTeleport, false, 187 (byte)InstantMessageDialog.RequestTeleport, false,
188 message, sessionID, false, presence.AbsolutePosition, 188 message, sessionID, false, presence.AbsolutePosition,
189 new Byte[0], true); 189 new Byte[0]);
190 m.RegionID = client.Scene.RegionInfo.RegionID.Guid; 190 m.RegionID = client.Scene.RegionInfo.RegionID.Guid;
191 191
192 m_log.DebugFormat("[HG LURE MODULE]: RequestTeleport sessionID={0}, regionID={1}, message={2}", m.imSessionID, m.RegionID, m.message); 192 m_log.DebugFormat("[HG LURE MODULE]: RequestTeleport sessionID={0}, regionID={1}, message={2}", m.imSessionID, m.RegionID, m.message);
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
index 1949459..a889984 100644
--- a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
@@ -173,7 +173,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
173 client.FirstName+" "+client.LastName, targetid, 173 client.FirstName+" "+client.LastName, targetid,
174 (byte)InstantMessageDialog.GodLikeRequestTeleport, false, 174 (byte)InstantMessageDialog.GodLikeRequestTeleport, false,
175 message, dest, false, presence.AbsolutePosition, 175 message, dest, false, presence.AbsolutePosition,
176 new Byte[0], true); 176 new Byte[0]);
177 } 177 }
178 else 178 else
179 { 179 {
@@ -181,7 +181,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
181 client.FirstName+" "+client.LastName, targetid, 181 client.FirstName+" "+client.LastName, targetid,
182 (byte)InstantMessageDialog.RequestTeleport, false, 182 (byte)InstantMessageDialog.RequestTeleport, false,
183 message, dest, false, presence.AbsolutePosition, 183 message, dest, false, presence.AbsolutePosition,
184 new Byte[0], true); 184 new Byte[0]);
185 } 185 }
186 186
187 if (m_TransferModule != null) 187 if (m_TransferModule != null)
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index 31e6ce9..880b2cc 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -327,14 +327,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
327 return; 327 return;
328 } 328 }
329 329
330 // Validate assorted conditions
331 string reason = string.Empty;
332 if (!ValidateGenericConditions(sp, reg, finalDestination, teleportFlags, out reason))
333 {
334 sp.ControllingClient.SendTeleportFailed(reason);
335 return;
336 }
337
338 // 330 //
339 // This is it 331 // This is it
340 // 332 //
@@ -366,13 +358,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
366 } 358 }
367 } 359 }
368 360
369 // Nothing to validate here
370 protected virtual bool ValidateGenericConditions(ScenePresence sp, GridRegion reg, GridRegion finalDestination, uint teleportFlags, out string reason)
371 {
372 reason = String.Empty;
373 return true;
374 }
375
376 /// <summary> 361 /// <summary>
377 /// Determines whether this instance is within the max transfer distance. 362 /// Determines whether this instance is within the max transfer distance.
378 /// </summary> 363 /// </summary>
@@ -488,11 +473,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
488 // both regions 473 // both regions
489 if (sp.ParentID != (uint)0) 474 if (sp.ParentID != (uint)0)
490 sp.StandUp(); 475 sp.StandUp();
476
491 else if (sp.Flying) 477 else if (sp.Flying)
492 teleportFlags |= (uint)TeleportFlags.IsFlying; 478 teleportFlags |= (uint)TeleportFlags.IsFlying;
493 479
494 // At least on LL 3.3.4, this is not strictly necessary - a teleport will succeed without sending this to
495 // the viewer. However, it might mean that the viewer does not see the black teleport screen (untested).
496 sp.ControllingClient.SendTeleportStart(teleportFlags); 480 sp.ControllingClient.SendTeleportStart(teleportFlags);
497 481
498 // the avatar.Close below will clear the child region list. We need this below for (possibly) 482 // the avatar.Close below will clear the child region list. We need this below for (possibly)
@@ -568,11 +552,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
568 // So let's wait 552 // So let's wait
569 Thread.Sleep(200); 553 Thread.Sleep(200);
570 554
571 // At least on LL 3.3.4 for teleports between different regions on the same simulator this appears
572 // unnecessary - teleport will succeed and SEED caps will be requested without it (though possibly
573 // only on TeleportFinish). This is untested for region teleport between different simulators
574 // though this probably also works.
575 m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath); 555 m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath);
556
576 } 557 }
577 else 558 else
578 { 559 {
@@ -593,7 +574,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
593 574
594 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent..."); 575 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent...");
595 576
596 if (!UpdateAgent(reg, finalDestination, agent, sp)) 577 if (!UpdateAgent(reg, finalDestination, agent))
597 { 578 {
598 // Region doesn't take it 579 // Region doesn't take it
599 m_log.WarnFormat( 580 m_log.WarnFormat(
@@ -669,7 +650,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
669 // an agent cannot teleport back to this region if it has teleported away. 650 // an agent cannot teleport back to this region if it has teleported away.
670 Thread.Sleep(3000); 651 Thread.Sleep(3000);
671 652
672 sp.Scene.IncomingCloseAgent(sp.UUID, false); 653 sp.Scene.IncomingCloseAgent(sp.UUID);
673 } 654 }
674 else 655 else
675 { 656 {
@@ -677,14 +658,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
677 sp.Reset(); 658 sp.Reset();
678 } 659 }
679 660
680 // Commented pending deletion since this method no longer appears to do anything at all 661 // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE!
681// // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! 662 if (sp.Scene.NeedSceneCacheClear(sp.UUID))
682// if (sp.Scene.NeedSceneCacheClear(sp.UUID)) 663 {
683// { 664 m_log.DebugFormat(
684// m_log.DebugFormat( 665 "[ENTITY TRANSFER MODULE]: User {0} is going to another region, profile cache removed",
685// "[ENTITY TRANSFER MODULE]: User {0} is going to another region, profile cache removed", 666 sp.UUID);
686// sp.UUID); 667 }
687// }
688 668
689 m_entityTransferStateMachine.ResetFromTransit(sp.UUID); 669 m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
690 } 670 }
@@ -721,7 +701,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
721 return success; 701 return success;
722 } 702 }
723 703
724 protected virtual bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agent, ScenePresence sp) 704 protected virtual bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agent)
725 { 705 {
726 return Scene.SimulationService.UpdateAgent(finalDestination, agent); 706 return Scene.SimulationService.UpdateAgent(finalDestination, agent);
727 } 707 }
@@ -1033,7 +1013,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1033 Scene initiatingScene) 1013 Scene initiatingScene)
1034 { 1014 {
1035 Thread.Sleep(10000); 1015 Thread.Sleep(10000);
1036
1037 IMessageTransferModule im = initiatingScene.RequestModuleInterface<IMessageTransferModule>(); 1016 IMessageTransferModule im = initiatingScene.RequestModuleInterface<IMessageTransferModule>();
1038 if (im != null) 1017 if (im != null)
1039 { 1018 {
@@ -1046,22 +1025,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1046 (uint)(int)position.X, 1025 (uint)(int)position.X,
1047 (uint)(int)position.Y, 1026 (uint)(int)position.Y,
1048 (uint)(int)position.Z); 1027 (uint)(int)position.Z);
1049 1028 GridInstantMessage m = new GridInstantMessage(initiatingScene, UUID.Zero,
1050 GridInstantMessage m 1029 "Region", agent.UUID,
1051 = new GridInstantMessage( 1030 (byte)InstantMessageDialog.GodLikeRequestTeleport, false,
1052 initiatingScene, 1031 "", gotoLocation, false, new Vector3(127, 0, 0),
1053 UUID.Zero, 1032 new Byte[0]);
1054 "Region",
1055 agent.UUID,
1056 (byte)InstantMessageDialog.GodLikeRequestTeleport,
1057 false,
1058 "",
1059 gotoLocation,
1060 false,
1061 new Vector3(127, 0, 0),
1062 new Byte[0],
1063 false);
1064
1065 im.SendInstantMessage(m, delegate(bool success) 1033 im.SendInstantMessage(m, delegate(bool success)
1066 { 1034 {
1067 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Client Initiating Teleport sending IM success = {0}", success); 1035 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Client Initiating Teleport sending IM success = {0}", success);
@@ -1223,11 +1191,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1223 // the user may change their profile information in other region, 1191 // the user may change their profile information in other region,
1224 // so the userinfo in UserProfileCache is not reliable any more, delete it 1192 // so the userinfo in UserProfileCache is not reliable any more, delete it
1225 // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! 1193 // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE!
1226// if (agent.Scene.NeedSceneCacheClear(agent.UUID)) 1194 if (agent.Scene.NeedSceneCacheClear(agent.UUID))
1227// { 1195 {
1228// m_log.DebugFormat( 1196 m_log.DebugFormat(
1229// "[ENTITY TRANSFER MODULE]: User {0} is going to another region", agent.UUID); 1197 "[ENTITY TRANSFER MODULE]: User {0} is going to another region", agent.UUID);
1230// } 1198 }
1231 1199
1232 //m_log.Debug("AFTER CROSS"); 1200 //m_log.Debug("AFTER CROSS");
1233 //Scene.DumpChildrenSeeds(UUID); 1201 //Scene.DumpChildrenSeeds(UUID);
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
index b16c37a..3010b59 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
@@ -54,59 +54,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
54 54
55 private GatekeeperServiceConnector m_GatekeeperConnector; 55 private GatekeeperServiceConnector m_GatekeeperConnector;
56 56
57 protected bool m_RestrictAppearanceAbroad;
58 protected string m_AccountName;
59 protected List<AvatarAppearance> m_ExportedAppearances;
60 protected List<AvatarAttachment> m_Attachs;
61
62 protected List<AvatarAppearance> ExportedAppearance
63 {
64 get
65 {
66 if (m_ExportedAppearances != null)
67 return m_ExportedAppearances;
68
69 m_ExportedAppearances = new List<AvatarAppearance>();
70 m_Attachs = new List<AvatarAttachment>();
71
72 string[] names = m_AccountName.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
73
74 foreach (string name in names)
75 {
76 string[] parts = name.Trim().Split();
77 if (parts.Length != 2)
78 {
79 m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Wrong user account name format {0}. Specify 'First Last'", name);
80 return null;
81 }
82 UserAccount account = Scene.UserAccountService.GetUserAccount(UUID.Zero, parts[0], parts[1]);
83 if (account == null)
84 {
85 m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unknown account {0}", m_AccountName);
86 return null;
87 }
88 AvatarAppearance a = Scene.AvatarService.GetAppearance(account.PrincipalID);
89 if (a != null)
90 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Successfully retrieved appearance for {0}", name);
91
92 foreach (AvatarAttachment att in a.GetAttachments())
93 {
94 InventoryItemBase item = new InventoryItemBase(att.ItemID, account.PrincipalID);
95 item = Scene.InventoryService.GetItem(item);
96 if (item != null)
97 a.SetAttachment(att.AttachPoint, att.ItemID, item.AssetID);
98 else
99 m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unable to retrieve item {0} from inventory {1}", att.ItemID, name);
100 }
101
102 m_ExportedAppearances.Add(a);
103 m_Attachs.AddRange(a.GetAttachments());
104 }
105
106 return m_ExportedAppearances;
107 }
108 }
109
110 #region ISharedRegionModule 57 #region ISharedRegionModule
111 58
112 public override string Name 59 public override string Name
@@ -125,18 +72,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
125 { 72 {
126 IConfig transferConfig = source.Configs["EntityTransfer"]; 73 IConfig transferConfig = source.Configs["EntityTransfer"];
127 if (transferConfig != null) 74 if (transferConfig != null)
128 {
129 m_levelHGTeleport = transferConfig.GetInt("LevelHGTeleport", 0); 75 m_levelHGTeleport = transferConfig.GetInt("LevelHGTeleport", 0);
130 76
131 m_RestrictAppearanceAbroad = transferConfig.GetBoolean("RestrictAppearanceAbroad", false);
132 if (m_RestrictAppearanceAbroad)
133 {
134 m_AccountName = transferConfig.GetString("AccountForAppearance", string.Empty);
135 if (m_AccountName == string.Empty)
136 m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: RestrictAppearanceAbroad is on, but no account has been given for avatar appearance!");
137 }
138 }
139
140 InitialiseCommon(source); 77 InitialiseCommon(source);
141 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: {0} enabled.", Name); 78 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: {0} enabled.", Name);
142 } 79 }
@@ -148,36 +85,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
148 base.AddRegion(scene); 85 base.AddRegion(scene);
149 86
150 if (m_Enabled) 87 if (m_Enabled)
151 {
152 scene.RegisterModuleInterface<IUserAgentVerificationModule>(this); 88 scene.RegisterModuleInterface<IUserAgentVerificationModule>(this);
153 scene.EventManager.OnIncomingSceneObject += OnIncomingSceneObject;
154 }
155 }
156
157 void OnIncomingSceneObject(SceneObjectGroup so)
158 {
159 if (!so.IsAttachment)
160 return;
161
162 if (so.Scene.UserManagementModule.IsLocalGridUser(so.AttachedAvatar))
163 return;
164
165 // foreign user
166 AgentCircuitData aCircuit = so.Scene.AuthenticateHandler.GetAgentCircuitData(so.AttachedAvatar);
167 if (aCircuit != null && (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0)
168 {
169 if (aCircuit.ServiceURLs != null && aCircuit.ServiceURLs.ContainsKey("AssetServerURI"))
170 {
171 string url = aCircuit.ServiceURLs["AssetServerURI"].ToString();
172 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Incoming attachement {0} for HG user {1} with asset server {2}", so.Name, so.AttachedAvatar, url);
173 Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>();
174 HGUuidGatherer uuidGatherer = new HGUuidGatherer(so.Scene.AssetService, url);
175 uuidGatherer.GatherAssetUuids(so, ids);
176
177 foreach (KeyValuePair<UUID, AssetType> kvp in ids)
178 uuidGatherer.FetchAsset(kvp.Key);
179 }
180 }
181 } 89 }
182 90
183 protected override void OnNewClient(IClientAPI client) 91 protected override void OnNewClient(IClientAPI client)
@@ -212,7 +120,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
212 int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, region.RegionID); 120 int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, region.RegionID);
213 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: region {0} flags: {1}", region.RegionID, flags); 121 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: region {0} flags: {1}", region.RegionID, flags);
214 122
215 if ((flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0) 123 if ((flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0)
216 { 124 {
217 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Destination region {0} is hyperlink", region.RegionID); 125 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Destination region {0} is hyperlink", region.RegionID);
218 GridRegion real_destination = m_GatekeeperConnector.GetHyperlinkRegion(region, region.RegionID); 126 GridRegion real_destination = m_GatekeeperConnector.GetHyperlinkRegion(region, region.RegionID);
@@ -232,7 +140,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
232 return true; 140 return true;
233 141
234 int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID); 142 int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID);
235 if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0) 143 if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0)
236 return true; 144 return true;
237 145
238 return false; 146 return false;
@@ -245,8 +153,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
245 { 153 {
246 // Log them out of this grid 154 // Log them out of this grid
247 Scene.PresenceService.LogoutAgent(sp.ControllingClient.SessionId); 155 Scene.PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
248 string userId = Scene.UserManagementModule.GetUserUUI(sp.UUID);
249 Scene.GridUserService.LoggedOut(userId, UUID.Zero, Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat);
250 } 156 }
251 } 157 }
252 158
@@ -256,11 +162,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
256 reason = string.Empty; 162 reason = string.Empty;
257 logout = false; 163 logout = false;
258 int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID); 164 int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID);
259 if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0) 165 if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0)
260 { 166 {
261 // this user is going to another grid 167 // this user is going to another grid
262 // for local users, check if HyperGrid teleport is allowed, based on user level 168 // check if HyperGrid teleport is allowed, based on user level
263 if (Scene.UserManagementModule.IsLocalGridUser(sp.UUID) && sp.UserLevel < m_levelHGTeleport) 169 if (sp.UserLevel < m_levelHGTeleport)
264 { 170 {
265 m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unable to HG teleport agent due to insufficient UserLevel."); 171 m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unable to HG teleport agent due to insufficient UserLevel.");
266 reason = "Hypergrid teleport not allowed"; 172 reason = "Hypergrid teleport not allowed";
@@ -294,124 +200,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
294 TeleportHome(id, client); 200 TeleportHome(id, client);
295 } 201 }
296 202
297 protected override bool ValidateGenericConditions(ScenePresence sp, GridRegion reg, GridRegion finalDestination, uint teleportFlags, out string reason)
298 {
299 reason = "Please wear your grid's allowed appearance before teleporting to another grid";
300 if (!m_RestrictAppearanceAbroad)
301 return true;
302
303 // The rest is only needed for controlling appearance
304
305 int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID);
306 if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0)
307 {
308 // this user is going to another grid
309 if (Scene.UserManagementModule.IsLocalGridUser(sp.UUID))
310 {
311 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: RestrictAppearanceAbroad is ON. Checking generic appearance");
312
313 // Check wearables
314 for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++)
315 {
316 for (int j = 0; j < sp.Appearance.Wearables[i].Count; j++)
317 {
318 if (sp.Appearance.Wearables[i] == null)
319 continue;
320
321 bool found = false;
322 foreach (AvatarAppearance a in ExportedAppearance)
323 if (a.Wearables[i] != null)
324 {
325 found = true;
326 break;
327 }
328
329 if (!found)
330 {
331 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Wearable not allowed to go outside {0}", i);
332 return false;
333 }
334
335 found = false;
336 foreach (AvatarAppearance a in ExportedAppearance)
337 if (sp.Appearance.Wearables[i][j].AssetID == a.Wearables[i][j].AssetID)
338 {
339 found = true;
340 break;
341 }
342
343 if (!found)
344 {
345 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Wearable not allowed to go outside {0}", i);
346 return false;
347 }
348 }
349 }
350
351 // Check attachments
352 foreach (AvatarAttachment att in sp.Appearance.GetAttachments())
353 {
354 bool found = false;
355 foreach (AvatarAttachment att2 in m_Attachs)
356 {
357 if (att2.AssetID == att.AssetID)
358 {
359 found = true;
360 break;
361 }
362 }
363 if (!found)
364 {
365 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Attachment not allowed to go outside {0}", att.AttachPoint);
366 return false;
367 }
368 }
369 }
370 }
371
372 reason = string.Empty;
373 return true;
374 }
375
376
377 //protected override bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agentData, ScenePresence sp)
378 //{
379 // int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID);
380 // if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0)
381 // {
382 // // this user is going to another grid
383 // if (m_RestrictAppearanceAbroad && Scene.UserManagementModule.IsLocalGridUser(agentData.AgentID))
384 // {
385 // // We need to strip the agent off its appearance
386 // m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: RestrictAppearanceAbroad is ON. Sending generic appearance");
387
388 // // Delete existing npc attachments
389 // Scene.AttachmentsModule.DeleteAttachmentsFromScene(sp, false);
390
391 // // XXX: We can't just use IAvatarFactoryModule.SetAppearance() yet since it doesn't transfer attachments
392 // AvatarAppearance newAppearance = new AvatarAppearance(ExportedAppearance, true);
393 // sp.Appearance = newAppearance;
394
395 // // Rez needed npc attachments
396 // Scene.AttachmentsModule.RezAttachments(sp);
397
398
399 // IAvatarFactoryModule module = Scene.RequestModuleInterface<IAvatarFactoryModule>();
400 // //module.SendAppearance(sp.UUID);
401 // module.RequestRebake(sp, false);
402
403 // Scene.AttachmentsModule.CopyAttachments(sp, agentData);
404 // agentData.Appearance = sp.Appearance;
405 // }
406 // }
407
408 // foreach (AvatarAttachment a in agentData.Appearance.GetAttachments())
409 // m_log.DebugFormat("[XXX]: {0}-{1}", a.ItemID, a.AssetID);
410
411
412 // return base.UpdateAgent(reg, finalDestination, agentData, sp);
413 //}
414
415 public override bool TeleportHome(UUID id, IClientAPI client) 203 public override bool TeleportHome(UUID id, IClientAPI client)
416 { 204 {
417 m_log.DebugFormat( 205 m_log.DebugFormat(
@@ -587,4 +375,4 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
587 return region; 375 return region;
588 } 376 }
589 } 377 }
590} 378} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
index f8ec6de..eaadc1b 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
@@ -71,19 +71,19 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
71 71
72 #region Internal functions 72 #region Internal functions
73 73
74 public AssetMetadata FetchMetadata(string url, UUID assetID) 74 public AssetBase FetchAsset(string url, UUID assetID)
75 { 75 {
76 if (!url.EndsWith("/") && !url.EndsWith("=")) 76 if (!url.EndsWith("/") && !url.EndsWith("="))
77 url = url + "/"; 77 url = url + "/";
78 78
79 AssetMetadata meta = m_scene.AssetService.GetMetadata(url + assetID.ToString()); 79 AssetBase asset = m_scene.AssetService.Get(url + assetID.ToString());
80 80
81 if (meta != null) 81 if (asset != null)
82 m_log.DebugFormat("[HG ASSET MAPPER]: Fetched metadata for asset {0} of type {1} from {2} ", assetID, meta.Type, url); 82 {
83 else 83 m_log.DebugFormat("[HG ASSET MAPPER]: Copied asset {0} from {1} to local asset server. ", asset.ID, url);
84 m_log.DebugFormat("[HG ASSET MAPPER]: Unable to fetched metadata for asset {0} from {1} ", assetID, url); 84 return asset;
85 85 }
86 return meta; 86 return null;
87 } 87 }
88 88
89 public bool PostAsset(string url, AssetBase asset) 89 public bool PostAsset(string url, AssetBase asset)
@@ -93,7 +93,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
93 if (!url.EndsWith("/") && !url.EndsWith("=")) 93 if (!url.EndsWith("/") && !url.EndsWith("="))
94 url = url + "/"; 94 url = url + "/";
95 95
96 bool success = true;
97 // See long comment in AssetCache.AddAsset 96 // See long comment in AssetCache.AddAsset
98 if (!asset.Temporary || asset.Local) 97 if (!asset.Temporary || asset.Local)
99 { 98 {
@@ -104,7 +103,14 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
104 // not having a global naming infrastructure 103 // not having a global naming infrastructure
105 AssetBase asset1 = new AssetBase(asset.FullID, asset.Name, asset.Type, asset.Metadata.CreatorID); 104 AssetBase asset1 = new AssetBase(asset.FullID, asset.Name, asset.Type, asset.Metadata.CreatorID);
106 Copy(asset, asset1); 105 Copy(asset, asset1);
107 asset1.ID = url + asset.ID; 106 try
107 {
108 asset1.ID = url + asset.ID;
109 }
110 catch
111 {
112 m_log.Warn("[HG ASSET MAPPER]: Oops.");
113 }
108 114
109 AdjustIdentifiers(asset1.Metadata); 115 AdjustIdentifiers(asset1.Metadata);
110 if (asset1.Metadata.Type == (sbyte)AssetType.Object) 116 if (asset1.Metadata.Type == (sbyte)AssetType.Object)
@@ -112,17 +118,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
112 else 118 else
113 asset1.Data = asset.Data; 119 asset1.Data = asset.Data;
114 120
115 string id = m_scene.AssetService.Store(asset1); 121 m_scene.AssetService.Store(asset1);
116 if (id == string.Empty) 122 m_log.DebugFormat("[HG ASSET MAPPER]: Posted copy of asset {0} from local asset server to {1}", asset1.ID, url);
117 {
118 m_log.DebugFormat("[HG ASSET MAPPER]: Asset server {0} did not accept {1}", url, asset.ID);
119 success = false;
120 }
121 else
122 m_log.DebugFormat("[HG ASSET MAPPER]: Posted copy of asset {0} from local asset server to {1}", asset1.ID, url);
123 } 123 }
124 return success; 124 return true;
125 } 125 }
126 else 126 else
127 m_log.Warn("[HG ASSET MAPPER]: Tried to post asset to remote server, but asset not in local cache."); 127 m_log.Warn("[HG ASSET MAPPER]: Tried to post asset to remote server, but asset not in local cache.");
128 128
@@ -222,17 +222,28 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
222 222
223 public void Get(UUID assetID, UUID ownerID, string userAssetURL) 223 public void Get(UUID assetID, UUID ownerID, string userAssetURL)
224 { 224 {
225 // Get the item from the remote asset server onto the local AssetService 225 // Get the item from the remote asset server onto the local AssetCache
226 // and place an entry in m_assetMap
227
228 m_log.Debug("[HG ASSET MAPPER]: Fetching object " + assetID + " from asset server " + userAssetURL);
229 AssetBase asset = FetchAsset(userAssetURL, assetID);
226 230
227 AssetMetadata meta = FetchMetadata(userAssetURL, assetID); 231 if (asset != null)
228 if (meta == null) 232 {
229 return; 233 // OK, now fetch the inside.
234 Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>();
235 HGUuidGatherer uuidGatherer = new HGUuidGatherer(this, m_scene.AssetService, userAssetURL);
236 uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids);
237 if (ids.ContainsKey(assetID))
238 ids.Remove(assetID);
239 foreach (UUID uuid in ids.Keys)
240 FetchAsset(userAssetURL, uuid);
230 241
231 // The act of gathering UUIDs downloads the assets from the remote server 242 m_log.DebugFormat("[HG ASSET MAPPER]: Successfully fetched asset {0} from asset server {1}", asset.ID, userAssetURL);
232 Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>();
233 HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, userAssetURL);
234 uuidGatherer.GatherAssetUuids(assetID, (AssetType)meta.Type, ids);
235 243
244 }
245 else
246 m_log.Warn("[HG ASSET MAPPER]: Could not fetch asset from remote asset server " + userAssetURL);
236 } 247 }
237 248
238 249
@@ -246,23 +257,19 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
246 if (asset != null) 257 if (asset != null)
247 { 258 {
248 Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>(); 259 Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>();
249 HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, string.Empty); 260 HGUuidGatherer uuidGatherer = new HGUuidGatherer(this, m_scene.AssetService, string.Empty);
250 uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids); 261 uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids);
251 bool success = false;
252 foreach (UUID uuid in ids.Keys) 262 foreach (UUID uuid in ids.Keys)
253 { 263 {
254 asset = m_scene.AssetService.Get(uuid.ToString()); 264 asset = m_scene.AssetService.Get(uuid.ToString());
255 if (asset == null) 265 if (asset == null)
256 m_log.DebugFormat("[HG ASSET MAPPER]: Could not find asset {0}", uuid); 266 m_log.DebugFormat("[HG ASSET MAPPER]: Could not find asset {0}", uuid);
257 else 267 else
258 success = PostAsset(userAssetURL, asset); 268 PostAsset(userAssetURL, asset);
259 } 269 }
260 270
261 // maybe all pieces got there... 271 // maybe all pieces got there...
262 if (!success) 272 m_log.DebugFormat("[HG ASSET MAPPER]: Successfully posted item {0} to asset server {1}", assetID, userAssetURL);
263 m_log.DebugFormat("[HG ASSET MAPPER]: Problems posting item {0} to asset server {1}", assetID, userAssetURL);
264 else
265 m_log.DebugFormat("[HG ASSET MAPPER]: Successfully posted item {0} to asset server {1}", assetID, userAssetURL);
266 273
267 } 274 }
268 else 275 else
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
index 6bb758e..cf72b58 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
@@ -92,7 +92,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
92 m_HomeURI = thisModuleConfig.GetString("HomeURI", m_HomeURI); 92 m_HomeURI = thisModuleConfig.GetString("HomeURI", m_HomeURI);
93 m_OutboundPermission = thisModuleConfig.GetBoolean("OutboundPermission", true); 93 m_OutboundPermission = thisModuleConfig.GetBoolean("OutboundPermission", true);
94 m_ThisGatekeeper = thisModuleConfig.GetString("Gatekeeper", string.Empty); 94 m_ThisGatekeeper = thisModuleConfig.GetString("Gatekeeper", string.Empty);
95 m_RestrictInventoryAccessAbroad = thisModuleConfig.GetBoolean("RestrictInventoryAccessAbroad", true); 95 m_RestrictInventoryAccessAbroad = thisModuleConfig.GetBoolean("RestrictInventoryAccessAbroad", false);
96 } 96 }
97 else 97 else
98 m_log.Warn("[HG INVENTORY ACCESS MODULE]: HGInventoryAccessModule configs not found. ProfileServerURI not set!"); 98 m_log.Warn("[HG INVENTORY ACCESS MODULE]: HGInventoryAccessModule configs not found. ProfileServerURI not set!");
@@ -263,13 +263,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
263 //} 263 //}
264 264
265 // OK, we're done fetching. Pass it up to the default RezObject 265 // OK, we're done fetching. Pass it up to the default RezObject
266 SceneObjectGroup sog = base.RezObject(remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection, 266 return base.RezObject(remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection,
267 RezSelected, RemoveItem, fromTaskID, attachment); 267 RezSelected, RemoveItem, fromTaskID, attachment);
268
269 if (sog == null)
270 remoteClient.SendAgentAlertMessage("Unable to rez: problem accessing inventory or locating assets", false);
271
272 return sog;
273 268
274 } 269 }
275 270
@@ -313,8 +308,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
313 protected override InventoryItemBase GetItem(UUID agentID, UUID itemID) 308 protected override InventoryItemBase GetItem(UUID agentID, UUID itemID)
314 { 309 {
315 InventoryItemBase item = base.GetItem(agentID, itemID); 310 InventoryItemBase item = base.GetItem(agentID, itemID);
316 if (item == null)
317 return null;
318 311
319 string userAssetServer = string.Empty; 312 string userAssetServer = string.Empty;
320 if (IsForeignUser(agentID, out userAssetServer)) 313 if (IsForeignUser(agentID, out userAssetServer))
@@ -351,7 +344,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
351 344
352 private void ProcessInventoryForArriving(IClientAPI client) 345 private void ProcessInventoryForArriving(IClientAPI client)
353 { 346 {
354 // No-op for now, but we may need to do something for freign users inventory
355 } 347 }
356 348
357 // 349 //
@@ -398,7 +390,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
398 390
399 private void ProcessInventoryForLeaving(IClientAPI client) 391 private void ProcessInventoryForLeaving(IClientAPI client)
400 { 392 {
401 // No-op for now
402 } 393 }
403 394
404 #endregion 395 #endregion
diff --git a/OpenSim/Region/ScriptEngine/Shared/ScriptException.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGUuidGatherer.cs
index f55ba7e..fcb544f 100644
--- a/OpenSim/Region/ScriptEngine/Shared/ScriptException.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGUuidGatherer.cs
@@ -26,19 +26,32 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Runtime.Serialization; 29using System.Collections.Generic;
30 30
31namespace OpenSim.Region.ScriptEngine.Shared 31using OpenSim.Framework;
32using OpenSim.Region.Framework.Scenes;
33using OpenSim.Services.Interfaces;
34using OpenMetaverse;
35
36namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
32{ 37{
33 [Serializable] 38 public class HGUuidGatherer : UuidGatherer
34 public class ScriptException : Exception
35 { 39 {
36 public ScriptException() : base() {} 40 protected string m_assetServerURL;
37 41 protected HGAssetMapper m_assetMapper;
38 public ScriptException(string message) : base(message) {}
39 42
40 public ScriptException(string message, Exception innerException) : base(message, innerException) {} 43 public HGUuidGatherer(HGAssetMapper assMap, IAssetService assetCache, string assetServerURL) : base(assetCache)
44 {
45 m_assetMapper = assMap;
46 m_assetServerURL = assetServerURL;
47 }
41 48
42 public ScriptException(SerializationInfo info, StreamingContext context) :base(info, context) {} 49 protected override AssetBase GetAsset(UUID uuid)
50 {
51 if (string.Empty == m_assetServerURL)
52 return m_assetCache.Get(uuid.ToString());
53 else
54 return m_assetMapper.FetchAsset(m_assetServerURL, uuid);
55 }
43 } 56 }
44} \ No newline at end of file 57}
diff --git a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs
index e411585..e135c21 100644
--- a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs
@@ -95,14 +95,14 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring
95 { 95 {
96 foreach (IMonitor monitor in m_staticMonitors) 96 foreach (IMonitor monitor in m_staticMonitors)
97 { 97 {
98 MainConsole.Instance.OutputFormat( 98 m_log.InfoFormat(
99 "[MONITOR MODULE]: {0} reports {1} = {2}", 99 "[MONITOR MODULE]: {0} reports {1} = {2}",
100 m_scene.RegionInfo.RegionName, monitor.GetFriendlyName(), monitor.GetFriendlyValue()); 100 m_scene.RegionInfo.RegionName, monitor.GetFriendlyName(), monitor.GetFriendlyValue());
101 } 101 }
102 102
103 foreach (KeyValuePair<string, float> tuple in m_scene.StatsReporter.GetExtraSimStats()) 103 foreach (KeyValuePair<string, float> tuple in m_scene.StatsReporter.GetExtraSimStats())
104 { 104 {
105 MainConsole.Instance.OutputFormat( 105 m_log.InfoFormat(
106 "[MONITOR MODULE]: {0} reports {1} = {2}", 106 "[MONITOR MODULE]: {0} reports {1} = {2}",
107 m_scene.RegionInfo.RegionName, tuple.Key, tuple.Value); 107 m_scene.RegionInfo.RegionName, tuple.Key, tuple.Value);
108 } 108 }
diff --git a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs
index fd8d5e3..65e4c90 100755
--- a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs
+++ b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs
@@ -1,170 +1,161 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright 7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright 9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the 12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products 13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission. 14 * derived from this software without specific prior written permission.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY 16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY 19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System; 28using System;
29using System.IO; 29using System.IO;
30using System.Text; 30using System.Text;
31using log4net; 31using log4net;
32 32
33namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging 33namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging
34{ 34{
35 /// <summary> 35 /// <summary>
36 /// Class for writing a high performance, high volume log file. 36 /// Class for writing a high performance, high volume log file.
37 /// Sometimes, to debug, one has a high volume logging to do and the regular 37 /// Sometimes, to debug, one has a high volume logging to do and the regular
38 /// log file output is not appropriate. 38 /// log file output is not appropriate.
39 /// Create a new instance with the parameters needed and 39 /// Create a new instance with the parameters needed and
40 /// call Write() to output a line. Call Close() when finished. 40 /// call Write() to output a line. Call Close() when finished.
41 /// If created with no parameters, it will not log anything. 41 /// If created with no parameters, it will not log anything.
42 /// </summary> 42 /// </summary>
43 public class LogWriter : IDisposable 43 public class LogWriter : IDisposable
44 { 44 {
45 public bool Enabled { get; private set; } 45 public bool Enabled { get; private set; }
46 46
47 private string m_logDirectory = "."; 47 private string m_logDirectory = ".";
48 private int m_logMaxFileTimeMin = 5; // 5 minutes 48 private int m_logMaxFileTimeMin = 5; // 5 minutes
49 public String LogFileHeader { get; set; } 49 public String LogFileHeader { get; set; }
50 50
51 private StreamWriter m_logFile = null; 51 private StreamWriter m_logFile = null;
52 private TimeSpan m_logFileLife; 52 private TimeSpan m_logFileLife;
53 private DateTime m_logFileEndTime; 53 private DateTime m_logFileEndTime;
54 private Object m_logFileWriteLock = new Object(); 54 private Object m_logFileWriteLock = new Object();
55 55
56 // set externally when debugging. If let 'null', this does not write any error messages. 56 // set externally when debugging. If let 'null', this does not write any error messages.
57 public ILog ErrorLogger = null; 57 public ILog ErrorLogger = null;
58 private string LogHeader = "[LOG WRITER]"; 58 private string LogHeader = "[LOG WRITER]";
59 59
60 /// <summary> 60 /// <summary>
61 /// Create a log writer that will not write anything. Good for when not enabled 61 /// Create a log writer that will not write anything. Good for when not enabled
62 /// but the write statements are still in the code. 62 /// but the write statements are still in the code.
63 /// </summary> 63 /// </summary>
64 public LogWriter() 64 public LogWriter()
65 { 65 {
66 Enabled = false; 66 Enabled = false;
67 m_logFile = null; 67 m_logFile = null;
68 } 68 }
69 69
70 /// <summary> 70 /// <summary>
71 /// Create a log writer instance. 71 /// Create a log writer instance.
72 /// </summary> 72 /// </summary>
73 /// <param name="dir">The directory to create the log file in. May be 'null' for default.</param> 73 /// <param name="dir">The directory to create the log file in. May be 'null' for default.</param>
74 /// <param name="headr">The characters that begin the log file name. May be 'null' for default.</param> 74 /// <param name="headr">The characters that begin the log file name. May be 'null' for default.</param>
75 /// <param name="maxFileTime">Maximum age of a log file in minutes. If zero, will set default.</param> 75 /// <param name="maxFileTime">Maximum age of a log file in minutes. If zero, will set default.</param>
76 public LogWriter(string dir, string headr, int maxFileTime) 76 public LogWriter(string dir, string headr, int maxFileTime)
77 { 77 {
78 m_logDirectory = dir == null ? "." : dir; 78 m_logDirectory = dir == null ? "." : dir;
79 79
80 LogFileHeader = headr == null ? "log-" : headr; 80 LogFileHeader = headr == null ? "log-" : headr;
81 81
82 m_logMaxFileTimeMin = maxFileTime; 82 m_logMaxFileTimeMin = maxFileTime;
83 if (m_logMaxFileTimeMin < 1) 83 if (m_logMaxFileTimeMin < 1)
84 m_logMaxFileTimeMin = 5; 84 m_logMaxFileTimeMin = 5;
85 85
86 m_logFileLife = new TimeSpan(0, m_logMaxFileTimeMin, 0); 86 m_logFileLife = new TimeSpan(0, m_logMaxFileTimeMin, 0);
87 m_logFileEndTime = DateTime.Now + m_logFileLife; 87 m_logFileEndTime = DateTime.Now + m_logFileLife;
88 88
89 Enabled = true; 89 Enabled = true;
90 } 90 }
91 91
92 public void Dispose() 92 public void Dispose()
93 { 93 {
94 this.Close(); 94 this.Close();
95 } 95 }
96 96
97 public void Close() 97 public void Close()
98 { 98 {
99 Enabled = false; 99 Enabled = false;
100 if (m_logFile != null) 100 if (m_logFile != null)
101 { 101 {
102 m_logFile.Close(); 102 m_logFile.Close();
103 m_logFile.Dispose(); 103 m_logFile.Dispose();
104 m_logFile = null; 104 m_logFile = null;
105 } 105 }
106 } 106 }
107 107
108 public void Write(string line, params object[] args) 108 public void Write(string line, params object[] args)
109 { 109 {
110 if (!Enabled) return; 110 if (!Enabled) return;
111 Write(String.Format(line, args)); 111 Write(String.Format(line, args));
112 } 112 }
113 113
114 public void Flush() 114 public void Write(string line)
115 { 115 {
116 if (!Enabled) return; 116 if (!Enabled) return;
117 if (m_logFile != null) 117 try
118 { 118 {
119 m_logFile.Flush(); 119 lock (m_logFileWriteLock)
120 } 120 {
121 } 121 DateTime now = DateTime.Now;
122 122 if (m_logFile == null || now > m_logFileEndTime)
123 public void Write(string line) 123 {
124 { 124 if (m_logFile != null)
125 if (!Enabled) return; 125 {
126 try 126 m_logFile.Close();
127 { 127 m_logFile.Dispose();
128 lock (m_logFileWriteLock) 128 m_logFile = null;
129 { 129 }
130 DateTime now = DateTime.Now; 130
131 if (m_logFile == null || now > m_logFileEndTime) 131 // First log file or time has expired, start writing to a new log file
132 { 132 m_logFileEndTime = now + m_logFileLife;
133 if (m_logFile != null) 133 string path = (m_logDirectory.Length > 0 ? m_logDirectory
134 { 134 + System.IO.Path.DirectorySeparatorChar.ToString() : "")
135 m_logFile.Close(); 135 + String.Format("{0}{1}.log", LogFileHeader, now.ToString("yyyyMMddHHmmss"));
136 m_logFile.Dispose(); 136 m_logFile = new StreamWriter(File.Open(path, FileMode.Append, FileAccess.Write));
137 m_logFile = null; 137 }
138 } 138 if (m_logFile != null)
139 139 {
140 // First log file or time has expired, start writing to a new log file 140 StringBuilder buff = new StringBuilder(line.Length + 25);
141 m_logFileEndTime = now + m_logFileLife; 141 buff.Append(now.ToString("yyyyMMddHHmmssfff"));
142 string path = (m_logDirectory.Length > 0 ? m_logDirectory 142 // buff.Append(now.ToString("yyyyMMddHHmmss"));
143 + System.IO.Path.DirectorySeparatorChar.ToString() : "") 143 buff.Append(",");
144 + String.Format("{0}{1}.log", LogFileHeader, now.ToString("yyyyMMddHHmmss")); 144 buff.Append(line);
145 m_logFile = new StreamWriter(File.Open(path, FileMode.Append, FileAccess.Write)); 145 buff.Append("\r\n");
146 } 146 m_logFile.Write(buff.ToString());
147 if (m_logFile != null) 147 }
148 { 148 }
149 StringBuilder buff = new StringBuilder(line.Length + 25); 149 }
150 buff.Append(now.ToString("yyyyMMddHHmmssfff")); 150 catch (Exception e)
151 // buff.Append(now.ToString("yyyyMMddHHmmss")); 151 {
152 buff.Append(","); 152 if (ErrorLogger != null)
153 buff.Append(line); 153 {
154 buff.Append("\r\n"); 154 ErrorLogger.ErrorFormat("{0}: FAILURE WRITING TO LOGFILE: {1}", LogHeader, e);
155 m_logFile.Write(buff.ToString()); 155 }
156 } 156 Enabled = false;
157 } 157 }
158 } 158 return;
159 catch (Exception e) 159 }
160 { 160 }
161 if (ErrorLogger != null) 161} \ No newline at end of file
162 {
163 ErrorLogger.ErrorFormat("{0}: FAILURE WRITING TO LOGFILE: {1}", LogHeader, e);
164 }
165 Enabled = false;
166 }
167 return;
168 }
169 }
170}
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs
index acefc97..4eecaa2 100644
--- a/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs
@@ -137,9 +137,6 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
137 ud.FirstName = words[0]; 137 ud.FirstName = words[0];
138 ud.LastName = "@" + words[1]; 138 ud.LastName = "@" + words[1];
139 users.Add(ud); 139 users.Add(ud);
140 // WARNING! that uriStr is not quite right... it may be missing the / at the end,
141 // which will cause trouble (duplicate entries on some tables). We should
142 // get the UUI instead from the UAS. TO BE FIXED.
143 AddUser(userID, names[0], names[1], uriStr); 140 AddUser(userID, names[0], names[1], uriStr);
144 m_log.DebugFormat("[USER MANAGEMENT MODULE]: User {0}@{1} found", words[0], words[1]); 141 m_log.DebugFormat("[USER MANAGEMENT MODULE]: User {0}@{1} found", words[0], words[1]);
145 } 142 }
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
index b4811da..f4ed67b 100644
--- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
@@ -31,7 +31,6 @@ using System.Reflection;
31 31
32using OpenSim.Framework; 32using OpenSim.Framework;
33using OpenSim.Framework.Console; 33using OpenSim.Framework.Console;
34using OpenSim.Region.ClientStack.LindenUDP;
35using OpenSim.Region.Framework; 34using OpenSim.Region.Framework;
36using OpenSim.Region.Framework.Interfaces; 35using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes; 36using OpenSim.Region.Framework.Scenes;
@@ -430,7 +429,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
430 429
431 public void AddUser(UUID uuid, string first, string last, string homeURL) 430 public void AddUser(UUID uuid, string first, string last, string homeURL)
432 { 431 {
433 //m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, first {1}, last {2}, url {3}", uuid, first, last, homeURL); 432 // m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, first {1}, last {2}, url {3}", uuid, first, last, homeURL);
433
434 AddUser(uuid, homeURL + ";" + first + " " + last); 434 AddUser(uuid, homeURL + ";" + first + " " + last);
435 } 435 }
436 436
@@ -553,8 +553,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
553 MainConsole.Instance.Output("-----------------------------------------------------------------------------"); 553 MainConsole.Instance.Output("-----------------------------------------------------------------------------");
554 foreach (KeyValuePair<UUID, UserData> kvp in m_UserCache) 554 foreach (KeyValuePair<UUID, UserData> kvp in m_UserCache)
555 { 555 {
556 MainConsole.Instance.Output(String.Format("{0} {1} {2} ({3})", 556 MainConsole.Instance.Output(String.Format("{0} {1} {2}",
557 kvp.Key, kvp.Value.FirstName, kvp.Value.LastName, kvp.Value.HomeURL)); 557 kvp.Key, kvp.Value.FirstName, kvp.Value.LastName));
558 } 558 }
559 559
560 return; 560 return;
diff --git a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml
index 6c73d91..424e0ab 100644
--- a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml
+++ b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml
@@ -15,7 +15,6 @@
15 <RegionModule id="InventoryAccessModule" type="OpenSim.Region.CoreModules.Framework.InventoryAccess.BasicInventoryAccessModule" /> 15 <RegionModule id="InventoryAccessModule" type="OpenSim.Region.CoreModules.Framework.InventoryAccess.BasicInventoryAccessModule" />
16 <RegionModule id="HGInventoryAccessModule" type="OpenSim.Region.CoreModules.Framework.InventoryAccess.HGInventoryAccessModule" /> 16 <RegionModule id="HGInventoryAccessModule" type="OpenSim.Region.CoreModules.Framework.InventoryAccess.HGInventoryAccessModule" />
17 <RegionModule id="LandManagementModule" type="OpenSim.Region.CoreModules.World.Land.LandManagementModule" /> 17 <RegionModule id="LandManagementModule" type="OpenSim.Region.CoreModules.World.Land.LandManagementModule" />
18 <RegionModule id="DwellModule" type="OpenSim.Region.CoreModules.World.Land.DwellModule" />
19 <RegionModule id="PrimCountModule" type="OpenSim.Region.CoreModules.World.Land.PrimCountModule" /> 18 <RegionModule id="PrimCountModule" type="OpenSim.Region.CoreModules.World.Land.PrimCountModule" />
20 <RegionModule id="ExportSerialisationModule" type="OpenSim.Region.CoreModules.World.Serialiser.SerialiserModule" /> 19 <RegionModule id="ExportSerialisationModule" type="OpenSim.Region.CoreModules.World.Serialiser.SerialiserModule" />
21 <RegionModule id="ArchiverModule" type="OpenSim.Region.CoreModules.World.Archiver.ArchiverModule" /> 20 <RegionModule id="ArchiverModule" type="OpenSim.Region.CoreModules.World.Archiver.ArchiverModule" />
diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs
deleted file mode 100644
index fce9490..0000000
--- a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs
+++ /dev/null
@@ -1,61 +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.Drawing;
30using OpenSim.Region.Framework.Interfaces;
31
32namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
33{
34 public class DynamicTexture : IDynamicTexture
35 {
36 public string InputCommands { get; private set; }
37 public Uri InputUri { get; private set; }
38 public string InputParams { get; private set; }
39 public byte[] Data { get; private set; }
40 public Size Size { get; private set; }
41 public bool IsReuseable { get; private set; }
42
43 public DynamicTexture(string inputCommands, string inputParams, byte[] data, Size size, bool isReuseable)
44 {
45 InputCommands = inputCommands;
46 InputParams = inputParams;
47 Data = data;
48 Size = size;
49 IsReuseable = isReuseable;
50 }
51
52 public DynamicTexture(Uri inputUri, string inputParams, byte[] data, Size size, bool isReuseable)
53 {
54 InputUri = inputUri;
55 InputParams = inputParams;
56 Data = data;
57 Size = size;
58 IsReuseable = isReuseable;
59 }
60 }
61} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
index 93a045e..18bd018 100644
--- a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
@@ -42,29 +42,13 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
42{ 42{
43 public class DynamicTextureModule : IRegionModule, IDynamicTextureManager 43 public class DynamicTextureModule : IRegionModule, IDynamicTextureManager
44 { 44 {
45// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 45 //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 46
47 private const int ALL_SIDES = -1; 47 private const int ALL_SIDES = -1;
48 48
49 public const int DISP_EXPIRE = 1; 49 public const int DISP_EXPIRE = 1;
50 public const int DISP_TEMP = 2; 50 public const int DISP_TEMP = 2;
51 51
52 /// <summary>
53 /// If true then where possible dynamic textures are reused.
54 /// </summary>
55 public bool ReuseTextures { get; set; }
56
57 /// <summary>
58 /// If false, then textures which have a low data size are not reused when ReuseTextures = true.
59 /// </summary>
60 /// <remarks>
61 /// LL viewers 3.3.4 and before appear to not fully render textures pulled from the viewer cache if those
62 /// textures have a relatively high pixel surface but a small data size. Typically, this appears to happen
63 /// if the data size is smaller than the viewer's discard level 2 size estimate. So if this is setting is
64 /// false, textures smaller than the calculation in IsSizeReuseable are always regenerated rather than reused
65 /// to work around this problem.</remarks>
66 public bool ReuseLowDataTextures { get; set; }
67
68 private Dictionary<UUID, Scene> RegisteredScenes = new Dictionary<UUID, Scene>(); 52 private Dictionary<UUID, Scene> RegisteredScenes = new Dictionary<UUID, Scene>();
69 53
70 private Dictionary<string, IDynamicTextureRender> RenderPlugins = 54 private Dictionary<string, IDynamicTextureRender> RenderPlugins =
@@ -72,15 +56,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
72 56
73 private Dictionary<UUID, DynamicTextureUpdater> Updaters = new Dictionary<UUID, DynamicTextureUpdater>(); 57 private Dictionary<UUID, DynamicTextureUpdater> Updaters = new Dictionary<UUID, DynamicTextureUpdater>();
74 58
75 /// <summary>
76 /// Record dynamic textures that we can reuse for a given data and parameter combination rather than
77 /// regenerate.
78 /// </summary>
79 /// <remarks>
80 /// Key is string.Format("{0}{1}", data
81 /// </remarks>
82 private Cache m_reuseableDynamicTextures;
83
84 #region IDynamicTextureManager Members 59 #region IDynamicTextureManager Members
85 60
86 public void RegisterRender(string handleType, IDynamicTextureRender render) 61 public void RegisterRender(string handleType, IDynamicTextureRender render)
@@ -94,17 +69,17 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
94 /// <summary> 69 /// <summary>
95 /// Called by code which actually renders the dynamic texture to supply texture data. 70 /// Called by code which actually renders the dynamic texture to supply texture data.
96 /// </summary> 71 /// </summary>
97 /// <param name="updaterId"></param> 72 /// <param name="id"></param>
98 /// <param name="texture"></param> 73 /// <param name="data"></param>
99 public void ReturnData(UUID updaterId, IDynamicTexture texture) 74 public void ReturnData(UUID id, byte[] data)
100 { 75 {
101 DynamicTextureUpdater updater = null; 76 DynamicTextureUpdater updater = null;
102 77
103 lock (Updaters) 78 lock (Updaters)
104 { 79 {
105 if (Updaters.ContainsKey(updaterId)) 80 if (Updaters.ContainsKey(id))
106 { 81 {
107 updater = Updaters[updaterId]; 82 updater = Updaters[id];
108 } 83 }
109 } 84 }
110 85
@@ -113,16 +88,7 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
113 if (RegisteredScenes.ContainsKey(updater.SimUUID)) 88 if (RegisteredScenes.ContainsKey(updater.SimUUID))
114 { 89 {
115 Scene scene = RegisteredScenes[updater.SimUUID]; 90 Scene scene = RegisteredScenes[updater.SimUUID];
116 UUID newTextureID = updater.DataReceived(texture.Data, scene); 91 updater.DataReceived(data, scene);
117
118 if (ReuseTextures
119 && !updater.BlendWithOldTexture
120 && texture.IsReuseable
121 && (ReuseLowDataTextures || IsDataSizeReuseable(texture)))
122 {
123 m_reuseableDynamicTextures.Store(
124 GenerateReusableTextureKey(texture.InputCommands, texture.InputParams), newTextureID);
125 }
126 } 92 }
127 } 93 }
128 94
@@ -138,27 +104,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
138 } 104 }
139 } 105 }
140 106
141 /// <summary>
142 /// Determines whether the texture is reuseable based on its data size.
143 /// </summary>
144 /// <remarks>
145 /// This is a workaround for a viewer bug where very small data size textures relative to their pixel size
146 /// are not redisplayed properly when pulled from cache. The calculation here is based on the typical discard
147 /// level of 2, a 'rate' of 0.125 and 4 components (which makes for a factor of 0.5).
148 /// </remarks>
149 /// <returns></returns>
150 private bool IsDataSizeReuseable(IDynamicTexture texture)
151 {
152// Console.WriteLine("{0} {1}", texture.Size.Width, texture.Size.Height);
153 int discardLevel2DataThreshold = (int)Math.Ceiling((texture.Size.Width >> 2) * (texture.Size.Height >> 2) * 0.5);
154
155// m_log.DebugFormat(
156// "[DYNAMIC TEXTURE MODULE]: Discard level 2 threshold {0}, texture data length {1}",
157// discardLevel2DataThreshold, texture.Data.Length);
158
159 return discardLevel2DataThreshold < texture.Data.Length;
160 }
161
162 public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, 107 public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url,
163 string extraParams, int updateTimer) 108 string extraParams, int updateTimer)
164 { 109 {
@@ -222,61 +167,22 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
222 public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, 167 public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data,
223 string extraParams, int updateTimer, bool SetBlending, int disp, byte AlphaValue, int face) 168 string extraParams, int updateTimer, bool SetBlending, int disp, byte AlphaValue, int face)
224 { 169 {
225 if (!RenderPlugins.ContainsKey(contentType)) 170 if (RenderPlugins.ContainsKey(contentType))
226 return UUID.Zero;
227
228 Scene scene;
229 RegisteredScenes.TryGetValue(simID, out scene);
230
231 if (scene == null)
232 return UUID.Zero;
233
234 SceneObjectPart part = scene.GetSceneObjectPart(primID);
235
236 if (part == null)
237 return UUID.Zero;
238
239 // If we want to reuse dynamic textures then we have to ignore any request from the caller to expire
240 // them.
241 if (ReuseTextures)
242 disp = disp & ~DISP_EXPIRE;
243
244 DynamicTextureUpdater updater = new DynamicTextureUpdater();
245 updater.SimUUID = simID;
246 updater.PrimID = primID;
247 updater.ContentType = contentType;
248 updater.BodyData = data;
249 updater.UpdateTimer = updateTimer;
250 updater.UpdaterID = UUID.Random();
251 updater.Params = extraParams;
252 updater.BlendWithOldTexture = SetBlending;
253 updater.FrontAlpha = AlphaValue;
254 updater.Face = face;
255 updater.Url = "Local image";
256 updater.Disp = disp;
257
258 object objReusableTextureUUID = null;
259
260 if (ReuseTextures && !updater.BlendWithOldTexture)
261 { 171 {
262 string reuseableTextureKey = GenerateReusableTextureKey(data, extraParams); 172 DynamicTextureUpdater updater = new DynamicTextureUpdater();
263 objReusableTextureUUID = m_reuseableDynamicTextures.Get(reuseableTextureKey); 173 updater.SimUUID = simID;
264 174 updater.PrimID = primID;
265 if (objReusableTextureUUID != null) 175 updater.ContentType = contentType;
266 { 176 updater.BodyData = data;
267 // If something else has removed this temporary asset from the cache, detect and invalidate 177 updater.UpdateTimer = updateTimer;
268 // our cached uuid. 178 updater.UpdaterID = UUID.Random();
269 if (scene.AssetService.GetMetadata(objReusableTextureUUID.ToString()) == null) 179 updater.Params = extraParams;
270 { 180 updater.BlendWithOldTexture = SetBlending;
271 m_reuseableDynamicTextures.Invalidate(reuseableTextureKey); 181 updater.FrontAlpha = AlphaValue;
272 objReusableTextureUUID = null; 182 updater.Face = face;
273 } 183 updater.Url = "Local image";
274 } 184 updater.Disp = disp;
275 }
276 185
277 // We cannot reuse a dynamic texture if the data is going to be blended with something already there.
278 if (objReusableTextureUUID == null)
279 {
280 lock (Updaters) 186 lock (Updaters)
281 { 187 {
282 if (!Updaters.ContainsKey(updater.UpdaterID)) 188 if (!Updaters.ContainsKey(updater.UpdaterID))
@@ -285,29 +191,11 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
285 } 191 }
286 } 192 }
287 193
288// m_log.DebugFormat(
289// "[DYNAMIC TEXTURE MODULE]: Requesting generation of new dynamic texture for {0} in {1}",
290// part.Name, part.ParentGroup.Scene.Name);
291
292 RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams); 194 RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams);
195 return updater.UpdaterID;
293 } 196 }
294 else 197
295 { 198 return UUID.Zero;
296// m_log.DebugFormat(
297// "[DYNAMIC TEXTURE MODULE]: Reusing cached texture {0} for {1} in {2}",
298// objReusableTextureUUID, part.Name, part.ParentGroup.Scene.Name);
299
300 // No need to add to updaters as the texture is always the same. Not that this functionality
301 // apppears to be implemented anyway.
302 updater.UpdatePart(part, (UUID)objReusableTextureUUID);
303 }
304
305 return updater.UpdaterID;
306 }
307
308 private string GenerateReusableTextureKey(string data, string extraParams)
309 {
310 return string.Format("{0}{1}", data, extraParams);
311 } 199 }
312 200
313 public void GetDrawStringSize(string contentType, string text, string fontName, int fontSize, 201 public void GetDrawStringSize(string contentType, string text, string fontName, int fontSize,
@@ -327,13 +215,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
327 215
328 public void Initialise(Scene scene, IConfigSource config) 216 public void Initialise(Scene scene, IConfigSource config)
329 { 217 {
330 IConfig texturesConfig = config.Configs["Textures"];
331 if (texturesConfig != null)
332 {
333 ReuseTextures = texturesConfig.GetBoolean("ReuseDynamicTextures", false);
334 ReuseLowDataTextures = texturesConfig.GetBoolean("ReuseDynamicLowDataTextures", false);
335 }
336
337 if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID)) 218 if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID))
338 { 219 {
339 RegisteredScenes.Add(scene.RegionInfo.RegionID, scene); 220 RegisteredScenes.Add(scene.RegionInfo.RegionID, scene);
@@ -343,11 +224,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
343 224
344 public void PostInitialise() 225 public void PostInitialise()
345 { 226 {
346 if (ReuseTextures)
347 {
348 m_reuseableDynamicTextures = new Cache(CacheMedium.Memory, CacheStrategy.Conservative);
349 m_reuseableDynamicTextures.DefaultTTL = new TimeSpan(24, 0, 0);
350 }
351 } 227 }
352 228
353 public void Close() 229 public void Close()
@@ -393,60 +269,9 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
393 } 269 }
394 270
395 /// <summary> 271 /// <summary>
396 /// Update the given part with the new texture.
397 /// </summary>
398 /// <returns>
399 /// The old texture UUID.
400 /// </returns>
401 public UUID UpdatePart(SceneObjectPart part, UUID textureID)
402 {
403 UUID oldID;
404
405 lock (part)
406 {
407 // mostly keep the values from before
408 Primitive.TextureEntry tmptex = part.Shape.Textures;
409
410 // FIXME: Need to return the appropriate ID if only a single face is replaced.
411 oldID = tmptex.DefaultTexture.TextureID;
412
413 if (Face == ALL_SIDES)
414 {
415 oldID = tmptex.DefaultTexture.TextureID;
416 tmptex.DefaultTexture.TextureID = textureID;
417 }
418 else
419 {
420 try
421 {
422 Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face);
423 texface.TextureID = textureID;
424 tmptex.FaceTextures[Face] = texface;
425 }
426 catch (Exception)
427 {
428 tmptex.DefaultTexture.TextureID = textureID;
429 }
430 }
431
432 // I'm pretty sure we always want to force this to true
433 // I'm pretty sure noone whats to set fullbright true if it wasn't true before.
434 // tmptex.DefaultTexture.Fullbright = true;
435
436 part.UpdateTextureEntry(tmptex.GetBytes());
437 }
438
439 return oldID;
440 }
441
442 /// <summary>
443 /// Called once new texture data has been received for this updater. 272 /// Called once new texture data has been received for this updater.
444 /// </summary> 273 /// </summary>
445 /// <param name="data"></param> 274 public void DataReceived(byte[] data, Scene scene)
446 /// <param name="scene"></param>
447 /// <param name="isReuseable">True if the data given is reuseable.</param>
448 /// <returns>The asset UUID given to the incoming data.</returns>
449 public UUID DataReceived(byte[] data, Scene scene)
450 { 275 {
451 SceneObjectPart part = scene.GetSceneObjectPart(PrimID); 276 SceneObjectPart part = scene.GetSceneObjectPart(PrimID);
452 277
@@ -456,8 +281,7 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
456 String.Format("DynamicTextureModule: Error preparing image using URL {0}", Url); 281 String.Format("DynamicTextureModule: Error preparing image using URL {0}", Url);
457 scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Say, 282 scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Say,
458 0, part.ParentGroup.RootPart.AbsolutePosition, part.Name, part.UUID, false); 283 0, part.ParentGroup.RootPart.AbsolutePosition, part.Name, part.UUID, false);
459 284 return;
460 return UUID.Zero;
461 } 285 }
462 286
463 byte[] assetData = null; 287 byte[] assetData = null;
@@ -495,29 +319,56 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
495 IJ2KDecoder cacheLayerDecode = scene.RequestModuleInterface<IJ2KDecoder>(); 319 IJ2KDecoder cacheLayerDecode = scene.RequestModuleInterface<IJ2KDecoder>();
496 if (cacheLayerDecode != null) 320 if (cacheLayerDecode != null)
497 { 321 {
498 if (!cacheLayerDecode.Decode(asset.FullID, asset.Data)) 322 cacheLayerDecode.Decode(asset.FullID, asset.Data);
499 m_log.WarnFormat( 323 cacheLayerDecode = null;
500 "[DYNAMIC TEXTURE MODULE]: Decoding of dynamically generated asset {0} for {1} in {2} failed",
501 asset.ID, part.Name, part.ParentGroup.Scene.Name);
502 } 324 }
503 325
504 UUID oldID = UpdatePart(part, asset.FullID); 326 UUID oldID = UUID.Zero;
505 327
506 if (oldID != UUID.Zero && ((Disp & DISP_EXPIRE) != 0)) 328 lock (part)
507 { 329 {
508 if (oldAsset == null) 330 // mostly keep the values from before
509 oldAsset = scene.AssetService.Get(oldID.ToString()); 331 Primitive.TextureEntry tmptex = part.Shape.Textures;
332
333 // remove the old asset from the cache
334 oldID = tmptex.DefaultTexture.TextureID;
335
336 if (Face == ALL_SIDES)
337 {
338 tmptex.DefaultTexture.TextureID = asset.FullID;
339 }
340 else
341 {
342 try
343 {
344 Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face);
345 texface.TextureID = asset.FullID;
346 tmptex.FaceTextures[Face] = texface;
347 }
348 catch (Exception)
349 {
350 tmptex.DefaultTexture.TextureID = asset.FullID;
351 }
352 }
510 353
354 // I'm pretty sure we always want to force this to true
355 // I'm pretty sure noone whats to set fullbright true if it wasn't true before.
356 // tmptex.DefaultTexture.Fullbright = true;
357
358 part.UpdateTextureEntry(tmptex.GetBytes());
359 }
360
361 if (oldID != UUID.Zero && ((Disp & DISP_EXPIRE) != 0))
362 {
363 if (oldAsset == null) oldAsset = scene.AssetService.Get(oldID.ToString());
511 if (oldAsset != null) 364 if (oldAsset != null)
512 { 365 {
513 if (oldAsset.Temporary) 366 if (oldAsset.Temporary == true)
514 { 367 {
515 scene.AssetService.Delete(oldID.ToString()); 368 scene.AssetService.Delete(oldID.ToString());
516 } 369 }
517 } 370 }
518 } 371 }
519
520 return asset.FullID;
521 } 372 }
522 373
523 private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha) 374 private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha)
diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
index 0b9174f..56221aa 100644
--- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
@@ -58,7 +58,6 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
58 public string body; 58 public string body;
59 public int responseCode; 59 public int responseCode;
60 public string responseBody; 60 public string responseBody;
61 public string responseType = "text/plain";
62 //public ManualResetEvent ev; 61 //public ManualResetEvent ev;
63 public bool requestDone; 62 public bool requestDone;
64 public int startTime; 63 public int startTime;
@@ -271,22 +270,6 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
271 } 270 }
272 } 271 }
273 272
274 public void HttpContentType(UUID request, string type)
275 {
276 lock (m_UrlMap)
277 {
278 if (m_RequestMap.ContainsKey(request))
279 {
280 UrlData urlData = m_RequestMap[request];
281 urlData.requests[request].responseType = type;
282 }
283 else
284 {
285 m_log.Info("[HttpRequestHandler] There is no http-in request with id " + request.ToString());
286 }
287 }
288 }
289
290 public void HttpResponse(UUID request, int status, string body) 273 public void HttpResponse(UUID request, int status, string body)
291 { 274 {
292 lock (m_RequestMap) 275 lock (m_RequestMap)
diff --git a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
index 45e6527..6f83948 100644
--- a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
@@ -32,7 +32,6 @@ using System.Net;
32using Nini.Config; 32using Nini.Config;
33using OpenMetaverse; 33using OpenMetaverse;
34using OpenMetaverse.Imaging; 34using OpenMetaverse.Imaging;
35using OpenSim.Region.CoreModules.Scripting.DynamicTexture;
36using OpenSim.Region.Framework.Interfaces; 35using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes; 36using OpenSim.Region.Framework.Scenes;
38using log4net; 37using log4net;
@@ -68,18 +67,12 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
68 return true; 67 return true;
69 } 68 }
70 69
71// public bool AlwaysIdenticalConversion(string bodyData, string extraParams) 70 public byte[] ConvertUrl(string url, string extraParams)
72// {
73// // We don't support conversion of body data.
74// return false;
75// }
76
77 public IDynamicTexture ConvertUrl(string url, string extraParams)
78 { 71 {
79 return null; 72 return null;
80 } 73 }
81 74
82 public IDynamicTexture ConvertData(string bodyData, string extraParams) 75 public byte[] ConvertStream(Stream data, string extraParams)
83 { 76 {
84 return null; 77 return null;
85 } 78 }
@@ -172,11 +165,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
172 165
173 private void HttpRequestReturn(IAsyncResult result) 166 private void HttpRequestReturn(IAsyncResult result)
174 { 167 {
168
175 RequestState state = (RequestState) result.AsyncState; 169 RequestState state = (RequestState) result.AsyncState;
176 WebRequest request = (WebRequest) state.Request; 170 WebRequest request = (WebRequest) state.Request;
177 Stream stream = null; 171 Stream stream = null;
178 byte[] imageJ2000 = new byte[0]; 172 byte[] imageJ2000 = new byte[0];
179 Size newSize = new Size(0, 0);
180 173
181 try 174 try
182 { 175 {
@@ -189,43 +182,37 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
189 try 182 try
190 { 183 {
191 Bitmap image = new Bitmap(stream); 184 Bitmap image = new Bitmap(stream);
185 Size newsize;
192 186
193 // TODO: make this a bit less hard coded 187 // TODO: make this a bit less hard coded
194 if ((image.Height < 64) && (image.Width < 64)) 188 if ((image.Height < 64) && (image.Width < 64))
195 { 189 {
196 newSize.Width = 32; 190 newsize = new Size(32, 32);
197 newSize.Height = 32;
198 } 191 }
199 else if ((image.Height < 128) && (image.Width < 128)) 192 else if ((image.Height < 128) && (image.Width < 128))
200 { 193 {
201 newSize.Width = 64; 194 newsize = new Size(64, 64);
202 newSize.Height = 64;
203 } 195 }
204 else if ((image.Height < 256) && (image.Width < 256)) 196 else if ((image.Height < 256) && (image.Width < 256))
205 { 197 {
206 newSize.Width = 128; 198 newsize = new Size(128, 128);
207 newSize.Height = 128;
208 } 199 }
209 else if ((image.Height < 512 && image.Width < 512)) 200 else if ((image.Height < 512 && image.Width < 512))
210 { 201 {
211 newSize.Width = 256; 202 newsize = new Size(256, 256);
212 newSize.Height = 256;
213 } 203 }
214 else if ((image.Height < 1024 && image.Width < 1024)) 204 else if ((image.Height < 1024 && image.Width < 1024))
215 { 205 {
216 newSize.Width = 512; 206 newsize = new Size(512, 512);
217 newSize.Height = 512;
218 } 207 }
219 else 208 else
220 { 209 {
221 newSize.Width = 1024; 210 newsize = new Size(1024, 1024);
222 newSize.Height = 1024;
223 } 211 }
224 212
225 using (Bitmap resize = new Bitmap(image, newSize)) 213 Bitmap resize = new Bitmap(image, newsize);
226 { 214
227 imageJ2000 = OpenJPEG.EncodeFromImage(resize, true); 215 imageJ2000 = OpenJPEG.EncodeFromImage(resize, true);
228 }
229 } 216 }
230 catch (Exception) 217 catch (Exception)
231 { 218 {
@@ -240,6 +227,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
240 } 227 }
241 catch (WebException) 228 catch (WebException)
242 { 229 {
230
243 } 231 }
244 finally 232 finally
245 { 233 {
@@ -248,14 +236,9 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
248 stream.Close(); 236 stream.Close();
249 } 237 }
250 } 238 }
251 239 m_log.DebugFormat("[LOADIMAGEURLMODULE] Returning {0} bytes of image data for request {1}",
252 m_log.DebugFormat("[LOADIMAGEURLMODULE]: Returning {0} bytes of image data for request {1}",
253 imageJ2000.Length, state.RequestID); 240 imageJ2000.Length, state.RequestID);
254 241 m_textureManager.ReturnData(state.RequestID, imageJ2000);
255 m_textureManager.ReturnData(
256 state.RequestID,
257 new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture(
258 request.RequestUri, null, imageJ2000, newSize, false));
259 } 242 }
260 243
261 #region Nested type: RequestState 244 #region Nested type: RequestState
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
index 41baccc..9787c8c 100644
--- a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
@@ -45,292 +45,31 @@ using OpenSim.Tests.Common.Mock;
45namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests 45namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
46{ 46{
47 [TestFixture] 47 [TestFixture]
48 public class VectorRenderModuleTests : OpenSimTestCase 48 public class VectorRenderModuleTests
49 { 49 {
50 Scene m_scene;
51 DynamicTextureModule m_dtm;
52 VectorRenderModule m_vrm;
53
54 private void SetupScene(bool reuseTextures)
55 {
56 m_scene = new SceneHelpers().SetupScene();
57
58 m_dtm = new DynamicTextureModule();
59 m_dtm.ReuseTextures = reuseTextures;
60// m_dtm.ReuseLowDataTextures = reuseTextures;
61
62 m_vrm = new VectorRenderModule();
63
64 SceneHelpers.SetupSceneModules(m_scene, m_dtm, m_vrm);
65 }
66
67 [Test] 50 [Test]
68 public void TestDraw() 51 public void TestDraw()
69 { 52 {
70 TestHelpers.InMethod(); 53 TestHelpers.InMethod();
71 54
72 SetupScene(false); 55 Scene scene = new SceneHelpers().SetupScene();
73 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); 56 DynamicTextureModule dtm = new DynamicTextureModule();
74 UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; 57 VectorRenderModule vrm = new VectorRenderModule();
75 58 SceneHelpers.SetupSceneModules(scene, dtm, vrm);
76 m_dtm.AddDynamicTextureData(
77 m_scene.RegionInfo.RegionID,
78 so.UUID,
79 m_vrm.GetContentType(),
80 "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;",
81 "",
82 0);
83
84 Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
85 }
86
87 [Test]
88 public void TestRepeatSameDraw()
89 {
90 TestHelpers.InMethod();
91
92 string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
93
94 SetupScene(false);
95 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
96
97 m_dtm.AddDynamicTextureData(
98 m_scene.RegionInfo.RegionID,
99 so.UUID,
100 m_vrm.GetContentType(),
101 dtText,
102 "",
103 0);
104
105 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
106
107 m_dtm.AddDynamicTextureData(
108 m_scene.RegionInfo.RegionID,
109 so.UUID,
110 m_vrm.GetContentType(),
111 dtText,
112 "",
113 0);
114
115 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
116 }
117
118 [Test]
119 public void TestRepeatSameDrawDifferentExtraParams()
120 {
121 TestHelpers.InMethod();
122
123 string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
124
125 SetupScene(false);
126 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
127
128 m_dtm.AddDynamicTextureData(
129 m_scene.RegionInfo.RegionID,
130 so.UUID,
131 m_vrm.GetContentType(),
132 dtText,
133 "",
134 0);
135
136 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
137
138 m_dtm.AddDynamicTextureData(
139 m_scene.RegionInfo.RegionID,
140 so.UUID,
141 m_vrm.GetContentType(),
142 dtText,
143 "alpha:250",
144 0);
145
146 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
147 }
148
149 [Test]
150 public void TestRepeatSameDrawContainingImage()
151 {
152 TestHelpers.InMethod();
153
154 string dtText
155 = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png";
156
157 SetupScene(false);
158 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
159
160 m_dtm.AddDynamicTextureData(
161 m_scene.RegionInfo.RegionID,
162 so.UUID,
163 m_vrm.GetContentType(),
164 dtText,
165 "",
166 0);
167
168 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
169
170 m_dtm.AddDynamicTextureData(
171 m_scene.RegionInfo.RegionID,
172 so.UUID,
173 m_vrm.GetContentType(),
174 dtText,
175 "",
176 0);
177
178 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
179 }
180
181 [Test]
182 public void TestDrawReusingTexture()
183 {
184 TestHelpers.InMethod();
185 59
186 SetupScene(true); 60 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene);
187 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
188 UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; 61 UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
189 62
190 m_dtm.AddDynamicTextureData( 63 dtm.AddDynamicTextureData(
191 m_scene.RegionInfo.RegionID, 64 scene.RegionInfo.RegionID,
192 so.UUID, 65 so.UUID,
193 m_vrm.GetContentType(), 66 vrm.GetContentType(),
194 "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;", 67 "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;",
195 "", 68 "",
196 0); 69 0);
197 70
198 Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
199 }
200
201 [Test]
202 public void TestRepeatSameDrawReusingTexture()
203 {
204 TestHelpers.InMethod();
205// TestHelpers.EnableLogging();
206
207 string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
208
209 SetupScene(true);
210 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
211
212 m_dtm.AddDynamicTextureData(
213 m_scene.RegionInfo.RegionID,
214 so.UUID,
215 m_vrm.GetContentType(),
216 dtText,
217 "",
218 0);
219
220 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
221
222 m_dtm.AddDynamicTextureData(
223 m_scene.RegionInfo.RegionID,
224 so.UUID,
225 m_vrm.GetContentType(),
226 dtText,
227 "",
228 0);
229
230 Assert.That(firstDynamicTextureID, Is.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
231 }
232
233 /// <summary>
234 /// Test a low data dynamically generated texture such that it is treated as a low data texture that causes
235 /// problems for current viewers.
236 /// </summary>
237 /// <remarks>
238 /// As we do not set DynamicTextureModule.ReuseLowDataTextures = true in this test, it should not reuse the
239 /// texture
240 /// </remarks>
241 [Test]
242 public void TestRepeatSameDrawLowDataTexture()
243 {
244 TestHelpers.InMethod();
245// TestHelpers.EnableLogging();
246
247 string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
248
249 SetupScene(true);
250 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
251
252 m_dtm.AddDynamicTextureData(
253 m_scene.RegionInfo.RegionID,
254 so.UUID,
255 m_vrm.GetContentType(),
256 dtText,
257 "1024",
258 0);
259
260 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
261
262 m_dtm.AddDynamicTextureData(
263 m_scene.RegionInfo.RegionID,
264 so.UUID,
265 m_vrm.GetContentType(),
266 dtText,
267 "1024",
268 0);
269
270 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
271 }
272
273 [Test]
274 public void TestRepeatSameDrawDifferentExtraParamsReusingTexture()
275 {
276 TestHelpers.InMethod();
277
278 string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
279
280 SetupScene(true);
281 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
282
283 m_dtm.AddDynamicTextureData(
284 m_scene.RegionInfo.RegionID,
285 so.UUID,
286 m_vrm.GetContentType(),
287 dtText,
288 "",
289 0);
290
291 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
292
293 m_dtm.AddDynamicTextureData(
294 m_scene.RegionInfo.RegionID,
295 so.UUID,
296 m_vrm.GetContentType(),
297 dtText,
298 "alpha:250",
299 0);
300
301 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
302 }
303
304 [Test]
305 public void TestRepeatSameDrawContainingImageReusingTexture()
306 {
307 TestHelpers.InMethod();
308
309 string dtText
310 = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png";
311
312 SetupScene(true);
313 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
314
315 m_dtm.AddDynamicTextureData(
316 m_scene.RegionInfo.RegionID,
317 so.UUID,
318 m_vrm.GetContentType(),
319 dtText,
320 "",
321 0);
322
323 UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
324
325 m_dtm.AddDynamicTextureData(
326 m_scene.RegionInfo.RegionID,
327 so.UUID,
328 m_vrm.GetContentType(),
329 dtText,
330 "",
331 0);
332 71
333 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); 72 Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
334 } 73 }
335 } 74 }
336} \ No newline at end of file 75} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
index 673c2d1..8b2f2f8 100644
--- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
@@ -30,12 +30,10 @@ using System.Drawing;
30using System.Drawing.Imaging; 30using System.Drawing.Imaging;
31using System.Globalization; 31using System.Globalization;
32using System.IO; 32using System.IO;
33using System.Linq;
34using System.Net; 33using System.Net;
35using Nini.Config; 34using Nini.Config;
36using OpenMetaverse; 35using OpenMetaverse;
37using OpenMetaverse.Imaging; 36using OpenMetaverse.Imaging;
38using OpenSim.Region.CoreModules.Scripting.DynamicTexture;
39using OpenSim.Region.Framework.Interfaces; 37using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Region.Framework.Scenes; 38using OpenSim.Region.Framework.Scenes;
41using log4net; 39using log4net;
@@ -47,13 +45,9 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
47{ 45{
48 public class VectorRenderModule : IRegionModule, IDynamicTextureRender 46 public class VectorRenderModule : IRegionModule, IDynamicTextureRender
49 { 47 {
50 // These fields exist for testing purposes, please do not remove.
51// private static bool s_flipper;
52// private static byte[] s_asset1Data;
53// private static byte[] s_asset2Data;
54
55 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
56 49
50 private string m_name = "VectorRenderModule";
57 private Scene m_scene; 51 private Scene m_scene;
58 private IDynamicTextureManager m_textureManager; 52 private IDynamicTextureManager m_textureManager;
59 private Graphics m_graph; 53 private Graphics m_graph;
@@ -67,12 +61,12 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
67 61
68 public string GetContentType() 62 public string GetContentType()
69 { 63 {
70 return "vector"; 64 return ("vector");
71 } 65 }
72 66
73 public string GetName() 67 public string GetName()
74 { 68 {
75 return Name; 69 return m_name;
76 } 70 }
77 71
78 public bool SupportsAsynchronous() 72 public bool SupportsAsynchronous()
@@ -80,20 +74,14 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
80 return true; 74 return true;
81 } 75 }
82 76
83// public bool AlwaysIdenticalConversion(string bodyData, string extraParams) 77 public byte[] ConvertUrl(string url, string extraParams)
84// {
85// string[] lines = GetLines(bodyData);
86// return lines.Any((str, r) => str.StartsWith("Image"));
87// }
88
89 public IDynamicTexture ConvertUrl(string url, string extraParams)
90 { 78 {
91 return null; 79 return null;
92 } 80 }
93 81
94 public IDynamicTexture ConvertData(string bodyData, string extraParams) 82 public byte[] ConvertStream(Stream data, string extraParams)
95 { 83 {
96 return Draw(bodyData, extraParams); 84 return null;
97 } 85 }
98 86
99 public bool AsyncConvertUrl(UUID id, string url, string extraParams) 87 public bool AsyncConvertUrl(UUID id, string url, string extraParams)
@@ -103,28 +91,21 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
103 91
104 public bool AsyncConvertData(UUID id, string bodyData, string extraParams) 92 public bool AsyncConvertData(UUID id, string bodyData, string extraParams)
105 { 93 {
106 // XXX: This isn't actually being done asynchronously! 94 Draw(bodyData, id, extraParams);
107 m_textureManager.ReturnData(id, ConvertData(bodyData, extraParams));
108
109 return true; 95 return true;
110 } 96 }
111 97
112 public void GetDrawStringSize(string text, string fontName, int fontSize, 98 public void GetDrawStringSize(string text, string fontName, int fontSize,
113 out double xSize, out double ySize) 99 out double xSize, out double ySize)
114 { 100 {
115 lock (this) 101 using (Font myFont = new Font(fontName, fontSize))
116 { 102 {
117 using (Font myFont = new Font(fontName, fontSize)) 103 SizeF stringSize = new SizeF();
104 lock (m_graph)
118 { 105 {
119 SizeF stringSize = new SizeF(); 106 stringSize = m_graph.MeasureString(text, myFont);
120 107 xSize = stringSize.Width;
121 // XXX: This lock may be unnecessary. 108 ySize = stringSize.Height;
122 lock (m_graph)
123 {
124 stringSize = m_graph.MeasureString(text, myFont);
125 xSize = stringSize.Width;
126 ySize = stringSize.Height;
127 }
128 } 109 }
129 } 110 }
130 } 111 }
@@ -163,13 +144,6 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
163 { 144 {
164 m_textureManager.RegisterRender(GetContentType(), this); 145 m_textureManager.RegisterRender(GetContentType(), this);
165 } 146 }
166
167 // This code exists for testing purposes, please do not remove.
168// s_asset1Data = m_scene.AssetService.Get("00000000-0000-1111-9999-000000000001").Data;
169// s_asset1Data = m_scene.AssetService.Get("9f4acf0d-1841-4e15-bdb8-3a12efc9dd8f").Data;
170
171 // Terrain dirt - smallest bin/assets file (6004 bytes)
172// s_asset2Data = m_scene.AssetService.Get("b8d3965a-ad78-bf43-699b-bff8eca6c975").Data;
173 } 147 }
174 148
175 public void Close() 149 public void Close()
@@ -178,7 +152,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
178 152
179 public string Name 153 public string Name
180 { 154 {
181 get { return "VectorRenderModule"; } 155 get { return m_name; }
182 } 156 }
183 157
184 public bool IsSharedModule 158 public bool IsSharedModule
@@ -188,7 +162,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
188 162
189 #endregion 163 #endregion
190 164
191 private IDynamicTexture Draw(string data, string extraParams) 165 private void Draw(string data, UUID id, string extraParams)
192 { 166 {
193 // We need to cater for old scripts that didnt use extraParams neatly, they use either an integer size which represents both width and height, or setalpha 167 // We need to cater for old scripts that didnt use extraParams neatly, they use either an integer size which represents both width and height, or setalpha
194 // we will now support multiple comma seperated params in the form width:256,height:512,alpha:255 168 // we will now support multiple comma seperated params in the form width:256,height:512,alpha:255
@@ -331,57 +305,40 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
331 305
332 Bitmap bitmap = null; 306 Bitmap bitmap = null;
333 Graphics graph = null; 307 Graphics graph = null;
334 bool reuseable = false;
335 308
336 try 309 try
337 { 310 {
338 // XXX: In testing, it appears that if multiple threads dispose of separate GDI+ objects simultaneously, 311 if (alpha == 256)
339 // the native malloc heap can become corrupted, possibly due to a double free(). This may be due to 312 bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb);
340 // bugs in the underlying libcairo used by mono's libgdiplus.dll on Linux/OSX. These problems were 313 else
341 // seen with both libcario 1.10.2-6.1ubuntu3 and 1.8.10-2ubuntu1. They go away if disposal is perfomed 314 bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);
342 // under lock. 315
343 lock (this) 316 graph = Graphics.FromImage(bitmap);
344 {
345 if (alpha == 256)
346 bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb);
347 else
348 bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);
349 317
350 graph = Graphics.FromImage(bitmap); 318 // this is really just to save people filling the
351 319 // background color in their scripts, only do when fully opaque
352 // this is really just to save people filling the 320 if (alpha >= 255)
353 // background color in their scripts, only do when fully opaque 321 {
354 if (alpha >= 255) 322 using (SolidBrush bgFillBrush = new SolidBrush(bgColor))
355 { 323 {
356 using (SolidBrush bgFillBrush = new SolidBrush(bgColor)) 324 graph.FillRectangle(bgFillBrush, 0, 0, width, height);
357 {
358 graph.FillRectangle(bgFillBrush, 0, 0, width, height);
359 }
360 } 325 }
361 326 }
362 for (int w = 0; w < bitmap.Width; w++) 327
328 for (int w = 0; w < bitmap.Width; w++)
329 {
330 if (alpha <= 255)
363 { 331 {
364 if (alpha <= 255) 332 for (int h = 0; h < bitmap.Height; h++)
365 { 333 {
366 for (int h = 0; h < bitmap.Height; h++) 334 bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h)));
367 {
368 bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h)));
369 }
370 } 335 }
371 } 336 }
372
373 GDIDraw(data, graph, altDataDelim, out reuseable);
374 } 337 }
375 338
339 GDIDraw(data, graph, altDataDelim);
340
376 byte[] imageJ2000 = new byte[0]; 341 byte[] imageJ2000 = new byte[0];
377
378 // This code exists for testing purposes, please do not remove.
379// if (s_flipper)
380// imageJ2000 = s_asset1Data;
381// else
382// imageJ2000 = s_asset2Data;
383//
384// s_flipper = !s_flipper;
385 342
386 try 343 try
387 { 344 {
@@ -394,24 +351,15 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
394 e.Message, e.StackTrace); 351 e.Message, e.StackTrace);
395 } 352 }
396 353
397 return new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture( 354 m_textureManager.ReturnData(id, imageJ2000);
398 data, extraParams, imageJ2000, new Size(width, height), reuseable);
399 } 355 }
400 finally 356 finally
401 { 357 {
402 // XXX: In testing, it appears that if multiple threads dispose of separate GDI+ objects simultaneously, 358 if (graph != null)
403 // the native malloc heap can become corrupted, possibly due to a double free(). This may be due to 359 graph.Dispose();
404 // bugs in the underlying libcairo used by mono's libgdiplus.dll on Linux/OSX. These problems were 360
405 // seen with both libcario 1.10.2-6.1ubuntu3 and 1.8.10-2ubuntu1. They go away if disposal is perfomed 361 if (bitmap != null)
406 // under lock. 362 bitmap.Dispose();
407 lock (this)
408 {
409 if (graph != null)
410 graph.Dispose();
411
412 if (bitmap != null)
413 bitmap.Dispose();
414 }
415 } 363 }
416 } 364 }
417 365
@@ -470,21 +418,8 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
470 } 418 }
471*/ 419*/
472 420
473 /// <summary> 421 private void GDIDraw(string data, Graphics graph, char dataDelim)
474 /// Split input data into discrete command lines.
475 /// </summary>
476 /// <returns></returns>
477 /// <param name='data'></param>
478 /// <param name='dataDelim'></param>
479 private string[] GetLines(string data, char dataDelim)
480 {
481 char[] lineDelimiter = { dataDelim };
482 return data.Split(lineDelimiter);
483 }
484
485 private void GDIDraw(string data, Graphics graph, char dataDelim, out bool reuseable)
486 { 422 {
487 reuseable = true;
488 Point startPoint = new Point(0, 0); 423 Point startPoint = new Point(0, 0);
489 Point endPoint = new Point(0, 0); 424 Point endPoint = new Point(0, 0);
490 Pen drawPen = null; 425 Pen drawPen = null;
@@ -499,9 +434,11 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
499 myFont = new Font(fontName, fontSize); 434 myFont = new Font(fontName, fontSize);
500 myBrush = new SolidBrush(Color.Black); 435 myBrush = new SolidBrush(Color.Black);
501 436
437 char[] lineDelimiter = {dataDelim};
502 char[] partsDelimiter = {','}; 438 char[] partsDelimiter = {','};
439 string[] lines = data.Split(lineDelimiter);
503 440
504 foreach (string line in GetLines(data, dataDelim)) 441 foreach (string line in lines)
505 { 442 {
506 string nextLine = line.Trim(); 443 string nextLine = line.Trim();
507 //replace with switch, or even better, do some proper parsing 444 //replace with switch, or even better, do some proper parsing
@@ -532,10 +469,6 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
532 } 469 }
533 else if (nextLine.StartsWith("Image")) 470 else if (nextLine.StartsWith("Image"))
534 { 471 {
535 // We cannot reuse any generated texture involving fetching an image via HTTP since that image
536 // can change.
537 reuseable = false;
538
539 float x = 0; 472 float x = 0;
540 float y = 0; 473 float y = 0;
541 GetParams(partsDelimiter, ref nextLine, 5, ref x, ref y); 474 GetParams(partsDelimiter, ref nextLine, 5, ref x, ref y);
diff --git a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs
index e167e31..07bb291 100644
--- a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs
@@ -28,7 +28,6 @@
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Text.RegularExpressions;
32using Nini.Config; 31using Nini.Config;
33using OpenMetaverse; 32using OpenMetaverse;
34using OpenSim.Framework; 33using OpenSim.Framework;
@@ -173,42 +172,12 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
173 /// <param name="hostID">UUID of the SceneObjectPart</param> 172 /// <param name="hostID">UUID of the SceneObjectPart</param>
174 /// <param name="channel">channel to listen on</param> 173 /// <param name="channel">channel to listen on</param>
175 /// <param name="name">name to filter on</param> 174 /// <param name="name">name to filter on</param>
176 /// <param name="id"> 175 /// <param name="id">key to filter on (user given, could be totally faked)</param>
177 /// key to filter on (user given, could be totally faked)
178 /// </param>
179 /// <param name="msg">msg to filter on</param>
180 /// <returns>number of the scripts handle</returns>
181 public int Listen(uint localID, UUID itemID, UUID hostID, int channel,
182 string name, UUID id, string msg)
183 {
184 return m_listenerManager.AddListener(localID, itemID, hostID,
185 channel, name, id, msg);
186 }
187
188 /// <summary>
189 /// Create a listen event callback with the specified filters.
190 /// The parameters localID,itemID are needed to uniquely identify
191 /// the script during 'peek' time. Parameter hostID is needed to
192 /// determine the position of the script.
193 /// </summary>
194 /// <param name="localID">localID of the script engine</param>
195 /// <param name="itemID">UUID of the script engine</param>
196 /// <param name="hostID">UUID of the SceneObjectPart</param>
197 /// <param name="channel">channel to listen on</param>
198 /// <param name="name">name to filter on</param>
199 /// <param name="id">
200 /// key to filter on (user given, could be totally faked)
201 /// </param>
202 /// <param name="msg">msg to filter on</param> 176 /// <param name="msg">msg to filter on</param>
203 /// <param name="regexBitfield">
204 /// Bitfield indicating which strings should be processed as regex.
205 /// </param>
206 /// <returns>number of the scripts handle</returns> 177 /// <returns>number of the scripts handle</returns>
207 public int Listen(uint localID, UUID itemID, UUID hostID, int channel, 178 public int Listen(uint localID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg)
208 string name, UUID id, string msg, int regexBitfield)
209 { 179 {
210 return m_listenerManager.AddListener(localID, itemID, hostID, 180 return m_listenerManager.AddListener(localID, itemID, hostID, channel, name, id, msg);
211 channel, name, id, msg, regexBitfield);
212 } 181 }
213 182
214 /// <summary> 183 /// <summary>
@@ -357,7 +326,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
357 if (channel == 0) 326 if (channel == 0)
358 { 327 {
359 // Channel 0 goes to viewer ONLY 328 // Channel 0 goes to viewer ONLY
360 m_scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Broadcast, 0, pos, name, id, target, false, false); 329 m_scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Broadcast, 0, pos, name, id, false, false, target);
361 return true; 330 return true;
362 } 331 }
363 332
@@ -501,25 +470,15 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
501 m_curlisteners = 0; 470 m_curlisteners = 0;
502 } 471 }
503 472
504 public int AddListener(uint localID, UUID itemID, UUID hostID, 473 public int AddListener(uint localID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg)
505 int channel, string name, UUID id, string msg)
506 {
507 return AddListener(localID, itemID, hostID, channel, name, id,
508 msg, 0);
509 }
510
511 public int AddListener(uint localID, UUID itemID, UUID hostID,
512 int channel, string name, UUID id, string msg,
513 int regexBitfield)
514 { 474 {
515 // do we already have a match on this particular filter event? 475 // do we already have a match on this particular filter event?
516 List<ListenerInfo> coll = GetListeners(itemID, channel, name, id, 476 List<ListenerInfo> coll = GetListeners(itemID, channel, name, id, msg);
517 msg);
518 477
519 if (coll.Count > 0) 478 if (coll.Count > 0)
520 { 479 {
521 // special case, called with same filter settings, return same 480 // special case, called with same filter settings, return same handle
522 // handle (2008-05-02, tested on 1.21.1 server, still holds) 481 // (2008-05-02, tested on 1.21.1 server, still holds)
523 return coll[0].GetHandle(); 482 return coll[0].GetHandle();
524 } 483 }
525 484
@@ -531,9 +490,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
531 490
532 if (newHandle > 0) 491 if (newHandle > 0)
533 { 492 {
534 ListenerInfo li = new ListenerInfo(newHandle, localID, 493 ListenerInfo li = new ListenerInfo(newHandle, localID, itemID, hostID, channel, name, id, msg);
535 itemID, hostID, channel, name, id, msg,
536 regexBitfield);
537 494
538 List<ListenerInfo> listeners; 495 List<ListenerInfo> listeners;
539 if (!m_listeners.TryGetValue(channel,out listeners)) 496 if (!m_listeners.TryGetValue(channel,out listeners))
@@ -674,22 +631,6 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
674 return -1; 631 return -1;
675 } 632 }
676 633
677 /// These are duplicated from ScriptBaseClass
678 /// http://opensimulator.org/mantis/view.php?id=6106#c21945
679 #region Constants for the bitfield parameter of osListenRegex
680
681 /// <summary>
682 /// process name parameter as regex
683 /// </summary>
684 public const int OS_LISTEN_REGEX_NAME = 0x1;
685
686 /// <summary>
687 /// process message parameter as regex
688 /// </summary>
689 public const int OS_LISTEN_REGEX_MESSAGE = 0x2;
690
691 #endregion
692
693 // Theres probably a more clever and efficient way to 634 // Theres probably a more clever and efficient way to
694 // do this, maybe with regex. 635 // do this, maybe with regex.
695 // PM2008: Ha, one could even be smart and define a specialized Enumerator. 636 // PM2008: Ha, one could even be smart and define a specialized Enumerator.
@@ -715,10 +656,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
715 { 656 {
716 continue; 657 continue;
717 } 658 }
718 if (li.GetName().Length > 0 && ( 659 if (li.GetName().Length > 0 && !li.GetName().Equals(name))
719 ((li.RegexBitfield & OS_LISTEN_REGEX_NAME) != OS_LISTEN_REGEX_NAME && !li.GetName().Equals(name)) ||
720 ((li.RegexBitfield & OS_LISTEN_REGEX_NAME) == OS_LISTEN_REGEX_NAME && !Regex.IsMatch(name, li.GetName()))
721 ))
722 { 660 {
723 continue; 661 continue;
724 } 662 }
@@ -726,10 +664,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
726 { 664 {
727 continue; 665 continue;
728 } 666 }
729 if (li.GetMessage().Length > 0 && ( 667 if (li.GetMessage().Length > 0 && !li.GetMessage().Equals(msg))
730 ((li.RegexBitfield & OS_LISTEN_REGEX_MESSAGE) != OS_LISTEN_REGEX_MESSAGE && !li.GetMessage().Equals(msg)) ||
731 ((li.RegexBitfield & OS_LISTEN_REGEX_MESSAGE) == OS_LISTEN_REGEX_MESSAGE && !Regex.IsMatch(msg, li.GetMessage()))
732 ))
733 { 668 {
734 continue; 669 continue;
735 } 670 }
@@ -762,13 +697,10 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
762 { 697 {
763 int idx = 0; 698 int idx = 0;
764 Object[] item = new Object[6]; 699 Object[] item = new Object[6];
765 int dataItemLength = 6;
766 700
767 while (idx < data.Length) 701 while (idx < data.Length)
768 { 702 {
769 dataItemLength = (idx + 7 == data.Length || (idx + 7 < data.Length && data[idx + 7] is bool)) ? 7 : 6; 703 Array.Copy(data, idx, item, 0, 6);
770 item = new Object[dataItemLength];
771 Array.Copy(data, idx, item, 0, dataItemLength);
772 704
773 ListenerInfo info = 705 ListenerInfo info =
774 ListenerInfo.FromData(localID, itemID, hostID, item); 706 ListenerInfo.FromData(localID, itemID, hostID, item);
@@ -780,12 +712,12 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
780 m_listeners[(int)item[2]].Add(info); 712 m_listeners[(int)item[2]].Add(info);
781 } 713 }
782 714
783 idx+=dataItemLength; 715 idx+=6;
784 } 716 }
785 } 717 }
786 } 718 }
787 719
788 public class ListenerInfo : IWorldCommListenerInfo 720 public class ListenerInfo: IWorldCommListenerInfo
789 { 721 {
790 private bool m_active; // Listener is active or not 722 private bool m_active; // Listener is active or not
791 private int m_handle; // Assigned handle of this listener 723 private int m_handle; // Assigned handle of this listener
@@ -799,29 +731,16 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
799 731
800 public ListenerInfo(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, UUID id, string message) 732 public ListenerInfo(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, UUID id, string message)
801 { 733 {
802 Initialise(handle, localID, ItemID, hostID, channel, name, id, 734 Initialise(handle, localID, ItemID, hostID, channel, name, id, message);
803 message, 0);
804 }
805
806 public ListenerInfo(int handle, uint localID, UUID ItemID,
807 UUID hostID, int channel, string name, UUID id,
808 string message, int regexBitfield)
809 {
810 Initialise(handle, localID, ItemID, hostID, channel, name, id,
811 message, regexBitfield);
812 } 735 }
813 736
814 public ListenerInfo(ListenerInfo li, string name, UUID id, string message) 737 public ListenerInfo(ListenerInfo li, string name, UUID id, string message)
815 { 738 {
816 Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID, li.m_channel, name, id, message, 0); 739 Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID, li.m_channel, name, id, message);
817 }
818
819 public ListenerInfo(ListenerInfo li, string name, UUID id, string message, int regexBitfield)
820 {
821 Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID, li.m_channel, name, id, message, regexBitfield);
822 } 740 }
823 741
824 private void Initialise(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, UUID id, string message, int regexBitfield) 742 private void Initialise(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name,
743 UUID id, string message)
825 { 744 {
826 m_active = true; 745 m_active = true;
827 m_handle = handle; 746 m_handle = handle;
@@ -832,12 +751,11 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
832 m_name = name; 751 m_name = name;
833 m_id = id; 752 m_id = id;
834 m_message = message; 753 m_message = message;
835 RegexBitfield = regexBitfield;
836 } 754 }
837 755
838 public Object[] GetSerializationData() 756 public Object[] GetSerializationData()
839 { 757 {
840 Object[] data = new Object[7]; 758 Object[] data = new Object[6];
841 759
842 data[0] = m_active; 760 data[0] = m_active;
843 data[1] = m_handle; 761 data[1] = m_handle;
@@ -845,19 +763,16 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
845 data[3] = m_name; 763 data[3] = m_name;
846 data[4] = m_id; 764 data[4] = m_id;
847 data[5] = m_message; 765 data[5] = m_message;
848 data[6] = RegexBitfield;
849 766
850 return data; 767 return data;
851 } 768 }
852 769
853 public static ListenerInfo FromData(uint localID, UUID ItemID, UUID hostID, Object[] data) 770 public static ListenerInfo FromData(uint localID, UUID ItemID, UUID hostID, Object[] data)
854 { 771 {
855 ListenerInfo linfo = new ListenerInfo((int)data[1], localID, ItemID, hostID, (int)data[2], (string)data[3], (UUID)data[4], (string)data[5]); 772 ListenerInfo linfo = new ListenerInfo((int)data[1], localID,
856 linfo.m_active = (bool)data[0]; 773 ItemID, hostID, (int)data[2], (string)data[3],
857 if (data.Length >= 7) 774 (UUID)data[4], (string)data[5]);
858 { 775 linfo.m_active=(bool)data[0];
859 linfo.RegexBitfield = (int)data[6];
860 }
861 776
862 return linfo; 777 return linfo;
863 } 778 }
@@ -916,7 +831,5 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
916 { 831 {
917 return m_id; 832 return m_id;
918 } 833 }
919
920 public int RegexBitfield { get; private set; }
921 } 834 }
922} 835}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs
index 1e1c7d0..008465f 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs
@@ -56,8 +56,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
56 56
57 private bool m_Enabled = false; 57 private bool m_Enabled = false;
58 58
59 private AssetPermissions m_AssetPerms;
60
61 public Type ReplaceableInterface 59 public Type ReplaceableInterface
62 { 60 {
63 get { return null; } 61 get { return null; }
@@ -130,9 +128,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
130 if (m_LocalAssetServiceURI != string.Empty) 128 if (m_LocalAssetServiceURI != string.Empty)
131 m_LocalAssetServiceURI = m_LocalAssetServiceURI.Trim('/'); 129 m_LocalAssetServiceURI = m_LocalAssetServiceURI.Trim('/');
132 130
133 IConfig hgConfig = source.Configs["HGAssetService"];
134 m_AssetPerms = new AssetPermissions(hgConfig); // it's ok if arg is null
135
136 m_Enabled = true; 131 m_Enabled = true;
137 m_log.Info("[HG ASSET CONNECTOR]: HG asset broker enabled"); 132 m_log.Info("[HG ASSET CONNECTOR]: HG asset broker enabled");
138 } 133 }
@@ -211,11 +206,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
211 asset = m_HGService.Get(id); 206 asset = m_HGService.Get(id);
212 if (asset != null) 207 if (asset != null)
213 { 208 {
214 // Now store it locally, if allowed 209 // Now store it locally
215 if (m_AssetPerms.AllowedImport(asset.Type)) 210 // For now, let me just do it for textures and scripts
211 if (((AssetType)asset.Type == AssetType.Texture) ||
212 ((AssetType)asset.Type == AssetType.LSLBytecode) ||
213 ((AssetType)asset.Type == AssetType.LSLText))
214 {
216 m_GridService.Store(asset); 215 m_GridService.Store(asset);
217 else 216 }
218 return null;
219 } 217 }
220 } 218 }
221 else 219 else
@@ -330,12 +328,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
330 328
331 string id = string.Empty; 329 string id = string.Empty;
332 if (IsHG(asset.ID)) 330 if (IsHG(asset.ID))
333 { 331 id = m_HGService.Store(asset);
334 if (m_AssetPerms.AllowedExport(asset.Type))
335 id = m_HGService.Store(asset);
336 else
337 return String.Empty;
338 }
339 else 332 else
340 id = m_GridService.Store(asset); 333 id = m_GridService.Store(asset);
341 334
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs
index 449c1f1..c78915f 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs
@@ -204,11 +204,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
204 public byte[] GetData(string id) 204 public byte[] GetData(string id)
205 { 205 {
206// m_log.DebugFormat("[LOCAL ASSET SERVICES CONNECTOR]: Requesting data for asset {0}", id); 206// m_log.DebugFormat("[LOCAL ASSET SERVICES CONNECTOR]: Requesting data for asset {0}", id);
207 207
208 AssetBase asset = null; 208 AssetBase asset = m_Cache.Get(id);
209
210 if (m_Cache != null)
211 asset = m_Cache.Get(id);
212 209
213 if (asset != null) 210 if (asset != null)
214 return asset.Data; 211 return asset.Data;
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs
deleted file mode 100644
index 1982473..0000000
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs
+++ /dev/null
@@ -1,136 +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.Reflection;
32using System.Threading;
33using log4net.Config;
34using Nini.Config;
35using NUnit.Framework;
36using OpenMetaverse;
37using OpenSim.Framework;
38using OpenSim.Region.Framework.Scenes;
39using OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset;
40using OpenSim.Tests.Common;
41
42namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset.Tests
43{
44 [TestFixture]
45 public class AssetConnectorsTests : OpenSimTestCase
46 {
47 [Test]
48 public void TestAddAsset()
49 {
50 TestHelpers.InMethod();
51// TestHelpers.EnableLogging();
52
53 IConfigSource config = new IniConfigSource();
54 config.AddConfig("Modules");
55 config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector");
56 config.AddConfig("AssetService");
57 config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService");
58 config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll");
59
60 LocalAssetServicesConnector lasc = new LocalAssetServicesConnector();
61 lasc.Initialise(config);
62
63 AssetBase a1 = AssetHelpers.CreateNotecardAsset();
64 lasc.Store(a1);
65
66 AssetBase retreivedA1 = lasc.Get(a1.ID);
67 Assert.That(retreivedA1.ID, Is.EqualTo(a1.ID));
68 Assert.That(retreivedA1.Metadata.ID, Is.EqualTo(a1.Metadata.ID));
69 Assert.That(retreivedA1.Data.Length, Is.EqualTo(a1.Data.Length));
70
71 AssetMetadata retrievedA1Metadata = lasc.GetMetadata(a1.ID);
72 Assert.That(retrievedA1Metadata.ID, Is.EqualTo(a1.ID));
73
74 byte[] retrievedA1Data = lasc.GetData(a1.ID);
75 Assert.That(retrievedA1Data.Length, Is.EqualTo(a1.Data.Length));
76
77 // TODO: Add cache and check that this does receive a copy of the asset
78 }
79
80 [Test]
81 public void TestAddTemporaryAsset()
82 {
83 TestHelpers.InMethod();
84// TestHelpers.EnableLogging();
85
86 IConfigSource config = new IniConfigSource();
87 config.AddConfig("Modules");
88 config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector");
89 config.AddConfig("AssetService");
90 config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService");
91 config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll");
92
93 LocalAssetServicesConnector lasc = new LocalAssetServicesConnector();
94 lasc.Initialise(config);
95
96 AssetBase a1 = AssetHelpers.CreateNotecardAsset();
97 a1.Temporary = true;
98
99 lasc.Store(a1);
100
101 Assert.That(lasc.Get(a1.ID), Is.Null);
102 Assert.That(lasc.GetData(a1.ID), Is.Null);
103 Assert.That(lasc.GetMetadata(a1.ID), Is.Null);
104
105 // TODO: Add cache and check that this does receive a copy of the asset
106 }
107
108 [Test]
109 public void TestAddLocalAsset()
110 {
111 TestHelpers.InMethod();
112// TestHelpers.EnableLogging();
113
114 IConfigSource config = new IniConfigSource();
115 config.AddConfig("Modules");
116 config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector");
117 config.AddConfig("AssetService");
118 config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService");
119 config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll");
120
121 LocalAssetServicesConnector lasc = new LocalAssetServicesConnector();
122 lasc.Initialise(config);
123
124 AssetBase a1 = AssetHelpers.CreateNotecardAsset();
125 a1.Local = true;
126
127 lasc.Store(a1);
128
129 Assert.That(lasc.Get(a1.ID), Is.Null);
130 Assert.That(lasc.GetData(a1.ID), Is.Null);
131 Assert.That(lasc.GetMetadata(a1.ID), Is.Null);
132
133 // TODO: Add cache and check that this does receive a copy of the asset
134 }
135 }
136} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs
index 4338133..b286d17 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs
@@ -43,15 +43,11 @@ using OpenSim.Tests.Common;
43namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests 43namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests
44{ 44{
45 [TestFixture] 45 [TestFixture]
46 public class GridConnectorsTests : OpenSimTestCase 46 public class GridConnectorsTests
47 { 47 {
48 LocalGridServicesConnector m_LocalConnector; 48 LocalGridServicesConnector m_LocalConnector;
49 49 private void SetUp()
50 [SetUp]
51 public override void SetUp()
52 { 50 {
53 base.SetUp();
54
55 IConfigSource config = new IniConfigSource(); 51 IConfigSource config = new IniConfigSource();
56 config.AddConfig("Modules"); 52 config.AddConfig("Modules");
57 config.AddConfig("GridService"); 53 config.AddConfig("GridService");
@@ -75,6 +71,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests
75 TestHelpers.InMethod(); 71 TestHelpers.InMethod();
76// log4net.Config.XmlConfigurator.Configure(); 72// log4net.Config.XmlConfigurator.Configure();
77 73
74 SetUp();
75
78 // Create 4 regions 76 // Create 4 regions
79 GridRegion r1 = new GridRegion(); 77 GridRegion r1 = new GridRegion();
80 r1.RegionName = "Test Region 1"; 78 r1.RegionName = "Test Region 1";
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs
index 221f815..b0edce7 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs
@@ -65,13 +65,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser
65 65
66 public void OnMakeRootAgent(ScenePresence sp) 66 public void OnMakeRootAgent(ScenePresence sp)
67 { 67 {
68// m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected root presence {0} in {1}", sp.UUID, sp.Scene.RegionInfo.RegionName);
69
68 if (sp.PresenceType != PresenceType.Npc) 70 if (sp.PresenceType != PresenceType.Npc)
69 {
70 string userid = sp.Scene.UserManagementModule.GetUserUUI(sp.UUID);
71 //m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected root presence {0} in {1}", userid, sp.Scene.RegionInfo.RegionName);
72 m_GridUserService.SetLastPosition( 71 m_GridUserService.SetLastPosition(
73 userid, UUID.Zero, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat); 72 sp.UUID.ToString(), UUID.Zero, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat);
74 }
75 } 73 }
76 74
77 public void OnNewClient(IClientAPI client) 75 public void OnNewClient(IClientAPI client)
@@ -84,16 +82,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser
84 if (client.SceneAgent.IsChildAgent) 82 if (client.SceneAgent.IsChildAgent)
85 return; 83 return;
86 84
87 string userId = client.AgentId.ToString(); 85// m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected client logout {0} in {1}", client.AgentId, client.Scene.RegionInfo.RegionName);
88 if (client.Scene is Scene)
89 {
90 Scene s = (Scene)client.Scene;
91 userId = s.UserManagementModule.GetUserUUI(client.AgentId);
92 }
93 //m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected client logout {0} in {1}", userId, client.Scene.RegionInfo.RegionName);
94
95 m_GridUserService.LoggedOut( 86 m_GridUserService.LoggedOut(
96 userId, client.SessionId, client.Scene.RegionInfo.RegionID, 87 client.AgentId.ToString(), client.SessionId, client.Scene.RegionInfo.RegionID,
97 client.SceneAgent.AbsolutePosition, client.SceneAgent.Lookat); 88 client.SceneAgent.AbsolutePosition, client.SceneAgent.Lookat);
98 } 89 }
99 } 90 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs
index 04acf67..badb552 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs
@@ -44,9 +44,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser
44 { 44 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 46
47 private const int KEEPTIME = 30; // 30 secs
48 private ExpiringCache<string, GridUserInfo> m_Infos = new ExpiringCache<string, GridUserInfo>();
49
50 #region ISharedRegionModule 47 #region ISharedRegionModule
51 48
52 private bool m_Enabled = false; 49 private bool m_Enabled = false;
@@ -131,60 +128,23 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser
131 128
132 public bool LoggedOut(string userID, UUID sessionID, UUID region, Vector3 position, Vector3 lookat) 129 public bool LoggedOut(string userID, UUID sessionID, UUID region, Vector3 position, Vector3 lookat)
133 { 130 {
134 if (m_Infos.Contains(userID))
135 m_Infos.Remove(userID);
136
137 return m_RemoteConnector.LoggedOut(userID, sessionID, region, position, lookat); 131 return m_RemoteConnector.LoggedOut(userID, sessionID, region, position, lookat);
138 } 132 }
139 133
140 134
141 public bool SetHome(string userID, UUID regionID, Vector3 position, Vector3 lookAt) 135 public bool SetHome(string userID, UUID regionID, Vector3 position, Vector3 lookAt)
142 { 136 {
143 if (m_RemoteConnector.SetHome(userID, regionID, position, lookAt)) 137 return m_RemoteConnector.SetHome(userID, regionID, position, lookAt);
144 {
145 // Update the cache too
146 GridUserInfo info = null;
147 if (m_Infos.TryGetValue(userID, out info))
148 {
149 info.HomeRegionID = regionID;
150 info.HomePosition = position;
151 info.HomeLookAt = lookAt;
152 }
153 return true;
154 }
155
156 return false;
157 } 138 }
158 139
159 public bool SetLastPosition(string userID, UUID sessionID, UUID regionID, Vector3 position, Vector3 lookAt) 140 public bool SetLastPosition(string userID, UUID sessionID, UUID regionID, Vector3 position, Vector3 lookAt)
160 { 141 {
161 if (m_RemoteConnector.SetLastPosition(userID, sessionID, regionID, position, lookAt)) 142 return m_RemoteConnector.SetLastPosition(userID, sessionID, regionID, position, lookAt);
162 {
163 // Update the cache too
164 GridUserInfo info = null;
165 if (m_Infos.TryGetValue(userID, out info))
166 {
167 info.LastRegionID = regionID;
168 info.LastPosition = position;
169 info.LastLookAt = lookAt;
170 }
171 return true;
172 }
173
174 return false;
175 } 143 }
176 144
177 public GridUserInfo GetGridUserInfo(string userID) 145 public GridUserInfo GetGridUserInfo(string userID)
178 { 146 {
179 GridUserInfo info = null; 147 return m_RemoteConnector.GetGridUserInfo(userID);
180 if (m_Infos.TryGetValue(userID, out info))
181 return info;
182
183 info = m_RemoteConnector.GetGridUserInfo(userID);
184
185 m_Infos.AddOrUpdate(userID, info, KEEPTIME);
186
187 return info;
188 } 148 }
189 149
190 public GridUserInfo[] GetGridUserInfo(string[] userID) 150 public GridUserInfo[] GetGridUserInfo(string[] userID)
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
index 8ed1833..6eb99ea 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
@@ -313,11 +313,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
313 313
314 if (m_scenes.ContainsKey(destination.RegionID)) 314 if (m_scenes.ContainsKey(destination.RegionID))
315 { 315 {
316// m_log.DebugFormat( 316 Util.FireAndForget(delegate { m_scenes[destination.RegionID].IncomingCloseAgent(id); });
317// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate",
318// s.RegionInfo.RegionName, destination.RegionHandle);
319
320 Util.FireAndForget(delegate { m_scenes[destination.RegionID].IncomingCloseAgent(id, false); });
321 return true; 317 return true;
322 } 318 }
323 //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent"); 319 //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent");
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
index ade5e76..619550c 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
@@ -43,7 +43,6 @@ using OpenSim.Region.Framework.Interfaces;
43using OpenSim.Region.Framework.Scenes; 43using OpenSim.Region.Framework.Scenes;
44using OpenSim.Region.Framework.Scenes.Serialization; 44using OpenSim.Region.Framework.Scenes.Serialization;
45using OpenSim.Services.Interfaces; 45using OpenSim.Services.Interfaces;
46using System.Threading;
47 46
48namespace OpenSim.Region.CoreModules.World.Archiver 47namespace OpenSim.Region.CoreModules.World.Archiver
49{ 48{
@@ -53,30 +52,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
53 public class ArchiveReadRequest 52 public class ArchiveReadRequest
54 { 53 {
55 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
56
57 /// <summary>
58 /// Contains data used while dearchiving a single scene.
59 /// </summary>
60 private class DearchiveContext
61 {
62 public Scene Scene { get; set; }
63
64 public List<string> SerialisedSceneObjects { get; set; }
65
66 public List<string> SerialisedParcels { get; set; }
67
68 public List<SceneObjectGroup> SceneObjects { get; set; }
69
70 public DearchiveContext(Scene scene)
71 {
72 Scene = scene;
73 SerialisedSceneObjects = new List<string>();
74 SerialisedParcels = new List<string>();
75 SceneObjects = new List<SceneObjectGroup>();
76 }
77 }
78 55
79
80 /// <summary> 56 /// <summary>
81 /// The maximum major version of OAR that we can read. Minor versions shouldn't need a max number since version 57 /// The maximum major version of OAR that we can read. Minor versions shouldn't need a max number since version
82 /// bumps here should be compatible. 58 /// bumps here should be compatible.
@@ -86,10 +62,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
86 /// <summary> 62 /// <summary>
87 /// Has the control file been loaded for this archive? 63 /// Has the control file been loaded for this archive?
88 /// </summary> 64 /// </summary>
89 public bool ControlFileLoaded { get; private set; } 65 public bool ControlFileLoaded { get; private set; }
90 66
91 protected string m_loadPath; 67 protected Scene m_scene;
92 protected Scene m_rootScene;
93 protected Stream m_loadStream; 68 protected Stream m_loadStream;
94 protected Guid m_requestId; 69 protected Guid m_requestId;
95 protected string m_errorMessage; 70 protected string m_errorMessage;
@@ -116,27 +91,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver
116 { 91 {
117 if (m_UserMan == null) 92 if (m_UserMan == null)
118 { 93 {
119 m_UserMan = m_rootScene.RequestModuleInterface<IUserManagement>(); 94 m_UserMan = m_scene.RequestModuleInterface<IUserManagement>();
120 } 95 }
121 return m_UserMan; 96 return m_UserMan;
122 } 97 }
123 } 98 }
124 99
125 /// <summary>
126 /// Used to cache lookups for valid groups.
127 /// </summary>
128 private IDictionary<UUID, bool> m_validGroupUuids = new Dictionary<UUID, bool>();
129
130 private IGroupsModule m_groupsModule;
131
132 private IAssetService m_assetService = null;
133
134
135 public ArchiveReadRequest(Scene scene, string loadPath, bool merge, bool skipAssets, Guid requestId) 100 public ArchiveReadRequest(Scene scene, string loadPath, bool merge, bool skipAssets, Guid requestId)
136 { 101 {
137 m_rootScene = scene; 102 m_scene = scene;
138 103
139 m_loadPath = loadPath;
140 try 104 try
141 { 105 {
142 m_loadStream = new GZipStream(ArchiveHelpers.GetStream(loadPath), CompressionMode.Decompress); 106 m_loadStream = new GZipStream(ArchiveHelpers.GetStream(loadPath), CompressionMode.Decompress);
@@ -156,15 +120,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver
156 120
157 // Zero can never be a valid user id 121 // Zero can never be a valid user id
158 m_validUserUuids[UUID.Zero] = false; 122 m_validUserUuids[UUID.Zero] = false;
159
160 m_groupsModule = m_rootScene.RequestModuleInterface<IGroupsModule>();
161 m_assetService = m_rootScene.AssetService;
162 } 123 }
163 124
164 public ArchiveReadRequest(Scene scene, Stream loadStream, bool merge, bool skipAssets, Guid requestId) 125 public ArchiveReadRequest(Scene scene, Stream loadStream, bool merge, bool skipAssets, Guid requestId)
165 { 126 {
166 m_rootScene = scene; 127 m_scene = scene;
167 m_loadPath = null;
168 m_loadStream = loadStream; 128 m_loadStream = loadStream;
169 m_merge = merge; 129 m_merge = merge;
170 m_skipAssets = skipAssets; 130 m_skipAssets = skipAssets;
@@ -172,9 +132,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver
172 132
173 // Zero can never be a valid user id 133 // Zero can never be a valid user id
174 m_validUserUuids[UUID.Zero] = false; 134 m_validUserUuids[UUID.Zero] = false;
175
176 m_groupsModule = m_rootScene.RequestModuleInterface<IGroupsModule>();
177 m_assetService = m_rootScene.AssetService;
178 } 135 }
179 136
180 /// <summary> 137 /// <summary>
@@ -182,25 +139,25 @@ namespace OpenSim.Region.CoreModules.World.Archiver
182 /// </summary> 139 /// </summary>
183 public void DearchiveRegion() 140 public void DearchiveRegion()
184 { 141 {
142 // The same code can handle dearchiving 0.1 and 0.2 OpenSim Archive versions
143 DearchiveRegion0DotStar();
144 }
145
146 private void DearchiveRegion0DotStar()
147 {
185 int successfulAssetRestores = 0; 148 int successfulAssetRestores = 0;
186 int failedAssetRestores = 0; 149 int failedAssetRestores = 0;
150 List<string> serialisedSceneObjects = new List<string>();
151 List<string> serialisedParcels = new List<string>();
152 string filePath = "NONE";
187 153
188 DearchiveScenesInfo dearchivedScenes; 154 TarArchiveReader archive = new TarArchiveReader(m_loadStream);
189
190 // We dearchive all the scenes at once, because the files in the TAR archive might be mixed.
191 // Therefore, we have to keep track of the dearchive context of all the scenes.
192 Dictionary<UUID, DearchiveContext> sceneContexts = new Dictionary<UUID, DearchiveContext>();
193
194 string fullPath = "NONE";
195 TarArchiveReader archive = null;
196 byte[] data; 155 byte[] data;
197 TarArchiveReader.TarEntryType entryType; 156 TarArchiveReader.TarEntryType entryType;
198 157
199 try 158 try
200 { 159 {
201 FindAndLoadControlFile(out archive, out dearchivedScenes); 160 while ((data = archive.ReadEntry(out filePath, out entryType)) != null)
202
203 while ((data = archive.ReadEntry(out fullPath, out entryType)) != null)
204 { 161 {
205 //m_log.DebugFormat( 162 //m_log.DebugFormat(
206 // "[ARCHIVER]: Successfully read {0} ({1} bytes)", filePath, data.Length); 163 // "[ARCHIVER]: Successfully read {0} ({1} bytes)", filePath, data.Length);
@@ -208,30 +165,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
208 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType) 165 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType)
209 continue; 166 continue;
210 167
211
212 // Find the scene that this file belongs to
213
214 Scene scene;
215 string filePath;
216 if (!dearchivedScenes.GetRegionFromPath(fullPath, out scene, out filePath))
217 continue; // this file belongs to a region that we're not loading
218
219 DearchiveContext sceneContext = null;
220 if (scene != null)
221 {
222 if (!sceneContexts.TryGetValue(scene.RegionInfo.RegionID, out sceneContext))
223 {
224 sceneContext = new DearchiveContext(scene);
225 sceneContexts.Add(scene.RegionInfo.RegionID, sceneContext);
226 }
227 }
228
229
230 // Process the file
231
232 if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH)) 168 if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH))
233 { 169 {
234 sceneContext.SerialisedSceneObjects.Add(Encoding.UTF8.GetString(data)); 170 serialisedSceneObjects.Add(Encoding.UTF8.GetString(data));
235 } 171 }
236 else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH) && !m_skipAssets) 172 else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH) && !m_skipAssets)
237 { 173 {
@@ -245,19 +181,19 @@ namespace OpenSim.Region.CoreModules.World.Archiver
245 } 181 }
246 else if (!m_merge && filePath.StartsWith(ArchiveConstants.TERRAINS_PATH)) 182 else if (!m_merge && filePath.StartsWith(ArchiveConstants.TERRAINS_PATH))
247 { 183 {
248 LoadTerrain(scene, filePath, data); 184 LoadTerrain(filePath, data);
249 } 185 }
250 else if (!m_merge && filePath.StartsWith(ArchiveConstants.SETTINGS_PATH)) 186 else if (!m_merge && filePath.StartsWith(ArchiveConstants.SETTINGS_PATH))
251 { 187 {
252 LoadRegionSettings(scene, filePath, data, dearchivedScenes); 188 LoadRegionSettings(filePath, data);
253 } 189 }
254 else if (!m_merge && filePath.StartsWith(ArchiveConstants.LANDDATA_PATH)) 190 else if (!m_merge && filePath.StartsWith(ArchiveConstants.LANDDATA_PATH))
255 { 191 {
256 sceneContext.SerialisedParcels.Add(Encoding.UTF8.GetString(data)); 192 serialisedParcels.Add(Encoding.UTF8.GetString(data));
257 } 193 }
258 else if (filePath == ArchiveConstants.CONTROL_FILE_PATH) 194 else if (filePath == ArchiveConstants.CONTROL_FILE_PATH)
259 { 195 {
260 // Ignore, because we already read the control file 196 LoadControlFile(filePath, data);
261 } 197 }
262 } 198 }
263 199
@@ -265,16 +201,15 @@ namespace OpenSim.Region.CoreModules.World.Archiver
265 } 201 }
266 catch (Exception e) 202 catch (Exception e)
267 { 203 {
268 m_log.Error( 204 m_log.ErrorFormat(
269 String.Format("[ARCHIVER]: Aborting load with error in archive file {0} ", fullPath), e); 205 "[ARCHIVER]: Aborting load with error in archive file {0}. {1}", filePath, e);
270 m_errorMessage += e.ToString(); 206 m_errorMessage += e.ToString();
271 m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, new List<UUID>(), m_errorMessage); 207 m_scene.EventManager.TriggerOarFileLoaded(m_requestId, m_errorMessage);
272 return; 208 return;
273 } 209 }
274 finally 210 finally
275 { 211 {
276 if (archive != null) 212 archive.Close();
277 archive.Close();
278 } 213 }
279 214
280 if (!m_skipAssets) 215 if (!m_skipAssets)
@@ -288,143 +223,32 @@ namespace OpenSim.Region.CoreModules.World.Archiver
288 } 223 }
289 } 224 }
290 225
291 foreach (DearchiveContext sceneContext in sceneContexts.Values) 226 if (!m_merge)
292 { 227 {
293 m_log.InfoFormat("[ARCHIVER]: Loading region {0}", sceneContext.Scene.RegionInfo.RegionName); 228 m_log.Info("[ARCHIVER]: Clearing all existing scene objects");
294 229 m_scene.DeleteAllSceneObjects();
295 if (!m_merge)
296 {
297 m_log.Info("[ARCHIVER]: Clearing all existing scene objects");
298 sceneContext.Scene.DeleteAllSceneObjects();
299 }
300
301 try
302 {
303 LoadParcels(sceneContext.Scene, sceneContext.SerialisedParcels);
304 LoadObjects(sceneContext.Scene, sceneContext.SerialisedSceneObjects, sceneContext.SceneObjects);
305
306 // Inform any interested parties that the region has changed. We waited until now so that all
307 // of the region's objects will be loaded when we send this notification.
308 IEstateModule estateModule = sceneContext.Scene.RequestModuleInterface<IEstateModule>();
309 if (estateModule != null)
310 estateModule.TriggerRegionInfoChange();
311 }
312 catch (Exception e)
313 {
314 m_log.Error("[ARCHIVER]: Error loading parcels or objects ", e);
315 m_errorMessage += e.ToString();
316 m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, new List<UUID>(), m_errorMessage);
317 return;
318 }
319 } 230 }
320 231
321 // Start the scripts. We delayed this because we want the OAR to finish loading ASAP, so 232 LoadParcels(serialisedParcels);
322 // that users can enter the scene. If we allow the scripts to start in the loop above 233 LoadObjects(serialisedSceneObjects);
323 // then they significantly increase the time until the OAR finishes loading.
324 Util.FireAndForget(delegate(object o)
325 {
326 Thread.Sleep(15000);
327 m_log.Info("[ARCHIVER]: Starting scripts in scene objects");
328
329 foreach (DearchiveContext sceneContext in sceneContexts.Values)
330 {
331 foreach (SceneObjectGroup sceneObject in sceneContext.SceneObjects)
332 {
333 sceneObject.CreateScriptInstances(0, false, sceneContext.Scene.DefaultScriptEngine, 0); // StateSource.RegionStart
334 sceneObject.ResumeScripts();
335 }
336
337 sceneContext.SceneObjects.Clear();
338 }
339 });
340 234
341 m_log.InfoFormat("[ARCHIVER]: Successfully loaded archive"); 235 m_log.InfoFormat("[ARCHIVER]: Successfully loaded archive");
342 236
343 m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, dearchivedScenes.GetLoadedScenes(), m_errorMessage); 237 m_scene.EventManager.TriggerOarFileLoaded(m_requestId, m_errorMessage);
344 }
345
346 /// <summary>
347 /// Searches through the files in the archive for the control file, and reads it.
348 /// We must read the control file first, in order to know which regions are available.
349 /// </summary>
350 /// <remarks>
351 /// In most cases the control file *is* first, since that's how we create archives. However,
352 /// it's possible that someone rewrote the archive externally so we can't rely on this fact.
353 /// </remarks>
354 /// <param name="archive"></param>
355 /// <param name="dearchivedScenes"></param>
356 private void FindAndLoadControlFile(out TarArchiveReader archive, out DearchiveScenesInfo dearchivedScenes)
357 {
358 archive = new TarArchiveReader(m_loadStream);
359 dearchivedScenes = new DearchiveScenesInfo();
360
361 string filePath;
362 byte[] data;
363 TarArchiveReader.TarEntryType entryType;
364 bool firstFile = true;
365
366 while ((data = archive.ReadEntry(out filePath, out entryType)) != null)
367 {
368 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType)
369 continue;
370
371 if (filePath == ArchiveConstants.CONTROL_FILE_PATH)
372 {
373 LoadControlFile(filePath, data, dearchivedScenes);
374
375 // Find which scenes are available in the simulator
376 ArchiveScenesGroup simulatorScenes = new ArchiveScenesGroup();
377 SceneManager.Instance.ForEachScene(delegate(Scene scene2)
378 {
379 simulatorScenes.AddScene(scene2);
380 });
381 simulatorScenes.CalcSceneLocations();
382 dearchivedScenes.SetSimulatorScenes(m_rootScene, simulatorScenes);
383
384 // If the control file wasn't the first file then reset the read pointer
385 if (!firstFile)
386 {
387 m_log.Warn("Control file wasn't the first file in the archive");
388 if (m_loadStream.CanSeek)
389 {
390 m_loadStream.Seek(0, SeekOrigin.Begin);
391 }
392 else if (m_loadPath != null)
393 {
394 archive.Close();
395 archive = null;
396 m_loadStream.Close();
397 m_loadStream = null;
398 m_loadStream = new GZipStream(ArchiveHelpers.GetStream(m_loadPath), CompressionMode.Decompress);
399 archive = new TarArchiveReader(m_loadStream);
400 }
401 else
402 {
403 // There isn't currently a scenario where this happens, but it's best to add a check just in case
404 throw new Exception("Error reading archive: control file wasn't the first file, and the input stream doesn't allow seeking");
405 }
406 }
407
408 return;
409 }
410
411 firstFile = false;
412 }
413
414 throw new Exception("Control file not found");
415 } 238 }
416 239
417 /// <summary> 240 /// <summary>
418 /// Load serialized scene objects. 241 /// Load serialized scene objects.
419 /// </summary> 242 /// </summary>
420 protected void LoadObjects(Scene scene, List<string> serialisedSceneObjects, List<SceneObjectGroup> sceneObjects) 243 /// <param name="serialisedSceneObjects"></param>
244 protected void LoadObjects(List<string> serialisedSceneObjects)
421 { 245 {
422 // Reload serialized prims 246 // Reload serialized prims
423 m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count); 247 m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count);
424 248
425 UUID oldTelehubUUID = scene.RegionInfo.RegionSettings.TelehubObject; 249 UUID oldTelehubUUID = m_scene.RegionInfo.RegionSettings.TelehubObject;
426 250
427 IRegionSerialiserModule serialiser = scene.RequestModuleInterface<IRegionSerialiserModule>(); 251 IRegionSerialiserModule serialiser = m_scene.RequestModuleInterface<IRegionSerialiserModule>();
428 int sceneObjectsLoadedCount = 0; 252 int sceneObjectsLoadedCount = 0;
429 253
430 foreach (string serialisedSceneObject in serialisedSceneObjects) 254 foreach (string serialisedSceneObject in serialisedSceneObjects)
@@ -445,7 +269,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
445 269
446 SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject); 270 SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject);
447 271
448 bool isTelehub = (sceneObject.UUID == oldTelehubUUID) && (oldTelehubUUID != UUID.Zero); 272 bool isTelehub = (sceneObject.UUID == oldTelehubUUID);
449 273
450 // For now, give all incoming scene objects new uuids. This will allow scenes to be cloned 274 // For now, give all incoming scene objects new uuids. This will allow scenes to be cloned
451 // on the same region server and multiple examples a single object archive to be imported 275 // on the same region server and multiple examples a single object archive to be imported
@@ -455,8 +279,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
455 if (isTelehub) 279 if (isTelehub)
456 { 280 {
457 // Change the Telehub Object to the new UUID 281 // Change the Telehub Object to the new UUID
458 scene.RegionInfo.RegionSettings.TelehubObject = sceneObject.UUID; 282 m_scene.RegionInfo.RegionSettings.TelehubObject = sceneObject.UUID;
459 scene.RegionInfo.RegionSettings.Save(); 283 m_scene.RegionInfo.RegionSettings.Save();
460 oldTelehubUUID = UUID.Zero; 284 oldTelehubUUID = UUID.Zero;
461 } 285 }
462 286
@@ -466,20 +290,17 @@ namespace OpenSim.Region.CoreModules.World.Archiver
466 { 290 {
467 if (part.CreatorData == null || part.CreatorData == string.Empty) 291 if (part.CreatorData == null || part.CreatorData == string.Empty)
468 { 292 {
469 if (!ResolveUserUuid(scene, part.CreatorID)) 293 if (!ResolveUserUuid(part.CreatorID))
470 part.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner; 294 part.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner;
471 } 295 }
472 if (UserManager != null) 296 if (UserManager != null)
473 UserManager.AddUser(part.CreatorID, part.CreatorData); 297 UserManager.AddUser(part.CreatorID, part.CreatorData);
474 298
475 if (!ResolveUserUuid(scene, part.OwnerID)) 299 if (!ResolveUserUuid(part.OwnerID))
476 part.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner; 300 part.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
477
478 if (!ResolveUserUuid(scene, part.LastOwnerID))
479 part.LastOwnerID = scene.RegionInfo.EstateSettings.EstateOwner;
480 301
481 if (!ResolveGroupUuid(part.GroupID)) 302 if (!ResolveUserUuid(part.LastOwnerID))
482 part.GroupID = UUID.Zero; 303 part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
483 304
484 // And zap any troublesome sit target information 305 // And zap any troublesome sit target information
485// part.SitTargetOrientation = new Quaternion(0, 0, 0, 1); 306// part.SitTargetOrientation = new Quaternion(0, 0, 0, 1);
@@ -490,14 +311,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver
490 // being no copy/no mod for everyone 311 // being no copy/no mod for everyone
491 lock (part.TaskInventory) 312 lock (part.TaskInventory)
492 { 313 {
493 if (!ResolveUserUuid(scene, part.CreatorID)) 314 if (!ResolveUserUuid(part.CreatorID))
494 part.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner; 315 part.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner;
495 316
496 if (!ResolveUserUuid(scene, part.OwnerID)) 317 if (!ResolveUserUuid(part.OwnerID))
497 part.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner; 318 part.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
498 319
499 if (!ResolveUserUuid(scene, part.LastOwnerID)) 320 if (!ResolveUserUuid(part.LastOwnerID))
500 part.LastOwnerID = scene.RegionInfo.EstateSettings.EstateOwner; 321 part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
501 322
502 // And zap any troublesome sit target information 323 // And zap any troublesome sit target information
503 part.SitTargetOrientation = new Quaternion(0, 0, 0, 1); 324 part.SitTargetOrientation = new Quaternion(0, 0, 0, 1);
@@ -510,31 +331,26 @@ namespace OpenSim.Region.CoreModules.World.Archiver
510 TaskInventoryDictionary inv = part.TaskInventory; 331 TaskInventoryDictionary inv = part.TaskInventory;
511 foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv) 332 foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv)
512 { 333 {
513 if (!ResolveUserUuid(scene, kvp.Value.OwnerID)) 334 if (!ResolveUserUuid(kvp.Value.OwnerID))
514 { 335 {
515 kvp.Value.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner; 336 kvp.Value.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
516 } 337 }
517
518 if (kvp.Value.CreatorData == null || kvp.Value.CreatorData == string.Empty) 338 if (kvp.Value.CreatorData == null || kvp.Value.CreatorData == string.Empty)
519 { 339 {
520 if (!ResolveUserUuid(scene, kvp.Value.CreatorID)) 340 if (!ResolveUserUuid(kvp.Value.CreatorID))
521 kvp.Value.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner; 341 kvp.Value.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner;
522 } 342 }
523
524 if (UserManager != null) 343 if (UserManager != null)
525 UserManager.AddUser(kvp.Value.CreatorID, kvp.Value.CreatorData); 344 UserManager.AddUser(kvp.Value.CreatorID, kvp.Value.CreatorData);
526
527 if (!ResolveGroupUuid(kvp.Value.GroupID))
528 kvp.Value.GroupID = UUID.Zero;
529 } 345 }
530 part.TaskInventory.LockItemsForRead(false); 346 part.TaskInventory.LockItemsForRead(false);
531 } 347 }
532 } 348 }
533 349
534 if (scene.AddRestoredSceneObject(sceneObject, true, false)) 350 if (m_scene.AddRestoredSceneObject(sceneObject, true, false))
535 { 351 {
536 sceneObjectsLoadedCount++; 352 sceneObjectsLoadedCount++;
537 sceneObject.CreateScriptInstances(0, false, scene.DefaultScriptEngine, 0); 353 sceneObject.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, 0);
538 sceneObject.ResumeScripts(); 354 sceneObject.ResumeScripts();
539 } 355 }
540 } 356 }
@@ -549,17 +365,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver
549 if (oldTelehubUUID != UUID.Zero) 365 if (oldTelehubUUID != UUID.Zero)
550 { 366 {
551 m_log.WarnFormat("Telehub object not found: {0}", oldTelehubUUID); 367 m_log.WarnFormat("Telehub object not found: {0}", oldTelehubUUID);
552 scene.RegionInfo.RegionSettings.TelehubObject = UUID.Zero; 368 m_scene.RegionInfo.RegionSettings.TelehubObject = UUID.Zero;
553 scene.RegionInfo.RegionSettings.ClearSpawnPoints(); 369 m_scene.RegionInfo.RegionSettings.ClearSpawnPoints();
554 } 370 }
555 } 371 }
556 372
557 /// <summary> 373 /// <summary>
558 /// Load serialized parcels. 374 /// Load serialized parcels.
559 /// </summary> 375 /// </summary>
560 /// <param name="scene"></param>
561 /// <param name="serialisedParcels"></param> 376 /// <param name="serialisedParcels"></param>
562 protected void LoadParcels(Scene scene, List<string> serialisedParcels) 377 protected void LoadParcels(List<string> serialisedParcels)
563 { 378 {
564 // Reload serialized parcels 379 // Reload serialized parcels
565 m_log.InfoFormat("[ARCHIVER]: Loading {0} parcels. Please wait.", serialisedParcels.Count); 380 m_log.InfoFormat("[ARCHIVER]: Loading {0} parcels. Please wait.", serialisedParcels.Count);
@@ -567,27 +382,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
567 foreach (string serialisedParcel in serialisedParcels) 382 foreach (string serialisedParcel in serialisedParcels)
568 { 383 {
569 LandData parcel = LandDataSerializer.Deserialize(serialisedParcel); 384 LandData parcel = LandDataSerializer.Deserialize(serialisedParcel);
385 if (!ResolveUserUuid(parcel.OwnerID))
386 parcel.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
570 387
571 // Validate User and Group UUID's
572
573 if (!ResolveUserUuid(scene, parcel.OwnerID))
574 parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner;
575
576 if (!ResolveGroupUuid(parcel.GroupID))
577 {
578 parcel.GroupID = UUID.Zero;
579 parcel.IsGroupOwned = false;
580 }
581
582 List<LandAccessEntry> accessList = new List<LandAccessEntry>();
583 foreach (LandAccessEntry entry in parcel.ParcelAccessList)
584 {
585 if (ResolveUserUuid(scene, entry.AgentID))
586 accessList.Add(entry);
587 // else, drop this access rule
588 }
589 parcel.ParcelAccessList = accessList;
590
591// m_log.DebugFormat( 388// m_log.DebugFormat(
592// "[ARCHIVER]: Adding parcel {0}, local id {1}, area {2}", 389// "[ARCHIVER]: Adding parcel {0}, local id {1}, area {2}",
593// parcel.Name, parcel.LocalID, parcel.Area); 390// parcel.Name, parcel.LocalID, parcel.Area);
@@ -598,24 +395,23 @@ namespace OpenSim.Region.CoreModules.World.Archiver
598 if (!m_merge) 395 if (!m_merge)
599 { 396 {
600 bool setupDefaultParcel = (landData.Count == 0); 397 bool setupDefaultParcel = (landData.Count == 0);
601 scene.LandChannel.Clear(setupDefaultParcel); 398 m_scene.LandChannel.Clear(setupDefaultParcel);
602 } 399 }
603 400
604 scene.EventManager.TriggerIncomingLandDataFromStorage(landData); 401 m_scene.EventManager.TriggerIncomingLandDataFromStorage(landData);
605 m_log.InfoFormat("[ARCHIVER]: Restored {0} parcels.", landData.Count); 402 m_log.InfoFormat("[ARCHIVER]: Restored {0} parcels.", landData.Count);
606 } 403 }
607 404
608 /// <summary> 405 /// <summary>
609 /// Look up the given user id to check whether it's one that is valid for this grid. 406 /// Look up the given user id to check whether it's one that is valid for this grid.
610 /// </summary> 407 /// </summary>
611 /// <param name="scene"></param>
612 /// <param name="uuid"></param> 408 /// <param name="uuid"></param>
613 /// <returns></returns> 409 /// <returns></returns>
614 private bool ResolveUserUuid(Scene scene, UUID uuid) 410 private bool ResolveUserUuid(UUID uuid)
615 { 411 {
616 if (!m_validUserUuids.ContainsKey(uuid)) 412 if (!m_validUserUuids.ContainsKey(uuid))
617 { 413 {
618 UserAccount account = scene.UserAccountService.GetUserAccount(scene.RegionInfo.ScopeID, uuid); 414 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, uuid);
619 m_validUserUuids.Add(uuid, account != null); 415 m_validUserUuids.Add(uuid, account != null);
620 } 416 }
621 417
@@ -623,30 +419,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver
623 } 419 }
624 420
625 /// <summary> 421 /// <summary>
626 /// Look up the given group id to check whether it's one that is valid for this grid.
627 /// </summary>
628 /// <param name="uuid"></param>
629 /// <returns></returns>
630 private bool ResolveGroupUuid(UUID uuid)
631 {
632 if (uuid == UUID.Zero)
633 return true; // this means the object has no group
634
635 if (!m_validGroupUuids.ContainsKey(uuid))
636 {
637 bool exists;
638
639 if (m_groupsModule == null)
640 exists = false;
641 else
642 exists = (m_groupsModule.GetGroupRecord(uuid) != null);
643
644 m_validGroupUuids.Add(uuid, exists);
645 }
646
647 return m_validGroupUuids[uuid];
648 }
649
650 /// Load an asset 422 /// Load an asset
651 /// </summary> 423 /// </summary>
652 /// <param name="assetFilename"></param> 424 /// <param name="assetFilename"></param>
@@ -670,7 +442,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
670 string extension = filename.Substring(i); 442 string extension = filename.Substring(i);
671 string uuid = filename.Remove(filename.Length - extension.Length); 443 string uuid = filename.Remove(filename.Length - extension.Length);
672 444
673 if (m_assetService.GetMetadata(uuid) != null) 445 if (m_scene.AssetService.GetMetadata(uuid) != null)
674 { 446 {
675 // m_log.DebugFormat("[ARCHIVER]: found existing asset {0}",uuid); 447 // m_log.DebugFormat("[ARCHIVER]: found existing asset {0}",uuid);
676 return true; 448 return true;
@@ -690,7 +462,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
690 462
691 // We're relying on the asset service to do the sensible thing and not store the asset if it already 463 // We're relying on the asset service to do the sensible thing and not store the asset if it already
692 // exists. 464 // exists.
693 m_assetService.Store(asset); 465 m_scene.AssetService.Store(asset);
694 466
695 /** 467 /**
696 * Create layers on decode for image assets. This is likely to significantly increase the time to load archives so 468 * Create layers on decode for image assets. This is likely to significantly increase the time to load archives so
@@ -718,14 +490,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver
718 /// <summary> 490 /// <summary>
719 /// Load region settings data 491 /// Load region settings data
720 /// </summary> 492 /// </summary>
721 /// <param name="scene"></param>
722 /// <param name="settingsPath"></param> 493 /// <param name="settingsPath"></param>
723 /// <param name="data"></param> 494 /// <param name="data"></param>
724 /// <param name="dearchivedScenes"></param>
725 /// <returns> 495 /// <returns>
726 /// true if settings were loaded successfully, false otherwise 496 /// true if settings were loaded successfully, false otherwise
727 /// </returns> 497 /// </returns>
728 private bool LoadRegionSettings(Scene scene, string settingsPath, byte[] data, DearchiveScenesInfo dearchivedScenes) 498 private bool LoadRegionSettings(string settingsPath, byte[] data)
729 { 499 {
730 RegionSettings loadedRegionSettings; 500 RegionSettings loadedRegionSettings;
731 501
@@ -741,7 +511,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
741 return false; 511 return false;
742 } 512 }
743 513
744 RegionSettings currentRegionSettings = scene.RegionInfo.RegionSettings; 514 RegionSettings currentRegionSettings = m_scene.RegionInfo.RegionSettings;
745 515
746 currentRegionSettings.AgentLimit = loadedRegionSettings.AgentLimit; 516 currentRegionSettings.AgentLimit = loadedRegionSettings.AgentLimit;
747 currentRegionSettings.AllowDamage = loadedRegionSettings.AllowDamage; 517 currentRegionSettings.AllowDamage = loadedRegionSettings.AllowDamage;
@@ -778,14 +548,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver
778 foreach (SpawnPoint sp in loadedRegionSettings.SpawnPoints()) 548 foreach (SpawnPoint sp in loadedRegionSettings.SpawnPoints())
779 currentRegionSettings.AddSpawnPoint(sp); 549 currentRegionSettings.AddSpawnPoint(sp);
780 550
781 currentRegionSettings.LoadedCreationDateTime = dearchivedScenes.LoadedCreationDateTime;
782 currentRegionSettings.LoadedCreationID = dearchivedScenes.GetOriginalRegionID(scene.RegionInfo.RegionID).ToString();
783
784 currentRegionSettings.Save(); 551 currentRegionSettings.Save();
785 552
786 scene.TriggerEstateSunUpdate(); 553 m_scene.TriggerEstateSunUpdate();
787 554
788 IEstateModule estateModule = scene.RequestModuleInterface<IEstateModule>(); 555 IEstateModule estateModule = m_scene.RequestModuleInterface<IEstateModule>();
556
789 if (estateModule != null) 557 if (estateModule != null)
790 estateModule.sendRegionHandshakeToAll(); 558 estateModule.sendRegionHandshakeToAll();
791 559
@@ -795,15 +563,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver
795 /// <summary> 563 /// <summary>
796 /// Load terrain data 564 /// Load terrain data
797 /// </summary> 565 /// </summary>
798 /// <param name="scene"></param>
799 /// <param name="terrainPath"></param> 566 /// <param name="terrainPath"></param>
800 /// <param name="data"></param> 567 /// <param name="data"></param>
801 /// <returns> 568 /// <returns>
802 /// true if terrain was resolved successfully, false otherwise. 569 /// true if terrain was resolved successfully, false otherwise.
803 /// </returns> 570 /// </returns>
804 private bool LoadTerrain(Scene scene, string terrainPath, byte[] data) 571 private bool LoadTerrain(string terrainPath, byte[] data)
805 { 572 {
806 ITerrainModule terrainModule = scene.RequestModuleInterface<ITerrainModule>(); 573 ITerrainModule terrainModule = m_scene.RequestModuleInterface<ITerrainModule>();
807 574
808 MemoryStream ms = new MemoryStream(data); 575 MemoryStream ms = new MemoryStream(data);
809 terrainModule.LoadFromStream(terrainPath, ms); 576 terrainModule.LoadFromStream(terrainPath, ms);
@@ -819,18 +586,17 @@ namespace OpenSim.Region.CoreModules.World.Archiver
819 /// </summary> 586 /// </summary>
820 /// <param name="path"></param> 587 /// <param name="path"></param>
821 /// <param name="data"></param> 588 /// <param name="data"></param>
822 /// <param name="dearchivedScenes"></param> 589 public void LoadControlFile(string path, byte[] data)
823 public DearchiveScenesInfo LoadControlFile(string path, byte[] data, DearchiveScenesInfo dearchivedScenes)
824 { 590 {
825 XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable()); 591 XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable());
826 XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None); 592 XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None);
827 XmlTextReader xtr = new XmlTextReader(Encoding.ASCII.GetString(data), XmlNodeType.Document, context); 593 XmlTextReader xtr = new XmlTextReader(Encoding.ASCII.GetString(data), XmlNodeType.Document, context);
828 594
829 // Loaded metadata will be empty if no information exists in the archive 595 RegionSettings currentRegionSettings = m_scene.RegionInfo.RegionSettings;
830 dearchivedScenes.LoadedCreationDateTime = 0;
831 dearchivedScenes.DefaultOriginalID = "";
832 596
833 bool multiRegion = false; 597 // Loaded metadata will empty if no information exists in the archive
598 currentRegionSettings.LoadedCreationDateTime = 0;
599 currentRegionSettings.LoadedCreationID = "";
834 600
835 while (xtr.Read()) 601 while (xtr.Read())
836 { 602 {
@@ -856,44 +622,18 @@ namespace OpenSim.Region.CoreModules.World.Archiver
856 { 622 {
857 int value; 623 int value;
858 if (Int32.TryParse(xtr.ReadElementContentAsString(), out value)) 624 if (Int32.TryParse(xtr.ReadElementContentAsString(), out value))
859 dearchivedScenes.LoadedCreationDateTime = value; 625 currentRegionSettings.LoadedCreationDateTime = value;
860 } 626 }
861 else if (xtr.Name.ToString() == "row") 627 else if (xtr.Name.ToString() == "id")
862 {
863 multiRegion = true;
864 dearchivedScenes.StartRow();
865 }
866 else if (xtr.Name.ToString() == "region")
867 {
868 dearchivedScenes.StartRegion();
869 }
870 else if (xtr.Name.ToString() == "id")
871 {
872 string id = xtr.ReadElementContentAsString();
873 dearchivedScenes.DefaultOriginalID = id;
874 if (multiRegion)
875 dearchivedScenes.SetRegionOriginalID(id);
876 }
877 else if (xtr.Name.ToString() == "dir")
878 { 628 {
879 dearchivedScenes.SetRegionDirectory(xtr.ReadElementContentAsString()); 629 currentRegionSettings.LoadedCreationID = xtr.ReadElementContentAsString();
880 } 630 }
881 } 631 }
882 } 632 }
883 633
884 dearchivedScenes.MultiRegionFormat = multiRegion; 634 currentRegionSettings.Save();
885 if (!multiRegion) 635
886 {
887 // Add the single scene
888 dearchivedScenes.StartRow();
889 dearchivedScenes.StartRegion();
890 dearchivedScenes.SetRegionOriginalID(dearchivedScenes.DefaultOriginalID);
891 dearchivedScenes.SetRegionDirectory("");
892 }
893
894 ControlFileLoaded = true; 636 ControlFileLoaded = true;
895
896 return dearchivedScenes;
897 } 637 }
898 } 638 }
899} 639} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs
deleted file mode 100644
index d8dace2..0000000
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs
+++ /dev/null
@@ -1,176 +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.Linq;
31using System.Text;
32using OpenSim.Region.Framework.Scenes;
33using OpenMetaverse;
34using System.Drawing;
35
36namespace OpenSim.Region.CoreModules.World.Archiver
37{
38 /// <summary>
39 /// A group of regions arranged in a rectangle, possibly with holes.
40 /// </summary>
41 /// <remarks>
42 /// The regions usually (but not necessarily) belong to an archive file, in which case we
43 /// store additional information used to create the archive (e.g., each region's
44 /// directory within the archive).
45 /// </remarks>
46 public class ArchiveScenesGroup
47 {
48 /// <summary>
49 /// All the regions. The outer dictionary contains rows (key: Y coordinate).
50 /// The inner dictionaries contain each row's regions (key: X coordinate).
51 /// </summary>
52 public SortedDictionary<uint, SortedDictionary<uint, Scene>> Regions { get; set; }
53
54 /// <summary>
55 /// The subdirectory where each region is stored in the archive.
56 /// </summary>
57 protected Dictionary<UUID, string> m_regionDirs;
58
59 /// <summary>
60 /// The grid coordinates of the regions' bounding box.
61 /// </summary>
62 public Rectangle Rect { get; set; }
63
64
65 public ArchiveScenesGroup()
66 {
67 Regions = new SortedDictionary<uint, SortedDictionary<uint, Scene>>();
68 m_regionDirs = new Dictionary<UUID, string>();
69 Rect = new Rectangle(0, 0, 0, 0);
70 }
71
72 public void AddScene(Scene scene)
73 {
74 uint x = scene.RegionInfo.RegionLocX;
75 uint y = scene.RegionInfo.RegionLocY;
76
77 SortedDictionary<uint, Scene> row;
78 if (!Regions.TryGetValue(y, out row))
79 {
80 row = new SortedDictionary<uint, Scene>();
81 Regions[y] = row;
82 }
83
84 row[x] = scene;
85 }
86
87 /// <summary>
88 /// Called after all the scenes have been added. Performs calculations that require
89 /// knowledge of all the scenes.
90 /// </summary>
91 public void CalcSceneLocations()
92 {
93 if (Regions.Count == 0)
94 return;
95
96 // Find the bounding rectangle
97
98 uint firstY = Regions.First().Key;
99 uint lastY = Regions.Last().Key;
100
101 uint? firstX = null;
102 uint? lastX = null;
103
104 foreach (SortedDictionary<uint, Scene> row in Regions.Values)
105 {
106 uint curFirstX = row.First().Key;
107 uint curLastX = row.Last().Key;
108
109 firstX = (firstX == null) ? curFirstX : (firstX < curFirstX) ? firstX : curFirstX;
110 lastX = (lastX == null) ? curLastX : (lastX > curLastX) ? lastX : curLastX;
111 }
112
113 Rect = new Rectangle((int)firstX, (int)firstY, (int)(lastX - firstX + 1), (int)(lastY - firstY + 1));
114
115
116 // Calculate the subdirectory in which each region will be stored in the archive
117
118 m_regionDirs.Clear();
119 ForEachScene(delegate(Scene scene)
120 {
121 // We add the region's coordinates to ensure uniqueness even if multiple regions have the same name
122 string path = string.Format("{0}_{1}_{2}",
123 scene.RegionInfo.RegionLocX - Rect.X + 1,
124 scene.RegionInfo.RegionLocY - Rect.Y + 1,
125 scene.RegionInfo.RegionName.Replace(' ', '_'));
126 m_regionDirs[scene.RegionInfo.RegionID] = path;
127 });
128 }
129
130 /// <summary>
131 /// Returns the subdirectory where the region is stored.
132 /// </summary>
133 /// <param name="regionID"></param>
134 /// <returns></returns>
135 public string GetRegionDir(UUID regionID)
136 {
137 return m_regionDirs[regionID];
138 }
139
140 /// <summary>
141 /// Performs an action on all the scenes in this order: rows from South to North,
142 /// and within each row West to East.
143 /// </summary>
144 /// <param name="action"></param>
145 public void ForEachScene(Action<Scene> action)
146 {
147 foreach (SortedDictionary<uint, Scene> row in Regions.Values)
148 {
149 foreach (Scene scene in row.Values)
150 {
151 action(scene);
152 }
153 }
154 }
155
156 /// <summary>
157 /// Returns the scene at position 'location'.
158 /// </summary>
159 /// <param name="location">A location in the grid</param>
160 /// <param name="scene">The scene at this location</param>
161 /// <returns>Whether the scene was found</returns>
162 public bool TryGetScene(Point location, out Scene scene)
163 {
164 SortedDictionary<uint, Scene> row;
165 if (Regions.TryGetValue((uint)location.Y, out row))
166 {
167 if (row.TryGetValue((uint)location.X, out scene))
168 return true;
169 }
170
171 scene = null;
172 return false;
173 }
174
175 }
176}
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
deleted file mode 100644
index d751b1c..0000000
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
+++ /dev/null
@@ -1,634 +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.IO.Compression;
32using System.Reflection;
33using System.Text.RegularExpressions;
34using System.Threading;
35using System.Xml;
36using log4net;
37using OpenMetaverse;
38using OpenSim.Framework;
39using OpenSim.Framework.Serialization;
40using OpenSim.Region.CoreModules.World.Terrain;
41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes;
43using Ionic.Zlib;
44using GZipStream = Ionic.Zlib.GZipStream;
45using CompressionMode = Ionic.Zlib.CompressionMode;
46using OpenSim.Framework.Serialization.External;
47
48namespace OpenSim.Region.CoreModules.World.Archiver
49{
50 /// <summary>
51 /// Prepare to write out an archive.
52 /// </summary>
53 public class ArchiveWriteRequest
54 {
55 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
56
57 /// <summary>
58 /// The minimum major version of OAR that we can write.
59 /// </summary>
60 public static int MIN_MAJOR_VERSION = 0;
61
62 /// <summary>
63 /// The maximum major version of OAR that we can write.
64 /// </summary>
65 public static int MAX_MAJOR_VERSION = 1;
66
67 /// <summary>
68 /// Whether we're saving a multi-region archive.
69 /// </summary>
70 public bool MultiRegionFormat { get; set; }
71
72 /// <summary>
73 /// Determine whether this archive will save assets. Default is true.
74 /// </summary>
75 public bool SaveAssets { get; set; }
76
77 /// <summary>
78 /// Determines which objects will be included in the archive, according to their permissions.
79 /// Default is null, meaning no permission checks.
80 /// </summary>
81 public string CheckPermissions { get; set; }
82
83 protected Scene m_rootScene;
84 protected Stream m_saveStream;
85 protected TarArchiveWriter m_archiveWriter;
86 protected Guid m_requestId;
87 protected Dictionary<string, object> m_options;
88
89 /// <summary>
90 /// Constructor
91 /// </summary>
92 /// <param name="module">Calling module</param>
93 /// <param name="savePath">The path to which to save data.</param>
94 /// <param name="requestId">The id associated with this request</param>
95 /// <exception cref="System.IO.IOException">
96 /// If there was a problem opening a stream for the file specified by the savePath
97 /// </exception>
98 public ArchiveWriteRequest(Scene scene, string savePath, Guid requestId) : this(scene, requestId)
99 {
100 try
101 {
102 m_saveStream = new GZipStream(new FileStream(savePath, FileMode.Create), CompressionMode.Compress, CompressionLevel.BestCompression);
103 }
104 catch (EntryPointNotFoundException e)
105 {
106 m_log.ErrorFormat(
107 "[ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream."
108 + "If you've manually installed Mono, have you appropriately updated zlib1g as well?");
109 m_log.ErrorFormat("{0} {1}", e.Message, e.StackTrace);
110 }
111 }
112
113 /// <summary>
114 /// Constructor.
115 /// </summary>
116 /// <param name="scene">The root scene to archive</param>
117 /// <param name="saveStream">The stream to which to save data.</param>
118 /// <param name="requestId">The id associated with this request</param>
119 public ArchiveWriteRequest(Scene scene, Stream saveStream, Guid requestId) : this(scene, requestId)
120 {
121 m_saveStream = saveStream;
122 }
123
124 protected ArchiveWriteRequest(Scene scene, Guid requestId)
125 {
126 m_rootScene = scene;
127 m_requestId = requestId;
128 m_archiveWriter = null;
129
130 MultiRegionFormat = false;
131 SaveAssets = true;
132 CheckPermissions = null;
133 }
134
135 /// <summary>
136 /// Archive the region requested.
137 /// </summary>
138 /// <exception cref="System.IO.IOException">if there was an io problem with creating the file</exception>
139 public void ArchiveRegion(Dictionary<string, object> options)
140 {
141 m_options = options;
142
143 if (options.ContainsKey("all") && (bool)options["all"])
144 MultiRegionFormat = true;
145
146 if (options.ContainsKey("noassets") && (bool)options["noassets"])
147 SaveAssets = false;
148
149 Object temp;
150 if (options.TryGetValue("checkPermissions", out temp))
151 CheckPermissions = (string)temp;
152
153
154 // Find the regions to archive
155 ArchiveScenesGroup scenesGroup = new ArchiveScenesGroup();
156 if (MultiRegionFormat)
157 {
158 m_log.InfoFormat("[ARCHIVER]: Saving {0} regions", SceneManager.Instance.Scenes.Count);
159 SceneManager.Instance.ForEachScene(delegate(Scene scene)
160 {
161 scenesGroup.AddScene(scene);
162 });
163 }
164 else
165 {
166 scenesGroup.AddScene(m_rootScene);
167 }
168 scenesGroup.CalcSceneLocations();
169
170
171 m_archiveWriter = new TarArchiveWriter(m_saveStream);
172
173 try
174 {
175 // Write out control file. It should be first so that it will be found ASAP when loading the file.
176 m_archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, CreateControlFile(scenesGroup));
177 m_log.InfoFormat("[ARCHIVER]: Added control file to archive.");
178
179 // Archive the regions
180
181 Dictionary<UUID, AssetType> assetUuids = new Dictionary<UUID, AssetType>();
182
183 scenesGroup.ForEachScene(delegate(Scene scene)
184 {
185 string regionDir = MultiRegionFormat ? scenesGroup.GetRegionDir(scene.RegionInfo.RegionID) : "";
186 ArchiveOneRegion(scene, regionDir, assetUuids);
187 });
188
189 // Archive the assets
190
191 if (SaveAssets)
192 {
193 m_log.DebugFormat("[ARCHIVER]: Saving {0} assets", assetUuids.Count);
194
195 // Asynchronously request all the assets required to perform this archive operation
196 AssetsRequest ar
197 = new AssetsRequest(
198 new AssetsArchiver(m_archiveWriter), assetUuids,
199 m_rootScene.AssetService, m_rootScene.UserAccountService,
200 m_rootScene.RegionInfo.ScopeID, options, ReceivedAllAssets);
201
202 Util.FireAndForget(o => ar.Execute());
203
204 // CloseArchive() will be called from ReceivedAllAssets()
205 }
206 else
207 {
208 m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified");
209 CloseArchive(string.Empty);
210 }
211 }
212 catch (Exception e)
213 {
214 CloseArchive(e.Message);
215 throw;
216 }
217 }
218
219
220 private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary<UUID, AssetType> assetUuids)
221 {
222 m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.RegionInfo.RegionName);
223
224 EntityBase[] entities = scene.GetEntities();
225 List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>();
226
227 int numObjectsSkippedPermissions = 0;
228
229 // Filter entities so that we only have scene objects.
230 // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods
231 // end up having to do this
232 IPermissionsModule permissionsModule = scene.RequestModuleInterface<IPermissionsModule>();
233 foreach (EntityBase entity in entities)
234 {
235 if (entity is SceneObjectGroup)
236 {
237 SceneObjectGroup sceneObject = (SceneObjectGroup)entity;
238
239 if (!sceneObject.IsDeleted && !sceneObject.IsAttachment)
240 {
241 if (!CanUserArchiveObject(scene.RegionInfo.EstateSettings.EstateOwner, sceneObject, CheckPermissions, permissionsModule))
242 {
243 // The user isn't allowed to copy/transfer this object, so it will not be included in the OAR.
244 ++numObjectsSkippedPermissions;
245 }
246 else
247 {
248 sceneObjects.Add(sceneObject);
249 }
250 }
251 }
252 }
253
254 if (SaveAssets)
255 {
256 UuidGatherer assetGatherer = new UuidGatherer(scene.AssetService);
257 int prevAssets = assetUuids.Count;
258
259 foreach (SceneObjectGroup sceneObject in sceneObjects)
260 {
261 assetGatherer.GatherAssetUuids(sceneObject, assetUuids);
262 }
263
264 m_log.DebugFormat(
265 "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets",
266 sceneObjects.Count, assetUuids.Count - prevAssets);
267 }
268
269 if (numObjectsSkippedPermissions > 0)
270 {
271 m_log.DebugFormat(
272 "[ARCHIVER]: {0} scene objects skipped due to lack of permissions",
273 numObjectsSkippedPermissions);
274 }
275
276 // Make sure that we also request terrain texture assets
277 RegionSettings regionSettings = scene.RegionInfo.RegionSettings;
278
279 if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1)
280 assetUuids[regionSettings.TerrainTexture1] = AssetType.Texture;
281
282 if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2)
283 assetUuids[regionSettings.TerrainTexture2] = AssetType.Texture;
284
285 if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3)
286 assetUuids[regionSettings.TerrainTexture3] = AssetType.Texture;
287
288 if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4)
289 assetUuids[regionSettings.TerrainTexture4] = AssetType.Texture;
290
291 Save(scene, sceneObjects, regionDir);
292 }
293
294 /// <summary>
295 /// Checks whether the user has permission to export an object group to an OAR.
296 /// </summary>
297 /// <param name="user">The user</param>
298 /// <param name="objGroup">The object group</param>
299 /// <param name="checkPermissions">Which permissions to check: "C" = Copy, "T" = Transfer</param>
300 /// <param name="permissionsModule">The scene's permissions module</param>
301 /// <returns>Whether the user is allowed to export the object to an OAR</returns>
302 private bool CanUserArchiveObject(UUID user, SceneObjectGroup objGroup, string checkPermissions, IPermissionsModule permissionsModule)
303 {
304 if (checkPermissions == null)
305 return true;
306
307 if (permissionsModule == null)
308 return true; // this shouldn't happen
309
310 // Check whether the user is permitted to export all of the parts in the SOG. If any
311 // part can't be exported then the entire SOG can't be exported.
312
313 bool permitted = true;
314 //int primNumber = 1;
315
316 foreach (SceneObjectPart obj in objGroup.Parts)
317 {
318 uint perm;
319 PermissionClass permissionClass = permissionsModule.GetPermissionClass(user, obj);
320 switch (permissionClass)
321 {
322 case PermissionClass.Owner:
323 perm = obj.BaseMask;
324 break;
325 case PermissionClass.Group:
326 perm = obj.GroupMask | obj.EveryoneMask;
327 break;
328 case PermissionClass.Everyone:
329 default:
330 perm = obj.EveryoneMask;
331 break;
332 }
333
334 bool canCopy = (perm & (uint)PermissionMask.Copy) != 0;
335 bool canTransfer = (perm & (uint)PermissionMask.Transfer) != 0;
336
337 // Special case: if Everyone can copy the object then this implies it can also be
338 // Transferred.
339 // However, if the user is the Owner then we don't check EveryoneMask, because it seems that the mask
340 // always (incorrectly) includes the Copy bit set in this case. But that's a mistake: the viewer
341 // does NOT show that the object has Everyone-Copy permissions, and doesn't allow it to be copied.
342 if (permissionClass != PermissionClass.Owner)
343 canTransfer |= (obj.EveryoneMask & (uint)PermissionMask.Copy) != 0;
344
345 bool partPermitted = true;
346 if (checkPermissions.Contains("C") && !canCopy)
347 partPermitted = false;
348 if (checkPermissions.Contains("T") && !canTransfer)
349 partPermitted = false;
350
351 // If the user is the Creator of the object then it can always be included in the OAR
352 bool creator = (obj.CreatorID.Guid == user.Guid);
353 if (creator)
354 partPermitted = true;
355
356 //string name = (objGroup.PrimCount == 1) ? objGroup.Name : string.Format("{0} ({1}/{2})", obj.Name, primNumber, objGroup.PrimCount);
357 //m_log.DebugFormat("[ARCHIVER]: Object permissions: {0}: Base={1:X4}, Owner={2:X4}, Everyone={3:X4}, permissionClass={4}, checkPermissions={5}, canCopy={6}, canTransfer={7}, creator={8}, permitted={9}",
358 // name, obj.BaseMask, obj.OwnerMask, obj.EveryoneMask,
359 // permissionClass, checkPermissions, canCopy, canTransfer, creator, partPermitted);
360
361 if (!partPermitted)
362 {
363 permitted = false;
364 break;
365 }
366
367 //++primNumber;
368 }
369
370 return permitted;
371 }
372
373 /// <summary>
374 /// Create the control file.
375 /// </summary>
376 /// <returns></returns>
377 public string CreateControlFile(ArchiveScenesGroup scenesGroup)
378 {
379 int majorVersion;
380 int minorVersion;
381
382 if (MultiRegionFormat)
383 {
384 majorVersion = MAX_MAJOR_VERSION;
385 minorVersion = 0;
386 }
387 else
388 {
389 // To support older versions of OpenSim, we continue to create single-region OARs
390 // using the old file format. In the future this format will be discontinued.
391 majorVersion = 0;
392 minorVersion = 8;
393 }
394//
395// if (m_options.ContainsKey("version"))
396// {
397// string[] parts = m_options["version"].ToString().Split('.');
398// if (parts.Length >= 1)
399// {
400// majorVersion = Int32.Parse(parts[0]);
401//
402// if (parts.Length >= 2)
403// minorVersion = Int32.Parse(parts[1]);
404// }
405// }
406//
407// if (majorVersion < MIN_MAJOR_VERSION || majorVersion > MAX_MAJOR_VERSION)
408// {
409// throw new Exception(
410// string.Format(
411// "OAR version number for save must be between {0} and {1}",
412// MIN_MAJOR_VERSION, MAX_MAJOR_VERSION));
413// }
414// else if (majorVersion == MAX_MAJOR_VERSION)
415// {
416// // Force 1.0
417// minorVersion = 0;
418// }
419// else if (majorVersion == MIN_MAJOR_VERSION)
420// {
421// // Force 0.4
422// minorVersion = 4;
423// }
424
425 m_log.InfoFormat("[ARCHIVER]: Creating version {0}.{1} OAR", majorVersion, minorVersion);
426 if (majorVersion == 1)
427 {
428 m_log.WarnFormat("[ARCHIVER]: Please be aware that version 1.0 OARs are not compatible with OpenSim versions prior to 0.7.4. Do not use the --all option if you want to produce a compatible OAR");
429 }
430
431 String s;
432
433 using (StringWriter sw = new StringWriter())
434 {
435 using (XmlTextWriter xtw = new XmlTextWriter(sw))
436 {
437 xtw.Formatting = Formatting.Indented;
438 xtw.WriteStartDocument();
439 xtw.WriteStartElement("archive");
440 xtw.WriteAttributeString("major_version", majorVersion.ToString());
441 xtw.WriteAttributeString("minor_version", minorVersion.ToString());
442
443 xtw.WriteStartElement("creation_info");
444 DateTime now = DateTime.UtcNow;
445 TimeSpan t = now - new DateTime(1970, 1, 1);
446 xtw.WriteElementString("datetime", ((int)t.TotalSeconds).ToString());
447 if (!MultiRegionFormat)
448 xtw.WriteElementString("id", m_rootScene.RegionInfo.RegionID.ToString());
449 xtw.WriteEndElement();
450
451 xtw.WriteElementString("assets_included", SaveAssets.ToString());
452
453 if (MultiRegionFormat)
454 {
455 WriteRegionsManifest(scenesGroup, xtw);
456 }
457 else
458 {
459 xtw.WriteStartElement("region_info");
460 WriteRegionInfo(m_rootScene, xtw);
461 xtw.WriteEndElement();
462 }
463
464 xtw.WriteEndElement();
465
466 xtw.Flush();
467 }
468
469 s = sw.ToString();
470 }
471
472 return s;
473 }
474
475 /// <summary>
476 /// Writes the list of regions included in a multi-region OAR.
477 /// </summary>
478 private static void WriteRegionsManifest(ArchiveScenesGroup scenesGroup, XmlTextWriter xtw)
479 {
480 xtw.WriteStartElement("regions");
481
482 // Write the regions in order: rows from South to North, then regions from West to East.
483 // The list of regions can have "holes"; we write empty elements in their position.
484
485 for (uint y = (uint)scenesGroup.Rect.Top; y < scenesGroup.Rect.Bottom; ++y)
486 {
487 SortedDictionary<uint, Scene> row;
488 if (scenesGroup.Regions.TryGetValue(y, out row))
489 {
490 xtw.WriteStartElement("row");
491
492 for (uint x = (uint)scenesGroup.Rect.Left; x < scenesGroup.Rect.Right; ++x)
493 {
494 Scene scene;
495 if (row.TryGetValue(x, out scene))
496 {
497 xtw.WriteStartElement("region");
498 xtw.WriteElementString("id", scene.RegionInfo.RegionID.ToString());
499 xtw.WriteElementString("dir", scenesGroup.GetRegionDir(scene.RegionInfo.RegionID));
500 WriteRegionInfo(scene, xtw);
501 xtw.WriteEndElement();
502 }
503 else
504 {
505 // Write a placeholder for a missing region
506 xtw.WriteElementString("region", "");
507 }
508 }
509
510 xtw.WriteEndElement();
511 }
512 else
513 {
514 // Write a placeholder for a missing row
515 xtw.WriteElementString("row", "");
516 }
517 }
518
519 xtw.WriteEndElement(); // "regions"
520 }
521
522 protected static void WriteRegionInfo(Scene scene, XmlTextWriter xtw)
523 {
524 bool isMegaregion;
525 Vector2 size;
526
527 IRegionCombinerModule rcMod = scene.RequestModuleInterface<IRegionCombinerModule>();
528
529 if (rcMod != null)
530 isMegaregion = rcMod.IsRootForMegaregion(scene.RegionInfo.RegionID);
531 else
532 isMegaregion = false;
533
534 if (isMegaregion)
535 size = rcMod.GetSizeOfMegaregion(scene.RegionInfo.RegionID);
536 else
537 size = new Vector2((float)Constants.RegionSize, (float)Constants.RegionSize);
538
539 xtw.WriteElementString("is_megaregion", isMegaregion.ToString());
540 xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y));
541 }
542
543
544 protected void Save(Scene scene, List<SceneObjectGroup> sceneObjects, string regionDir)
545 {
546 if (regionDir != string.Empty)
547 regionDir = ArchiveConstants.REGIONS_PATH + regionDir + "/";
548
549 m_log.InfoFormat("[ARCHIVER]: Adding region settings to archive.");
550
551 // Write out region settings
552 string settingsPath = String.Format("{0}{1}{2}.xml",
553 regionDir, ArchiveConstants.SETTINGS_PATH, scene.RegionInfo.RegionName);
554 m_archiveWriter.WriteFile(settingsPath, RegionSettingsSerializer.Serialize(scene.RegionInfo.RegionSettings));
555
556 m_log.InfoFormat("[ARCHIVER]: Adding parcel settings to archive.");
557
558 // Write out land data (aka parcel) settings
559 List<ILandObject> landObjects = scene.LandChannel.AllParcels();
560 foreach (ILandObject lo in landObjects)
561 {
562 LandData landData = lo.LandData;
563 string landDataPath = String.Format("{0}{1}{2}.xml",
564 regionDir, ArchiveConstants.LANDDATA_PATH, landData.GlobalID.ToString());
565 m_archiveWriter.WriteFile(landDataPath, LandDataSerializer.Serialize(landData, m_options));
566 }
567
568 m_log.InfoFormat("[ARCHIVER]: Adding terrain information to archive.");
569
570 // Write out terrain
571 string terrainPath = String.Format("{0}{1}{2}.r32",
572 regionDir, ArchiveConstants.TERRAINS_PATH, scene.RegionInfo.RegionName);
573
574 MemoryStream ms = new MemoryStream();
575 scene.RequestModuleInterface<ITerrainModule>().SaveToStream(terrainPath, ms);
576 m_archiveWriter.WriteFile(terrainPath, ms.ToArray());
577 ms.Close();
578
579 m_log.InfoFormat("[ARCHIVER]: Adding scene objects to archive.");
580
581 // Write out scene object metadata
582 IRegionSerialiserModule serializer = scene.RequestModuleInterface<IRegionSerialiserModule>();
583 foreach (SceneObjectGroup sceneObject in sceneObjects)
584 {
585 //m_log.DebugFormat("[ARCHIVER]: Saving {0} {1}, {2}", entity.Name, entity.UUID, entity.GetType());
586
587 string serializedObject = serializer.SerializeGroupToXml2(sceneObject, m_options);
588 string objectPath = string.Format("{0}{1}", regionDir, ArchiveHelpers.CreateObjectPath(sceneObject));
589 m_archiveWriter.WriteFile(objectPath, serializedObject);
590 }
591 }
592
593 protected void ReceivedAllAssets(
594 ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids)
595 {
596 foreach (UUID uuid in assetsNotFoundUuids)
597 {
598 m_log.DebugFormat("[ARCHIVER]: Could not find asset {0}", uuid);
599 }
600
601 // m_log.InfoFormat(
602 // "[ARCHIVER]: Received {0} of {1} assets requested",
603 // assetsFoundUuids.Count, assetsFoundUuids.Count + assetsNotFoundUuids.Count);
604
605 CloseArchive(String.Empty);
606 }
607
608
609 /// <summary>
610 /// Closes the archive and notifies that we're done.
611 /// </summary>
612 /// <param name="errorMessage">The error that occurred, or empty for success</param>
613 protected void CloseArchive(string errorMessage)
614 {
615 try
616 {
617 if (m_archiveWriter != null)
618 m_archiveWriter.Close();
619 m_saveStream.Close();
620 }
621 catch (Exception e)
622 {
623 m_log.Error(string.Format("[ARCHIVER]: Error closing archive: {0} ", e.Message), e);
624 if (errorMessage == string.Empty)
625 errorMessage = e.Message;
626 }
627
628 m_log.InfoFormat("[ARCHIVER]: Finished writing out OAR for {0}", m_rootScene.RegionInfo.RegionName);
629
630 m_rootScene.EventManager.TriggerOarFileSaved(m_requestId, errorMessage);
631 }
632
633 }
634}
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs
new file mode 100644
index 0000000..0780d86
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs
@@ -0,0 +1,153 @@
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.Reflection;
32using System.Xml;
33using log4net;
34using OpenMetaverse;
35using OpenSim.Framework;
36using OpenSim.Framework.Serialization;
37using OpenSim.Framework.Serialization.External;
38using OpenSim.Region.CoreModules.World.Terrain;
39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Region.Framework.Scenes;
41
42namespace OpenSim.Region.CoreModules.World.Archiver
43{
44 /// <summary>
45 /// Method called when all the necessary assets for an archive request have been received.
46 /// </summary>
47 public delegate void AssetsRequestCallback(
48 ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids);
49
50 /// <summary>
51 /// Execute the write of an archive once we have received all the necessary data
52 /// </summary>
53 public class ArchiveWriteRequestExecution
54 {
55 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
56
57 protected ITerrainModule m_terrainModule;
58 protected IRegionSerialiserModule m_serialiser;
59 protected List<SceneObjectGroup> m_sceneObjects;
60 protected Scene m_scene;
61 protected TarArchiveWriter m_archiveWriter;
62 protected Guid m_requestId;
63 protected Dictionary<string, object> m_options;
64
65 public ArchiveWriteRequestExecution(
66 List<SceneObjectGroup> sceneObjects,
67 ITerrainModule terrainModule,
68 IRegionSerialiserModule serialiser,
69 Scene scene,
70 TarArchiveWriter archiveWriter,
71 Guid requestId,
72 Dictionary<string, object> options)
73 {
74 m_sceneObjects = sceneObjects;
75 m_terrainModule = terrainModule;
76 m_serialiser = serialiser;
77 m_scene = scene;
78 m_archiveWriter = archiveWriter;
79 m_requestId = requestId;
80 m_options = options;
81 }
82
83 protected internal void ReceivedAllAssets(
84 ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids)
85 {
86 try
87 {
88 Save(assetsFoundUuids, assetsNotFoundUuids);
89 }
90 finally
91 {
92 m_archiveWriter.Close();
93 }
94
95 m_log.InfoFormat("[ARCHIVER]: Finished writing out OAR for {0}", m_scene.RegionInfo.RegionName);
96
97 m_scene.EventManager.TriggerOarFileSaved(m_requestId, String.Empty);
98 }
99
100 protected internal void Save(ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids)
101 {
102 foreach (UUID uuid in assetsNotFoundUuids)
103 {
104 m_log.DebugFormat("[ARCHIVER]: Could not find asset {0}", uuid);
105 }
106
107// m_log.InfoFormat(
108// "[ARCHIVER]: Received {0} of {1} assets requested",
109// assetsFoundUuids.Count, assetsFoundUuids.Count + assetsNotFoundUuids.Count);
110
111 m_log.InfoFormat("[ARCHIVER]: Adding region settings to archive.");
112
113 // Write out region settings
114 string settingsPath
115 = String.Format("{0}{1}.xml", ArchiveConstants.SETTINGS_PATH, m_scene.RegionInfo.RegionName);
116 m_archiveWriter.WriteFile(settingsPath, RegionSettingsSerializer.Serialize(m_scene.RegionInfo.RegionSettings));
117
118 m_log.InfoFormat("[ARCHIVER]: Adding parcel settings to archive.");
119
120 // Write out land data (aka parcel) settings
121 List<ILandObject>landObjects = m_scene.LandChannel.AllParcels();
122 foreach (ILandObject lo in landObjects)
123 {
124 LandData landData = lo.LandData;
125 string landDataPath = String.Format("{0}{1}.xml", ArchiveConstants.LANDDATA_PATH,
126 landData.GlobalID.ToString());
127 m_archiveWriter.WriteFile(landDataPath, LandDataSerializer.Serialize(landData, m_options));
128 }
129
130 m_log.InfoFormat("[ARCHIVER]: Adding terrain information to archive.");
131
132 // Write out terrain
133 string terrainPath
134 = String.Format("{0}{1}.r32", ArchiveConstants.TERRAINS_PATH, m_scene.RegionInfo.RegionName);
135
136 MemoryStream ms = new MemoryStream();
137 m_terrainModule.SaveToStream(terrainPath, ms);
138 m_archiveWriter.WriteFile(terrainPath, ms.ToArray());
139 ms.Close();
140
141 m_log.InfoFormat("[ARCHIVER]: Adding scene objects to archive.");
142
143 // Write out scene object metadata
144 foreach (SceneObjectGroup sceneObject in m_sceneObjects)
145 {
146 //m_log.DebugFormat("[ARCHIVER]: Saving {0} {1}, {2}", entity.Name, entity.UUID, entity.GetType());
147
148 string serializedObject = m_serialiser.SerializeGroupToXml2(sceneObject, m_options);
149 m_archiveWriter.WriteFile(ArchiveHelpers.CreateObjectPath(sceneObject), serializedObject);
150 }
151 }
152 }
153} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs
new file mode 100644
index 0000000..4edaaca
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs
@@ -0,0 +1,438 @@
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.IO.Compression;
32using System.Reflection;
33using System.Text.RegularExpressions;
34using System.Threading;
35using System.Xml;
36using log4net;
37using OpenMetaverse;
38using OpenSim.Framework;
39using OpenSim.Framework.Serialization;
40using OpenSim.Region.CoreModules.World.Terrain;
41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes;
43using Ionic.Zlib;
44using GZipStream = Ionic.Zlib.GZipStream;
45using CompressionMode = Ionic.Zlib.CompressionMode;
46
47namespace OpenSim.Region.CoreModules.World.Archiver
48{
49 /// <summary>
50 /// Prepare to write out an archive.
51 /// </summary>
52 public class ArchiveWriteRequestPreparation
53 {
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55
56 /// <summary>
57 /// The minimum major version of OAR that we can write.
58 /// </summary>
59 public static int MIN_MAJOR_VERSION = 0;
60
61 /// <summary>
62 /// The maximum major version of OAR that we can write.
63 /// </summary>
64 public static int MAX_MAJOR_VERSION = 0;
65
66 /// <summary>
67 /// Determine whether this archive will save assets. Default is true.
68 /// </summary>
69 public bool SaveAssets { get; set; }
70
71 protected ArchiverModule m_module;
72 protected Scene m_scene;
73 protected Stream m_saveStream;
74 protected Guid m_requestId;
75
76 /// <summary>
77 /// Constructor
78 /// </summary>
79 /// <param name="module">Calling module</param>
80 /// <param name="savePath">The path to which to save data.</param>
81 /// <param name="requestId">The id associated with this request</param>
82 /// <exception cref="System.IO.IOException">
83 /// If there was a problem opening a stream for the file specified by the savePath
84 /// </exception>
85 public ArchiveWriteRequestPreparation(ArchiverModule module, string savePath, Guid requestId) : this(module, requestId)
86 {
87 try
88 {
89 m_saveStream = new GZipStream(new FileStream(savePath, FileMode.Create), CompressionMode.Compress, CompressionLevel.BestCompression);
90 }
91 catch (EntryPointNotFoundException e)
92 {
93 m_log.ErrorFormat(
94 "[ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream."
95 + "If you've manually installed Mono, have you appropriately updated zlib1g as well?");
96 m_log.ErrorFormat("{0} {1}", e.Message, e.StackTrace);
97 }
98 }
99
100 /// <summary>
101 /// Constructor.
102 /// </summary>
103 /// <param name="module">Calling module</param>
104 /// <param name="saveStream">The stream to which to save data.</param>
105 /// <param name="requestId">The id associated with this request</param>
106 public ArchiveWriteRequestPreparation(ArchiverModule module, Stream saveStream, Guid requestId) : this(module, requestId)
107 {
108 m_saveStream = saveStream;
109 }
110
111 protected ArchiveWriteRequestPreparation(ArchiverModule module, Guid requestId)
112 {
113 m_module = module;
114
115 // FIXME: This is only here for regression test purposes since they do not supply a module. Need to fix
116 // this.
117 if (m_module != null)
118 m_scene = m_module.Scene;
119
120 m_requestId = requestId;
121
122 SaveAssets = true;
123 }
124
125 /// <summary>
126 /// Archive the region requested.
127 /// </summary>
128 /// <exception cref="System.IO.IOException">if there was an io problem with creating the file</exception>
129 public void ArchiveRegion(Dictionary<string, object> options)
130 {
131 if (options.ContainsKey("noassets") && (bool)options["noassets"])
132 SaveAssets = false;
133
134 try
135 {
136 Dictionary<UUID, AssetType> assetUuids = new Dictionary<UUID, AssetType>();
137
138 EntityBase[] entities = m_scene.GetEntities();
139 List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>();
140
141 string checkPermissions = null;
142 int numObjectsSkippedPermissions = 0;
143 Object temp;
144 if (options.TryGetValue("checkPermissions", out temp))
145 checkPermissions = (string)temp;
146
147 // Filter entities so that we only have scene objects.
148 // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods
149 // end up having to do this
150 foreach (EntityBase entity in entities)
151 {
152 if (entity is SceneObjectGroup)
153 {
154 SceneObjectGroup sceneObject = (SceneObjectGroup)entity;
155
156 if (!sceneObject.IsDeleted && !sceneObject.IsAttachment)
157 {
158 if (!CanUserArchiveObject(m_scene.RegionInfo.EstateSettings.EstateOwner, sceneObject, checkPermissions))
159 {
160 // The user isn't allowed to copy/transfer this object, so it will not be included in the OAR.
161 ++numObjectsSkippedPermissions;
162 }
163 else
164 {
165 sceneObjects.Add(sceneObject);
166 }
167 }
168 }
169 }
170
171 if (SaveAssets)
172 {
173 UuidGatherer assetGatherer = new UuidGatherer(m_scene.AssetService);
174
175 foreach (SceneObjectGroup sceneObject in sceneObjects)
176 {
177 assetGatherer.GatherAssetUuids(sceneObject, assetUuids);
178 }
179
180 m_log.DebugFormat(
181 "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets",
182 sceneObjects.Count, assetUuids.Count);
183 }
184 else
185 {
186 m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified");
187 }
188
189 if (numObjectsSkippedPermissions > 0)
190 {
191 m_log.DebugFormat(
192 "[ARCHIVER]: {0} scene objects skipped due to lack of permissions",
193 numObjectsSkippedPermissions);
194 }
195
196 // Make sure that we also request terrain texture assets
197 RegionSettings regionSettings = m_scene.RegionInfo.RegionSettings;
198
199 if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1)
200 assetUuids[regionSettings.TerrainTexture1] = AssetType.Texture;
201
202 if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2)
203 assetUuids[regionSettings.TerrainTexture2] = AssetType.Texture;
204
205 if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3)
206 assetUuids[regionSettings.TerrainTexture3] = AssetType.Texture;
207
208 if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4)
209 assetUuids[regionSettings.TerrainTexture4] = AssetType.Texture;
210
211 TarArchiveWriter archiveWriter = new TarArchiveWriter(m_saveStream);
212
213 // Asynchronously request all the assets required to perform this archive operation
214 ArchiveWriteRequestExecution awre
215 = new ArchiveWriteRequestExecution(
216 sceneObjects,
217 m_scene.RequestModuleInterface<ITerrainModule>(),
218 m_scene.RequestModuleInterface<IRegionSerialiserModule>(),
219 m_scene,
220 archiveWriter,
221 m_requestId,
222 options);
223
224 m_log.InfoFormat("[ARCHIVER]: Creating archive file. This may take some time.");
225
226 // Write out control file. This has to be done first so that subsequent loaders will see this file first
227 // XXX: I know this is a weak way of doing it since external non-OAR aware tar executables will not do this
228 archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, CreateControlFile(options));
229 m_log.InfoFormat("[ARCHIVER]: Added control file to archive.");
230
231 if (SaveAssets)
232 {
233 AssetsRequest ar
234 = new AssetsRequest(
235 new AssetsArchiver(archiveWriter), assetUuids,
236 m_scene.AssetService, m_scene.UserAccountService,
237 m_scene.RegionInfo.ScopeID, options, awre.ReceivedAllAssets);
238
239 Util.FireAndForget(o => ar.Execute());
240 }
241 else
242 {
243 awre.ReceivedAllAssets(new List<UUID>(), new List<UUID>());
244 }
245 }
246 catch (Exception)
247 {
248 m_saveStream.Close();
249 throw;
250 }
251 }
252
253 /// <summary>
254 /// Checks whether the user has permission to export an object group to an OAR.
255 /// </summary>
256 /// <param name="user">The user</param>
257 /// <param name="objGroup">The object group</param>
258 /// <param name="checkPermissions">Which permissions to check: "C" = Copy, "T" = Transfer</param>
259 /// <returns>Whether the user is allowed to export the object to an OAR</returns>
260 private bool CanUserArchiveObject(UUID user, SceneObjectGroup objGroup, string checkPermissions)
261 {
262 if (checkPermissions == null)
263 return true;
264
265 IPermissionsModule module = m_scene.RequestModuleInterface<IPermissionsModule>();
266 if (module == null)
267 return true; // this shouldn't happen
268
269 // Check whether the user is permitted to export all of the parts in the SOG. If any
270 // part can't be exported then the entire SOG can't be exported.
271
272 bool permitted = true;
273 //int primNumber = 1;
274
275 foreach (SceneObjectPart obj in objGroup.Parts)
276 {
277 uint perm;
278 PermissionClass permissionClass = module.GetPermissionClass(user, obj);
279 switch (permissionClass)
280 {
281 case PermissionClass.Owner:
282 perm = obj.BaseMask;
283 break;
284 case PermissionClass.Group:
285 perm = obj.GroupMask | obj.EveryoneMask;
286 break;
287 case PermissionClass.Everyone:
288 default:
289 perm = obj.EveryoneMask;
290 break;
291 }
292
293 bool canCopy = (perm & (uint)PermissionMask.Copy) != 0;
294 bool canTransfer = (perm & (uint)PermissionMask.Transfer) != 0;
295
296 // Special case: if Everyone can copy the object then this implies it can also be
297 // Transferred.
298 // However, if the user is the Owner then we don't check EveryoneMask, because it seems that the mask
299 // always (incorrectly) includes the Copy bit set in this case. But that's a mistake: the viewer
300 // does NOT show that the object has Everyone-Copy permissions, and doesn't allow it to be copied.
301 if (permissionClass != PermissionClass.Owner)
302 canTransfer |= (obj.EveryoneMask & (uint)PermissionMask.Copy) != 0;
303
304 bool partPermitted = true;
305 if (checkPermissions.Contains("C") && !canCopy)
306 partPermitted = false;
307 if (checkPermissions.Contains("T") && !canTransfer)
308 partPermitted = false;
309
310 // If the user is the Creator of the object then it can always be included in the OAR
311 bool creator = (obj.CreatorID.Guid == user.Guid);
312 if (creator)
313 partPermitted = true;
314
315 //string name = (objGroup.PrimCount == 1) ? objGroup.Name : string.Format("{0} ({1}/{2})", obj.Name, primNumber, objGroup.PrimCount);
316 //m_log.DebugFormat("[ARCHIVER]: Object permissions: {0}: Base={1:X4}, Owner={2:X4}, Everyone={3:X4}, permissionClass={4}, checkPermissions={5}, canCopy={6}, canTransfer={7}, creator={8}, permitted={9}",
317 // name, obj.BaseMask, obj.OwnerMask, obj.EveryoneMask,
318 // permissionClass, checkPermissions, canCopy, canTransfer, creator, partPermitted);
319
320 if (!partPermitted)
321 {
322 permitted = false;
323 break;
324 }
325
326 //++primNumber;
327 }
328
329 return permitted;
330 }
331
332 /// <summary>
333 /// Create the control file for the most up to date archive
334 /// </summary>
335 /// <returns></returns>
336 public string CreateControlFile(Dictionary<string, object> options)
337 {
338 int majorVersion = MAX_MAJOR_VERSION, minorVersion = 8;
339//
340// if (options.ContainsKey("version"))
341// {
342// string[] parts = options["version"].ToString().Split('.');
343// if (parts.Length >= 1)
344// {
345// majorVersion = Int32.Parse(parts[0]);
346//
347// if (parts.Length >= 2)
348// minorVersion = Int32.Parse(parts[1]);
349// }
350// }
351//
352// if (majorVersion < MIN_MAJOR_VERSION || majorVersion > MAX_MAJOR_VERSION)
353// {
354// throw new Exception(
355// string.Format(
356// "OAR version number for save must be between {0} and {1}",
357// MIN_MAJOR_VERSION, MAX_MAJOR_VERSION));
358// }
359// else if (majorVersion == MAX_MAJOR_VERSION)
360// {
361// // Force 1.0
362// minorVersion = 0;
363// }
364// else if (majorVersion == MIN_MAJOR_VERSION)
365// {
366// // Force 0.4
367// minorVersion = 4;
368// }
369
370 m_log.InfoFormat("[ARCHIVER]: Creating version {0}.{1} OAR", majorVersion, minorVersion);
371 //if (majorVersion == 1)
372 //{
373 // m_log.WarnFormat("[ARCHIVER]: Please be aware that version 1.0 OARs are not compatible with OpenSim 0.7.0.2 and earlier. Please use the --version=0 option if you want to produce a compatible OAR");
374 //}
375
376 String s;
377
378 using (StringWriter sw = new StringWriter())
379 {
380 using (XmlTextWriter xtw = new XmlTextWriter(sw))
381 {
382 xtw.Formatting = Formatting.Indented;
383 xtw.WriteStartDocument();
384 xtw.WriteStartElement("archive");
385 xtw.WriteAttributeString("major_version", majorVersion.ToString());
386 xtw.WriteAttributeString("minor_version", minorVersion.ToString());
387
388 xtw.WriteStartElement("creation_info");
389 DateTime now = DateTime.UtcNow;
390 TimeSpan t = now - new DateTime(1970, 1, 1);
391 xtw.WriteElementString("datetime", ((int)t.TotalSeconds).ToString());
392 xtw.WriteElementString("id", UUID.Random().ToString());
393 xtw.WriteEndElement();
394
395 xtw.WriteStartElement("region_info");
396
397 bool isMegaregion;
398 Vector2 size;
399 IRegionCombinerModule rcMod = null;
400
401 // FIXME: This is only here for regression test purposes since they do not supply a module. Need to fix
402 // this, possibly by doing control file creation somewhere else.
403 if (m_module != null)
404 rcMod = m_module.RegionCombinerModule;
405
406 if (rcMod != null)
407 isMegaregion = rcMod.IsRootForMegaregion(m_scene.RegionInfo.RegionID);
408 else
409 isMegaregion = false;
410
411 if (isMegaregion)
412 size = rcMod.GetSizeOfMegaregion(m_scene.RegionInfo.RegionID);
413 else
414 size = new Vector2((float)Constants.RegionSize, (float)Constants.RegionSize);
415
416 xtw.WriteElementString("is_megaregion", isMegaregion.ToString());
417 xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y));
418
419 xtw.WriteEndElement();
420
421 xtw.WriteElementString("assets_included", SaveAssets.ToString());
422
423 xtw.WriteEndElement();
424
425 xtw.Flush();
426 }
427
428 s = sw.ToString();
429 }
430
431// if (m_scene != null)
432// Console.WriteLine(
433// "[ARCHIVE WRITE REQUEST PREPARATION]: Control file for {0} is: {1}", m_scene.RegionInfo.RegionName, s);
434
435 return s;
436 }
437 }
438}
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs
index abf3713..bf3b124 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs
@@ -32,8 +32,6 @@ using System.Reflection;
32using log4net; 32using log4net;
33using NDesk.Options; 33using NDesk.Options;
34using Nini.Config; 34using Nini.Config;
35using OpenSim.Framework;
36using OpenSim.Framework.Console;
37using OpenSim.Region.Framework.Interfaces; 35using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes; 36using OpenSim.Region.Framework.Scenes;
39 37
@@ -119,7 +117,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
119// 117//
120// foreach (string param in mainParams) 118// foreach (string param in mainParams)
121// m_log.DebugFormat("GOT PARAM [{0}]", param); 119// m_log.DebugFormat("GOT PARAM [{0}]", param);
122 120
123 if (mainParams.Count > 2) 121 if (mainParams.Count > 2)
124 { 122 {
125 DearchiveRegion(mainParams[2], mergeOar, skipAssets, Guid.Empty); 123 DearchiveRegion(mainParams[2], mergeOar, skipAssets, Guid.Empty);
@@ -148,22 +146,17 @@ namespace OpenSim.Region.CoreModules.World.Archiver
148 ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; }); 146 ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; });
149 ops.Add("publish", v => options["wipe-owners"] = v != null); 147 ops.Add("publish", v => options["wipe-owners"] = v != null);
150 ops.Add("perm=", delegate(string v) { options["checkPermissions"] = v; }); 148 ops.Add("perm=", delegate(string v) { options["checkPermissions"] = v; });
151 ops.Add("all", delegate(string v) { options["all"] = v != null; });
152 149
153 List<string> mainParams = ops.Parse(cmdparams); 150 List<string> mainParams = ops.Parse(cmdparams);
154 151
155 string path;
156 if (mainParams.Count > 2) 152 if (mainParams.Count > 2)
157 path = mainParams[2]; 153 {
154 ArchiveRegion(mainParams[2], options);
155 }
158 else 156 else
159 path = DEFAULT_OAR_BACKUP_FILENAME; 157 {
160 158 ArchiveRegion(DEFAULT_OAR_BACKUP_FILENAME, options);
161 // Not doing this right now as this causes some problems with auto-backup systems. Maybe a force flag is 159 }
162 // needed
163// if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, path))
164// return;
165
166 ArchiveRegion(path, options);
167 } 160 }
168 161
169 public void ArchiveRegion(string savePath, Dictionary<string, object> options) 162 public void ArchiveRegion(string savePath, Dictionary<string, object> options)
@@ -176,7 +169,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
176 m_log.InfoFormat( 169 m_log.InfoFormat(
177 "[ARCHIVER]: Writing archive for region {0} to {1}", Scene.RegionInfo.RegionName, savePath); 170 "[ARCHIVER]: Writing archive for region {0} to {1}", Scene.RegionInfo.RegionName, savePath);
178 171
179 new ArchiveWriteRequest(Scene, savePath, requestId).ArchiveRegion(options); 172 new ArchiveWriteRequestPreparation(this, savePath, requestId).ArchiveRegion(options);
180 } 173 }
181 174
182 public void ArchiveRegion(Stream saveStream) 175 public void ArchiveRegion(Stream saveStream)
@@ -191,7 +184,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
191 184
192 public void ArchiveRegion(Stream saveStream, Guid requestId, Dictionary<string, object> options) 185 public void ArchiveRegion(Stream saveStream, Guid requestId, Dictionary<string, object> options)
193 { 186 {
194 new ArchiveWriteRequest(Scene, saveStream, requestId).ArchiveRegion(options); 187 new ArchiveWriteRequestPreparation(this, saveStream, requestId).ArchiveRegion(options);
195 } 188 }
196 189
197 public void DearchiveRegion(string loadPath) 190 public void DearchiveRegion(string loadPath)
diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
index e2f8833..89e9593 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
@@ -46,12 +46,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver
46 { 46 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 48
49 /// <summary>
50 /// Method called when all the necessary assets for an archive request have been received.
51 /// </summary>
52 public delegate void AssetsRequestCallback(
53 ICollection<UUID> assetsFoundUuids, ICollection<UUID> assetsNotFoundUuids);
54
55 enum RequestState 49 enum RequestState
56 { 50 {
57 Initial, 51 Initial,
@@ -129,10 +123,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver
129 m_options = options; 123 m_options = options;
130 m_repliesRequired = uuids.Count; 124 m_repliesRequired = uuids.Count;
131 125
132 // FIXME: This is a really poor way of handling the timeout since it will always leave the original requesting thread
133 // hanging. Need to restructure so an original request thread waits for a ManualResetEvent on asset received
134 // so we can properly abort that thread. Or request all assets synchronously, though that would be a more
135 // radical change
136 m_requestCallbackTimer = new System.Timers.Timer(TIMEOUT); 126 m_requestCallbackTimer = new System.Timers.Timer(TIMEOUT);
137 m_requestCallbackTimer.AutoReset = false; 127 m_requestCallbackTimer.AutoReset = false;
138 m_requestCallbackTimer.Elapsed += new ElapsedEventHandler(OnRequestCallbackTimeout); 128 m_requestCallbackTimer.Elapsed += new ElapsedEventHandler(OnRequestCallbackTimeout);
diff --git a/OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs b/OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs
deleted file mode 100644
index 3dcc020..0000000
--- a/OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs
+++ /dev/null
@@ -1,232 +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.Linq;
31using System.Text;
32using OpenSim.Region.Framework.Scenes;
33using OpenMetaverse;
34using System.Drawing;
35using log4net;
36using System.Reflection;
37using OpenSim.Framework.Serialization;
38
39namespace OpenSim.Region.CoreModules.World.Archiver
40{
41 /// <summary>
42 /// The regions included in an OAR file.
43 /// </summary>
44 public class DearchiveScenesInfo
45 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47
48 /// <summary>
49 /// One region in the archive.
50 /// </summary>
51 public class RegionInfo
52 {
53 /// <summary>
54 /// The subdirectory in which the region is stored.
55 /// </summary>
56 public string Directory { get; set; }
57
58 /// <summary>
59 /// The region's coordinates (relative to the South-West corner of the block).
60 /// </summary>
61 public Point Location { get; set; }
62
63 /// <summary>
64 /// The UUID of the original scene from which this archived region was saved.
65 /// </summary>
66 public string OriginalID { get; set; }
67
68 /// <summary>
69 /// The scene in the current simulator into which this region is loaded.
70 /// If null then the region doesn't have a corresponding scene, and it won't be loaded.
71 /// </summary>
72 public Scene Scene { get; set; }
73 }
74
75 /// <summary>
76 /// Whether this archive uses the multi-region format.
77 /// </summary>
78 public Boolean MultiRegionFormat { get; set; }
79
80 /// <summary>
81 /// Maps (Region directory -> region)
82 /// </summary>
83 protected Dictionary<string, RegionInfo> m_directory2region = new Dictionary<string, RegionInfo>();
84
85 /// <summary>
86 /// Maps (UUID of the scene in the simulator where the region will be loaded -> region)
87 /// </summary>
88 protected Dictionary<UUID, RegionInfo> m_newId2region = new Dictionary<UUID, RegionInfo>();
89
90 public int LoadedCreationDateTime { get; set; }
91 public string DefaultOriginalID { get; set; }
92
93 // These variables are used while reading the archive control file
94 protected int? m_curY = null;
95 protected int? m_curX = null;
96 protected RegionInfo m_curRegion;
97
98
99 public DearchiveScenesInfo()
100 {
101 MultiRegionFormat = false;
102 }
103
104
105 // The following methods are used while reading the archive control file
106
107 public void StartRow()
108 {
109 m_curY = (m_curY == null) ? 0 : m_curY + 1;
110 m_curX = null;
111 }
112
113 public void StartRegion()
114 {
115 m_curX = (m_curX == null) ? 0 : m_curX + 1;
116 // Note: this doesn't mean we have a real region in this location; this could just be a "hole"
117 }
118
119 public void SetRegionOriginalID(string id)
120 {
121 m_curRegion = new RegionInfo();
122 m_curRegion.Location = new Point((int)m_curX, (int)m_curY);
123 m_curRegion.OriginalID = id;
124 // 'curRegion' will be saved in 'm_directory2region' when SetRegionDir() is called
125 }
126
127 public void SetRegionDirectory(string directory)
128 {
129 m_curRegion.Directory = directory;
130 m_directory2region[directory] = m_curRegion;
131 }
132
133
134 /// <summary>
135 /// Sets all the scenes present in the simulator.
136 /// </summary>
137 /// <remarks>
138 /// This method matches regions in the archive to scenes in the simulator according to
139 /// their relative position. We only load regions if there's an existing Scene in the
140 /// grid location where the region should be loaded.
141 /// </remarks>
142 /// <param name="rootScene">The scene where the Load OAR operation was run</param>
143 /// <param name="simulatorScenes">All the scenes in the simulator</param>
144 public void SetSimulatorScenes(Scene rootScene, ArchiveScenesGroup simulatorScenes)
145 {
146 foreach (RegionInfo archivedRegion in m_directory2region.Values)
147 {
148 Point location = new Point((int)rootScene.RegionInfo.RegionLocX, (int)rootScene.RegionInfo.RegionLocY);
149 location.Offset(archivedRegion.Location);
150
151 Scene scene;
152 if (simulatorScenes.TryGetScene(location, out scene))
153 {
154 archivedRegion.Scene = scene;
155 m_newId2region[scene.RegionInfo.RegionID] = archivedRegion;
156 }
157 else
158 {
159 m_log.WarnFormat("[ARCHIVER]: Not loading archived region {0} because there's no existing region at location {1},{2}",
160 archivedRegion.Directory, location.X, location.Y);
161 }
162 }
163 }
164
165 /// <summary>
166 /// Returns the archived region according to the path of a file in the archive.
167 /// Also, converts the full path into a path that is relative to the region's directory.
168 /// </summary>
169 /// <param name="fullPath">The path of a file in the archive</param>
170 /// <param name="scene">The corresponding Scene, or null if none</param>
171 /// <param name="relativePath">The path relative to the region's directory. (Or the original
172 /// path, if this file doesn't belong to a region.)</param>
173 /// <returns>True: use this file; False: skip it</returns>
174 public bool GetRegionFromPath(string fullPath, out Scene scene, out string relativePath)
175 {
176 scene = null;
177 relativePath = fullPath;
178
179 if (!MultiRegionFormat)
180 {
181 if (m_newId2region.Count > 0)
182 scene = m_newId2region.First().Value.Scene;
183 return true;
184 }
185
186 if (!fullPath.StartsWith(ArchiveConstants.REGIONS_PATH))
187 return true; // this file doesn't belong to a region
188
189 string[] parts = fullPath.Split(new Char[] { '/' }, 3);
190 if (parts.Length != 3)
191 return false;
192 string regionDirectory = parts[1];
193 relativePath = parts[2];
194
195 RegionInfo region;
196 if (m_directory2region.TryGetValue(regionDirectory, out region))
197 {
198 scene = region.Scene;
199 return (scene != null);
200 }
201 else
202 {
203 return false;
204 }
205 }
206
207 /// <summary>
208 /// Returns the original UUID of a region (from the simulator where the OAR was saved),
209 /// given the UUID of the scene it was loaded into in the current simulator.
210 /// </summary>
211 /// <param name="newID"></param>
212 /// <returns></returns>
213 public string GetOriginalRegionID(UUID newID)
214 {
215 RegionInfo region;
216 if (m_newId2region.TryGetValue(newID, out region))
217 return region.OriginalID;
218 else
219 return DefaultOriginalID;
220 }
221
222 /// <summary>
223 /// Returns the scenes that have been (or will be) loaded.
224 /// </summary>
225 /// <returns></returns>
226 public List<UUID> GetLoadedScenes()
227 {
228 return m_newId2region.Keys.ToList();
229 }
230
231 }
232}
diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
index 82f49b0..5deaf52 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
@@ -47,41 +47,32 @@ using ArchiveConstants = OpenSim.Framework.Serialization.ArchiveConstants;
47using TarArchiveReader = OpenSim.Framework.Serialization.TarArchiveReader; 47using TarArchiveReader = OpenSim.Framework.Serialization.TarArchiveReader;
48using TarArchiveWriter = OpenSim.Framework.Serialization.TarArchiveWriter; 48using TarArchiveWriter = OpenSim.Framework.Serialization.TarArchiveWriter;
49using RegionSettings = OpenSim.Framework.RegionSettings; 49using RegionSettings = OpenSim.Framework.RegionSettings;
50using OpenSim.Region.Framework.Interfaces;
51 50
52namespace OpenSim.Region.CoreModules.World.Archiver.Tests 51namespace OpenSim.Region.CoreModules.World.Archiver.Tests
53{ 52{
54 [TestFixture] 53 [TestFixture]
55 public class ArchiverTests : OpenSimTestCase 54 public class ArchiverTests
56 { 55 {
57 private Guid m_lastRequestId; 56 private Guid m_lastRequestId;
58 private string m_lastErrorMessage; 57 private string m_lastErrorMessage;
59 58
60 protected SceneHelpers m_sceneHelpers;
61 protected TestScene m_scene; 59 protected TestScene m_scene;
62 protected ArchiverModule m_archiverModule; 60 protected ArchiverModule m_archiverModule;
63 protected SerialiserModule m_serialiserModule;
64 61
65 protected TaskInventoryItem m_soundItem; 62 protected TaskInventoryItem m_soundItem;
66 63
67 [SetUp] 64 [SetUp]
68 public override void SetUp() 65 public void SetUp()
69 { 66 {
70 base.SetUp();
71
72 // FIXME: Do something about this - relying on statics in unit tests causes trouble sooner or later
73 new SceneManager();
74
75 m_archiverModule = new ArchiverModule(); 67 m_archiverModule = new ArchiverModule();
76 m_serialiserModule = new SerialiserModule(); 68 SerialiserModule serialiserModule = new SerialiserModule();
77 TerrainModule terrainModule = new TerrainModule(); 69 TerrainModule terrainModule = new TerrainModule();
78 70
79 m_sceneHelpers = new SceneHelpers(); 71 m_scene = new SceneHelpers().SetupScene();
80 m_scene = m_sceneHelpers.SetupScene(); 72 SceneHelpers.SetupSceneModules(m_scene, m_archiverModule, serialiserModule, terrainModule);
81 SceneHelpers.SetupSceneModules(m_scene, m_archiverModule, m_serialiserModule, terrainModule);
82 } 73 }
83 74
84 private void LoadCompleted(Guid requestId, List<UUID> loadedScenes, string errorMessage) 75 private void LoadCompleted(Guid requestId, string errorMessage)
85 { 76 {
86 lock (this) 77 lock (this)
87 { 78 {
@@ -137,10 +128,26 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
137 TestHelpers.InMethod(); 128 TestHelpers.InMethod();
138// log4net.Config.XmlConfigurator.Configure(); 129// log4net.Config.XmlConfigurator.Configure();
139 130
140 SceneObjectGroup sog1; 131 SceneObjectPart part1 = CreateSceneObjectPart1();
141 SceneObjectGroup sog2; 132 SceneObjectGroup sog1 = new SceneObjectGroup(part1);
142 UUID ncAssetUuid; 133 m_scene.AddNewSceneObject(sog1, false);
143 CreateTestObjects(m_scene, out sog1, out sog2, out ncAssetUuid); 134
135 SceneObjectPart part2 = CreateSceneObjectPart2();
136
137 AssetNotecard nc = new AssetNotecard();
138 nc.BodyText = "Hello World!";
139 nc.Encode();
140 UUID ncAssetUuid = new UUID("00000000-0000-0000-1000-000000000000");
141 UUID ncItemUuid = new UUID("00000000-0000-0000-1100-000000000000");
142 AssetBase ncAsset
143 = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero);
144 m_scene.AssetService.Store(ncAsset);
145 SceneObjectGroup sog2 = new SceneObjectGroup(part2);
146 TaskInventoryItem ncItem
147 = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid };
148 part2.Inventory.AddInventoryItem(ncItem, true);
149
150 m_scene.AddNewSceneObject(sog2, false);
144 151
145 MemoryStream archiveWriteStream = new MemoryStream(); 152 MemoryStream archiveWriteStream = new MemoryStream();
146 m_scene.EventManager.OnOarFileSaved += SaveCompleted; 153 m_scene.EventManager.OnOarFileSaved += SaveCompleted;
@@ -179,7 +186,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
179 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); 186 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
180 187
181 ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty); 188 ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty);
182 arr.LoadControlFile(filePath, data, new DearchiveScenesInfo()); 189 arr.LoadControlFile(filePath, data);
183 190
184 Assert.That(arr.ControlFileLoaded, Is.True); 191 Assert.That(arr.ControlFileLoaded, Is.True);
185 192
@@ -204,30 +211,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
204 // TODO: Test presence of more files and contents of files. 211 // TODO: Test presence of more files and contents of files.
205 } 212 }
206 213
207 private void CreateTestObjects(Scene scene, out SceneObjectGroup sog1, out SceneObjectGroup sog2, out UUID ncAssetUuid)
208 {
209 SceneObjectPart part1 = CreateSceneObjectPart1();
210 sog1 = new SceneObjectGroup(part1);
211 scene.AddNewSceneObject(sog1, false);
212
213 AssetNotecard nc = new AssetNotecard();
214 nc.BodyText = "Hello World!";
215 nc.Encode();
216 ncAssetUuid = UUID.Random();
217 UUID ncItemUuid = UUID.Random();
218 AssetBase ncAsset
219 = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero);
220 m_scene.AssetService.Store(ncAsset);
221
222 TaskInventoryItem ncItem
223 = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid };
224 SceneObjectPart part2 = CreateSceneObjectPart2();
225 sog2 = new SceneObjectGroup(part2);
226 part2.Inventory.AddInventoryItem(ncItem, true);
227
228 scene.AddNewSceneObject(sog2, false);
229 }
230
231 /// <summary> 214 /// <summary>
232 /// Test saving an OpenSim Region Archive with the no assets option 215 /// Test saving an OpenSim Region Archive with the no assets option
233 /// </summary> 216 /// </summary>
@@ -287,7 +270,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
287 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); 270 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
288 271
289 ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty); 272 ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty);
290 arr.LoadControlFile(filePath, data, new DearchiveScenesInfo()); 273 arr.LoadControlFile(filePath, data);
291 274
292 Assert.That(arr.ControlFileLoaded, Is.True); 275 Assert.That(arr.ControlFileLoaded, Is.True);
293 276
@@ -324,7 +307,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
324 307
325 tar.WriteFile( 308 tar.WriteFile(
326 ArchiveConstants.CONTROL_FILE_PATH, 309 ArchiveConstants.CONTROL_FILE_PATH,
327 new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup())); 310 new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary<string, Object>()));
328 311
329 SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ownerId, "obj1-", 0x11); 312 SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ownerId, "obj1-", 0x11);
330 SceneObjectPart sop2 313 SceneObjectPart sop2
@@ -379,10 +362,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
379 // Also check that direct entries which will also have a file entry containing that directory doesn't 362 // Also check that direct entries which will also have a file entry containing that directory doesn't
380 // upset load 363 // upset load
381 tar.WriteDir(ArchiveConstants.TERRAINS_PATH); 364 tar.WriteDir(ArchiveConstants.TERRAINS_PATH);
382 365
383 tar.WriteFile( 366 tar.WriteFile(
384 ArchiveConstants.CONTROL_FILE_PATH, 367 ArchiveConstants.CONTROL_FILE_PATH,
385 new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup())); 368 new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary<string, Object>()));
369
386 SceneObjectPart part1 = CreateSceneObjectPart1(); 370 SceneObjectPart part1 = CreateSceneObjectPart1();
387 371
388 part1.SitTargetOrientation = new Quaternion(0.2f, 0.3f, 0.4f, 0.5f); 372 part1.SitTargetOrientation = new Quaternion(0.2f, 0.3f, 0.4f, 0.5f);
@@ -405,12 +389,31 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
405 Assert.That(soundDataResourceName, Is.Not.Null); 389 Assert.That(soundDataResourceName, Is.Not.Null);
406 390
407 byte[] soundData; 391 byte[] soundData;
408 UUID soundUuid; 392 Console.WriteLine("Loading " + soundDataResourceName);
409 CreateSoundAsset(tar, assembly, soundDataResourceName, out soundData, out soundUuid); 393 using (Stream resource = assembly.GetManifestResourceStream(soundDataResourceName))
410 394 {
411 TaskInventoryItem item1 395 using (BinaryReader br = new BinaryReader(resource))
412 = new TaskInventoryItem { AssetID = soundUuid, ItemID = soundItemUuid, Name = soundItemName }; 396 {
413 part1.Inventory.AddInventoryItem(item1, true); 397 // FIXME: Use the inspector instead
398 soundData = br.ReadBytes(99999999);
399 UUID soundUuid = UUID.Parse("00000000-0000-0000-0000-000000000001");
400 string soundAssetFileName
401 = ArchiveConstants.ASSETS_PATH + soundUuid
402 + ArchiveConstants.ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.SoundWAV];
403 tar.WriteFile(soundAssetFileName, soundData);
404
405 /*
406 AssetBase soundAsset = AssetHelpers.CreateAsset(soundUuid, soundData);
407 scene.AssetService.Store(soundAsset);
408 asset1FileName = ArchiveConstants.ASSETS_PATH + soundUuid + ".wav";
409 */
410
411 TaskInventoryItem item1
412 = new TaskInventoryItem { AssetID = soundUuid, ItemID = soundItemUuid, Name = soundItemName };
413 part1.Inventory.AddInventoryItem(item1, true);
414 }
415 }
416
414 m_scene.AddNewSceneObject(object1, false); 417 m_scene.AddNewSceneObject(object1, false);
415 418
416 string object1FileName = string.Format( 419 string object1FileName = string.Format(
@@ -432,34 +435,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
432 435
433 Assert.That(m_lastErrorMessage, Is.Null); 436 Assert.That(m_lastErrorMessage, Is.Null);
434 437
435 TestLoadedRegion(part1, soundItemName, soundData);
436 }
437
438 private static void CreateSoundAsset(TarArchiveWriter tar, Assembly assembly, string soundDataResourceName, out byte[] soundData, out UUID soundUuid)
439 {
440 using (Stream resource = assembly.GetManifestResourceStream(soundDataResourceName))
441 {
442 using (BinaryReader br = new BinaryReader(resource))
443 {
444 // FIXME: Use the inspector instead
445 soundData = br.ReadBytes(99999999);
446 soundUuid = UUID.Parse("00000000-0000-0000-0000-000000000001");
447 string soundAssetFileName
448 = ArchiveConstants.ASSETS_PATH + soundUuid
449 + ArchiveConstants.ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.SoundWAV];
450 tar.WriteFile(soundAssetFileName, soundData);
451
452 /*
453 AssetBase soundAsset = AssetHelpers.CreateAsset(soundUuid, soundData);
454 scene.AssetService.Store(soundAsset);
455 asset1FileName = ArchiveConstants.ASSETS_PATH + soundUuid + ".wav";
456 */
457 }
458 }
459 }
460
461 private void TestLoadedRegion(SceneObjectPart part1, string soundItemName, byte[] soundData)
462 {
463 SceneObjectPart object1PartLoaded = m_scene.GetSceneObjectPart(part1.Name); 438 SceneObjectPart object1PartLoaded = m_scene.GetSceneObjectPart(part1.Name);
464 439
465 Assert.That(object1PartLoaded, Is.Not.Null, "object1 was not loaded"); 440 Assert.That(object1PartLoaded, Is.Not.Null, "object1 was not loaded");
@@ -479,6 +454,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
479 Assert.That(loadedSoundAsset.Data, Is.EqualTo(soundData), "saved and loaded sound data do not match"); 454 Assert.That(loadedSoundAsset.Data, Is.EqualTo(soundData), "saved and loaded sound data do not match");
480 455
481 Assert.Greater(m_scene.LandChannel.AllParcels().Count, 0, "incorrect number of parcels"); 456 Assert.Greater(m_scene.LandChannel.AllParcels().Count, 0, "incorrect number of parcels");
457
458 // Temporary
459 Console.WriteLine("Successfully completed {0}", MethodBase.GetCurrentMethod());
482 } 460 }
483 461
484 /// <summary> 462 /// <summary>
@@ -538,8 +516,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
538 SerialiserModule serialiserModule = new SerialiserModule(); 516 SerialiserModule serialiserModule = new SerialiserModule();
539 TerrainModule terrainModule = new TerrainModule(); 517 TerrainModule terrainModule = new TerrainModule();
540 518
541 m_sceneHelpers = new SceneHelpers(); 519 TestScene scene2 = new SceneHelpers().SetupScene();
542 TestScene scene2 = m_sceneHelpers.SetupScene();
543 SceneHelpers.SetupSceneModules(scene2, archiverModule, serialiserModule, terrainModule); 520 SceneHelpers.SetupSceneModules(scene2, archiverModule, serialiserModule, terrainModule);
544 521
545 // Make sure there's a valid owner for the owner we saved (this should have been wiped if the code is 522 // Make sure there's a valid owner for the owner we saved (this should have been wiped if the code is
@@ -577,7 +554,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
577 tar.WriteDir(ArchiveConstants.TERRAINS_PATH); 554 tar.WriteDir(ArchiveConstants.TERRAINS_PATH);
578 tar.WriteFile( 555 tar.WriteFile(
579 ArchiveConstants.CONTROL_FILE_PATH, 556 ArchiveConstants.CONTROL_FILE_PATH,
580 new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup())); 557 new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary<string, Object>()));
581 558
582 RegionSettings rs = new RegionSettings(); 559 RegionSettings rs = new RegionSettings();
583 rs.AgentLimit = 17; 560 rs.AgentLimit = 17;
@@ -687,7 +664,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
687 SerialiserModule serialiserModule = new SerialiserModule(); 664 SerialiserModule serialiserModule = new SerialiserModule();
688 TerrainModule terrainModule = new TerrainModule(); 665 TerrainModule terrainModule = new TerrainModule();
689 666
690 Scene scene = m_sceneHelpers.SetupScene(); 667 Scene scene = new SceneHelpers().SetupScene();
691 SceneHelpers.SetupSceneModules(scene, archiverModule, serialiserModule, terrainModule); 668 SceneHelpers.SetupSceneModules(scene, archiverModule, serialiserModule, terrainModule);
692 669
693 m_scene.AddNewSceneObject(new SceneObjectGroup(part2), false); 670 m_scene.AddNewSceneObject(new SceneObjectGroup(part2), false);
@@ -723,258 +700,5 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
723 Assert.That(object2PartMerged.GroupPosition, Is.EqualTo(part2.GroupPosition), "object2 group position not equal after merge"); 700 Assert.That(object2PartMerged.GroupPosition, Is.EqualTo(part2.GroupPosition), "object2 group position not equal after merge");
724 } 701 }
725 } 702 }
726
727 /// <summary>
728 /// Test saving a multi-region OAR.
729 /// </summary>
730 [Test]
731 public void TestSaveMultiRegionOar()
732 {
733 TestHelpers.InMethod();
734
735 // Create test regions
736
737 int WIDTH = 2;
738 int HEIGHT = 2;
739
740 List<Scene> scenes = new List<Scene>();
741
742 // Maps (Directory in OAR file -> scene)
743 Dictionary<string, Scene> regionPaths = new Dictionary<string, Scene>();
744
745 // Maps (Scene -> expected object paths)
746 Dictionary<UUID, List<string>> expectedPaths = new Dictionary<UUID, List<string>>();
747
748 // List of expected assets
749 List<UUID> expectedAssets = new List<UUID>();
750
751 for (uint y = 0; y < HEIGHT; y++)
752 {
753 for (uint x = 0; x < WIDTH; x++)
754 {
755 Scene scene;
756 if (x == 0 && y == 0)
757 {
758 scene = m_scene; // this scene was already created in SetUp()
759 }
760 else
761 {
762 scene = m_sceneHelpers.SetupScene(string.Format("Unit test region {0}", (y * WIDTH) + x + 1), UUID.Random(), 1000 + x, 1000 + y);
763 SceneHelpers.SetupSceneModules(scene, new ArchiverModule(), m_serialiserModule, new TerrainModule());
764 }
765 scenes.Add(scene);
766
767 string dir = String.Format("{0}_{1}_{2}", x + 1, y + 1, scene.RegionInfo.RegionName.Replace(" ", "_"));
768 regionPaths[dir] = scene;
769
770 SceneObjectGroup sog1;
771 SceneObjectGroup sog2;
772 UUID ncAssetUuid;
773
774 CreateTestObjects(scene, out sog1, out sog2, out ncAssetUuid);
775
776 expectedPaths[scene.RegionInfo.RegionID] = new List<string>();
777 expectedPaths[scene.RegionInfo.RegionID].Add(ArchiveHelpers.CreateObjectPath(sog1));
778 expectedPaths[scene.RegionInfo.RegionID].Add(ArchiveHelpers.CreateObjectPath(sog2));
779
780 expectedAssets.Add(ncAssetUuid);
781 }
782 }
783
784
785 // Save OAR
786
787 MemoryStream archiveWriteStream = new MemoryStream();
788 m_scene.EventManager.OnOarFileSaved += SaveCompleted;
789
790 Guid requestId = new Guid("00000000-0000-0000-0000-808080808080");
791
792 Dictionary<string, Object> options = new Dictionary<string, Object>();
793 options.Add("all", true);
794
795 lock (this)
796 {
797 m_archiverModule.ArchiveRegion(archiveWriteStream, requestId, options);
798 Monitor.Wait(this, 60000);
799 }
800
801
802 // Check that the OAR contains the expected data
803
804 Assert.That(m_lastRequestId, Is.EqualTo(requestId));
805
806 byte[] archive = archiveWriteStream.ToArray();
807 MemoryStream archiveReadStream = new MemoryStream(archive);
808 TarArchiveReader tar = new TarArchiveReader(archiveReadStream);
809
810 Dictionary<UUID, List<string>> foundPaths = new Dictionary<UUID, List<string>>();
811 List<UUID> foundAssets = new List<UUID>();
812
813 foreach (Scene scene in scenes)
814 {
815 foundPaths[scene.RegionInfo.RegionID] = new List<string>();
816 }
817
818 string filePath;
819 TarArchiveReader.TarEntryType tarEntryType;
820
821 byte[] data = tar.ReadEntry(out filePath, out tarEntryType);
822 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
823
824 ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty);
825 arr.LoadControlFile(filePath, data, new DearchiveScenesInfo());
826
827 Assert.That(arr.ControlFileLoaded, Is.True);
828
829 while (tar.ReadEntry(out filePath, out tarEntryType) != null)
830 {
831 if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH))
832 {
833 // Assets are shared, so this file doesn't belong to any specific region.
834 string fileName = filePath.Remove(0, ArchiveConstants.ASSETS_PATH.Length);
835 if (fileName.EndsWith("_notecard.txt"))
836 foundAssets.Add(UUID.Parse(fileName.Substring(0, fileName.Length - "_notecard.txt".Length)));
837 }
838 else
839 {
840 // This file belongs to one of the regions. Find out which one.
841 Assert.IsTrue(filePath.StartsWith(ArchiveConstants.REGIONS_PATH));
842 string[] parts = filePath.Split(new Char[] { '/' }, 3);
843 Assert.AreEqual(3, parts.Length);
844 string regionDirectory = parts[1];
845 string relativePath = parts[2];
846 Scene scene = regionPaths[regionDirectory];
847
848 if (relativePath.StartsWith(ArchiveConstants.OBJECTS_PATH))
849 {
850 foundPaths[scene.RegionInfo.RegionID].Add(relativePath);
851 }
852 }
853 }
854
855 Assert.AreEqual(scenes.Count, foundPaths.Count);
856 foreach (Scene scene in scenes)
857 {
858 Assert.That(foundPaths[scene.RegionInfo.RegionID], Is.EquivalentTo(expectedPaths[scene.RegionInfo.RegionID]));
859 }
860
861 Assert.That(foundAssets, Is.EquivalentTo(expectedAssets));
862 }
863
864 /// <summary>
865 /// Test loading a multi-region OAR.
866 /// </summary>
867 [Test]
868 public void TestLoadMultiRegionOar()
869 {
870 TestHelpers.InMethod();
871
872 // Create an ArchiveScenesGroup with the regions in the OAR. This is needed to generate the control file.
873
874 int WIDTH = 2;
875 int HEIGHT = 2;
876
877 for (uint y = 0; y < HEIGHT; y++)
878 {
879 for (uint x = 0; x < WIDTH; x++)
880 {
881 Scene scene;
882 if (x == 0 && y == 0)
883 {
884 scene = m_scene; // this scene was already created in SetUp()
885 }
886 else
887 {
888 scene = m_sceneHelpers.SetupScene(string.Format("Unit test region {0}", (y * WIDTH) + x + 1), UUID.Random(), 1000 + x, 1000 + y);
889 SceneHelpers.SetupSceneModules(scene, new ArchiverModule(), m_serialiserModule, new TerrainModule());
890 }
891 }
892 }
893
894 ArchiveScenesGroup scenesGroup = new ArchiveScenesGroup();
895 SceneManager.Instance.ForEachScene(delegate(Scene scene)
896 {
897 scenesGroup.AddScene(scene);
898 });
899 scenesGroup.CalcSceneLocations();
900
901 // Generate the OAR file
902
903 MemoryStream archiveWriteStream = new MemoryStream();
904 TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream);
905
906 ArchiveWriteRequest writeRequest = new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty);
907 writeRequest.MultiRegionFormat = true;
908 tar.WriteFile(
909 ArchiveConstants.CONTROL_FILE_PATH, writeRequest.CreateControlFile(scenesGroup));
910
911 SceneObjectPart part1 = CreateSceneObjectPart1();
912 part1.SitTargetOrientation = new Quaternion(0.2f, 0.3f, 0.4f, 0.5f);
913 part1.SitTargetPosition = new Vector3(1, 2, 3);
914
915 SceneObjectGroup object1 = new SceneObjectGroup(part1);
916
917 // Let's put some inventory items into our object
918 string soundItemName = "sound-item1";
919 UUID soundItemUuid = UUID.Parse("00000000-0000-0000-0000-000000000002");
920 Type type = GetType();
921 Assembly assembly = type.Assembly;
922 string soundDataResourceName = null;
923 string[] names = assembly.GetManifestResourceNames();
924 foreach (string name in names)
925 {
926 if (name.EndsWith(".Resources.test-sound.wav"))
927 soundDataResourceName = name;
928 }
929 Assert.That(soundDataResourceName, Is.Not.Null);
930
931 byte[] soundData;
932 UUID soundUuid;
933 CreateSoundAsset(tar, assembly, soundDataResourceName, out soundData, out soundUuid);
934
935 TaskInventoryItem item1
936 = new TaskInventoryItem { AssetID = soundUuid, ItemID = soundItemUuid, Name = soundItemName };
937 part1.Inventory.AddInventoryItem(item1, true);
938 m_scene.AddNewSceneObject(object1, false);
939
940 string object1FileName = string.Format(
941 "{0}_{1:000}-{2:000}-{3:000}__{4}.xml",
942 part1.Name,
943 Math.Round(part1.GroupPosition.X), Math.Round(part1.GroupPosition.Y), Math.Round(part1.GroupPosition.Z),
944 part1.UUID);
945 string path = "regions/1_1_Unit_test_region/" + ArchiveConstants.OBJECTS_PATH + object1FileName;
946 tar.WriteFile(path, SceneObjectSerializer.ToXml2Format(object1));
947
948 tar.Close();
949
950
951 // Delete the current objects, to test that they're loaded from the OAR and didn't
952 // just remain in the scene.
953 SceneManager.Instance.ForEachScene(delegate(Scene scene)
954 {
955 scene.DeleteAllSceneObjects();
956 });
957
958 // Create a "hole", to test that that the corresponding region isn't loaded from the OAR
959 SceneManager.Instance.CloseScene(SceneManager.Instance.Scenes[1]);
960
961
962 // Check thay the OAR file contains the expected data
963
964 MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray());
965
966 lock (this)
967 {
968 m_scene.EventManager.OnOarFileLoaded += LoadCompleted;
969 m_archiverModule.DearchiveRegion(archiveReadStream);
970 }
971
972 Assert.That(m_lastErrorMessage, Is.Null);
973
974 Assert.AreEqual(3, SceneManager.Instance.Scenes.Count);
975
976 TestLoadedRegion(part1, soundItemName, soundData);
977 }
978
979 } 703 }
980} 704}
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
index 5fd1bce..fdef9d8 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
@@ -40,7 +40,6 @@ using OpenMetaverse;
40using OpenSim.Framework; 40using OpenSim.Framework;
41using OpenSim.Region.Framework.Interfaces; 41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
43using RegionFlags = OpenMetaverse.RegionFlags;
44 43
45namespace OpenSim.Region.CoreModules.World.Estate 44namespace OpenSim.Region.CoreModules.World.Estate
46{ 45{
diff --git a/OpenSim/Region/CoreModules/World/Land/DwellModule.cs b/OpenSim/Region/CoreModules/World/Land/DwellModule.cs
deleted file mode 100644
index d1f05a7..0000000
--- a/OpenSim/Region/CoreModules/World/Land/DwellModule.cs
+++ /dev/null
@@ -1,110 +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;
30using System.Collections.Generic;
31using System.Diagnostics;
32using System.Reflection;
33using System.Text;
34using log4net;
35using Nini.Config;
36using OpenMetaverse;
37using OpenMetaverse.StructuredData;
38using OpenMetaverse.Messages.Linden;
39using OpenSim.Framework;
40using OpenSim.Framework.Capabilities;
41using OpenSim.Framework.Console;
42using OpenSim.Framework.Servers;
43using OpenSim.Framework.Servers.HttpServer;
44using OpenSim.Region.CoreModules.Framework.InterfaceCommander;
45using OpenSim.Region.Framework.Interfaces;
46using OpenSim.Region.Framework.Scenes;
47using OpenSim.Region.Physics.Manager;
48using OpenSim.Services.Interfaces;
49using Caps = OpenSim.Framework.Capabilities.Caps;
50using GridRegion = OpenSim.Services.Interfaces.GridRegion;
51
52namespace OpenSim.Region.CoreModules.World.Land
53{
54 public class DwellModule : IDwellModule, INonSharedRegionModule
55 {
56 private Scene m_scene;
57
58 public Type ReplaceableInterface
59 {
60 get { return typeof(IDwellModule); }
61 }
62
63 public string Name
64 {
65 get { return "DwellModule"; }
66 }
67
68 public void Initialise(IConfigSource source)
69 {
70 }
71
72 public void AddRegion(Scene scene)
73 {
74 m_scene = scene;
75
76 m_scene.EventManager.OnNewClient += OnNewClient;
77 }
78
79 public void RegionLoaded(Scene scene)
80 {
81 }
82
83 public void RemoveRegion(Scene scene)
84 {
85 }
86
87 public void Close()
88 {
89 }
90
91 public void OnNewClient(IClientAPI client)
92 {
93 client.OnParcelDwellRequest += ClientOnParcelDwellRequest;
94 }
95
96 private void ClientOnParcelDwellRequest(int localID, IClientAPI client)
97 {
98 ILandObject parcel = m_scene.LandChannel.GetLandObject(localID);
99 if (parcel == null)
100 return;
101
102 client.SendParcelDwellReply(localID, parcel.LandData.GlobalID, parcel.LandData.Dwell);
103 }
104
105 public int GetDwell(UUID parcelID)
106 {
107 return 0;
108 }
109 }
110}
diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
index b5e2bc3..aae6603 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
@@ -927,7 +927,6 @@ namespace OpenSim.Region.CoreModules.World.Land
927 ILandObject newLand = startLandObject.Copy(); 927 ILandObject newLand = startLandObject.Copy();
928 newLand.LandData.Name = newLand.LandData.Name; 928 newLand.LandData.Name = newLand.LandData.Name;
929 newLand.LandData.GlobalID = UUID.Random(); 929 newLand.LandData.GlobalID = UUID.Random();
930 newLand.LandData.Dwell = 0;
931 930
932 newLand.SetLandBitmap(newLand.GetSquareLandBitmap(start_x, start_y, end_x, end_y)); 931 newLand.SetLandBitmap(newLand.GetSquareLandBitmap(start_x, start_y, end_x, end_y));
933 932
diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
index d5b2adb..4f06737 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
@@ -33,7 +33,6 @@ using OpenMetaverse;
33using OpenSim.Framework; 33using OpenSim.Framework;
34using OpenSim.Region.Framework.Interfaces; 34using OpenSim.Region.Framework.Interfaces;
35using OpenSim.Region.Framework.Scenes; 35using OpenSim.Region.Framework.Scenes;
36using RegionFlags = OpenMetaverse.RegionFlags;
37 36
38namespace OpenSim.Region.CoreModules.World.Land 37namespace OpenSim.Region.CoreModules.World.Land
39{ 38{
diff --git a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
index cbb3abe..102b4d7 100644
--- a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
@@ -69,7 +69,7 @@ namespace OpenSim.Region.CoreModules.World.Land
69 /// without recounting the whole sim. 69 /// without recounting the whole sim.
70 /// 70 ///
71 /// We start out tainted so that the first get call resets the various prim counts. 71 /// We start out tainted so that the first get call resets the various prim counts.
72 /// </value> 72 /// <value>
73 private bool m_Tainted = true; 73 private bool m_Tainted = true;
74 74
75 private Object m_TaintLock = new Object(); 75 private Object m_TaintLock = new Object();
diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
index ab8f143..09f6758 100644
--- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
@@ -27,12 +27,9 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.IO;
31using System.Linq;
32using System.Reflection; 30using System.Reflection;
33using System.Text; 31using System.Text;
34using System.Text.RegularExpressions; 32using System.Text.RegularExpressions;
35using System.Xml;
36using log4net; 33using log4net;
37using Mono.Addins; 34using Mono.Addins;
38using NDesk.Options; 35using NDesk.Options;
@@ -43,7 +40,6 @@ using OpenSim.Framework.Console;
43using OpenSim.Framework.Monitoring; 40using OpenSim.Framework.Monitoring;
44using OpenSim.Region.Framework.Interfaces; 41using OpenSim.Region.Framework.Interfaces;
45using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
46using OpenSim.Region.Framework.Scenes.Serialization;
47 43
48namespace OpenSim.Region.CoreModules.World.Objects.Commands 44namespace OpenSim.Region.CoreModules.World.Objects.Commands
49{ 45{
@@ -87,85 +83,52 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
87 m_console.Commands.AddCommand( 83 m_console.Commands.AddCommand(
88 "Objects", false, "delete object owner", 84 "Objects", false, "delete object owner",
89 "delete object owner <UUID>", 85 "delete object owner <UUID>",
90 "Delete scene objects by owner", 86 "Delete a scene object by owner", HandleDeleteObject);
91 "Command will ask for confirmation before proceeding.",
92 HandleDeleteObject);
93 87
94 m_console.Commands.AddCommand( 88 m_console.Commands.AddCommand(
95 "Objects", false, "delete object creator", 89 "Objects", false, "delete object creator",
96 "delete object creator <UUID>", 90 "delete object creator <UUID>",
97 "Delete scene objects by creator", 91 "Delete a scene object by creator", HandleDeleteObject);
98 "Command will ask for confirmation before proceeding.",
99 HandleDeleteObject);
100 92
101 m_console.Commands.AddCommand( 93 m_console.Commands.AddCommand(
102 "Objects", false, "delete object id", 94 "Objects", false, "delete object uuid",
103 "delete object id <UUID-or-localID>", 95 "delete object uuid <UUID>",
104 "Delete a scene object by uuid or localID", 96 "Delete a scene object by uuid", HandleDeleteObject);
105 HandleDeleteObject);
106 97
107 m_console.Commands.AddCommand( 98 m_console.Commands.AddCommand(
108 "Objects", false, "delete object name", 99 "Objects", false, "delete object name",
109 "delete object name [--regex] <name>", 100 "delete object name [--regex] <name>",
110 "Delete a scene object by name.", 101 "Delete a scene object by name.",
111 "Command will ask for confirmation before proceeding.\n" 102 "If --regex is specified then the name is treatead as a regular expression",
112 + "If --regex is specified then the name is treatead as a regular expression",
113 HandleDeleteObject); 103 HandleDeleteObject);
114 104
115 m_console.Commands.AddCommand( 105 m_console.Commands.AddCommand(
116 "Objects", false, "delete object outside", 106 "Objects", false, "delete object outside",
117 "delete object outside", 107 "delete object outside",
118 "Delete all scene objects outside region boundaries", 108 "Delete all scene objects outside region boundaries", HandleDeleteObject);
119 "Command will ask for confirmation before proceeding.",
120 HandleDeleteObject);
121 109
122 m_console.Commands.AddCommand( 110 m_console.Commands.AddCommand(
123 "Objects", 111 "Objects",
124 false, 112 false,
125 "delete object pos", 113 "show object uuid",
126 "delete object pos <start-coord> to <end-coord>", 114 "show object uuid <UUID>",
127 "Delete scene objects within the given area.", 115 "Show details of a scene object with the given UUID", HandleShowObjectByUuid);
128 ConsoleUtil.CoordHelp,
129 HandleDeleteObject);
130
131 m_console.Commands.AddCommand(
132 "Objects",
133 false,
134 "show object id",
135 "show object id [--full] <UUID-or-localID>",
136 "Show details of a scene object with the given UUID or localID",
137 "The --full option will print out information on all the parts of the object.\n"
138 + "For yet more detailed part information, use the \"show part\" commands.",
139 HandleShowObjectById);
140 116
141 m_console.Commands.AddCommand( 117 m_console.Commands.AddCommand(
142 "Objects", 118 "Objects",
143 false, 119 false,
144 "show object name", 120 "show object name",
145 "show object name [--full] [--regex] <name>", 121 "show object name [--regex] <name>",
146 "Show details of scene objects with the given name.", 122 "Show details of scene objects with the given name.",
147 "The --full option will print out information on all the parts of the object.\n" 123 "If --regex is specified then the name is treatead as a regular expression",
148 + "For yet more detailed part information, use the \"show part\" commands.\n"
149 + "If --regex is specified then the name is treatead as a regular expression.",
150 HandleShowObjectByName); 124 HandleShowObjectByName);
151 125
152 m_console.Commands.AddCommand( 126 m_console.Commands.AddCommand(
153 "Objects", 127 "Objects",
154 false, 128 false,
155 "show object pos", 129 "show part uuid",
156 "show object pos [--full] <start-coord> to <end-coord>", 130 "show part uuid <UUID>",
157 "Show details of scene objects within the given area.", 131 "Show details of a scene object parts with the given UUID", HandleShowPartByUuid);
158 "The --full option will print out information on all the parts of the object.\n"
159 + "For yet more detailed part information, use the \"show part\" commands.\n"
160 + ConsoleUtil.CoordHelp,
161 HandleShowObjectByPos);
162
163 m_console.Commands.AddCommand(
164 "Objects",
165 false,
166 "show part id",
167 "show part id <UUID-or-localID>",
168 "Show details of a scene object part with the given UUID or localID", HandleShowPartById);
169 132
170 m_console.Commands.AddCommand( 133 m_console.Commands.AddCommand(
171 "Objects", 134 "Objects",
@@ -173,28 +136,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
173 "show part name", 136 "show part name",
174 "show part name [--regex] <name>", 137 "show part name [--regex] <name>",
175 "Show details of scene object parts with the given name.", 138 "Show details of scene object parts with the given name.",
176 "If --regex is specified then the name is treated as a regular expression", 139 "If --regex is specified then the name is treatead as a regular expression",
177 HandleShowPartByName); 140 HandleShowPartByName);
178
179 m_console.Commands.AddCommand(
180 "Objects",
181 false,
182 "show part pos",
183 "show part pos <start-coord> to <end-coord>",
184 "Show details of scene object parts within the given area.",
185 ConsoleUtil.CoordHelp,
186 HandleShowPartByPos);
187
188 m_console.Commands.AddCommand(
189 "Objects",
190 false,
191 "dump object id",
192 "dump object id <UUID-or-localID>",
193 "Dump the formatted serialization of the given object to the file <UUID>.xml",
194 "e.g. dump object uuid c1ed6809-cc24-4061-a4c2-93082a2d1f1d will dump serialization to c1ed6809-cc24-4061-a4c2-93082a2d1f1d.xml\n"
195 + "To locate the UUID or localID in the first place, you need to use the other show object commands.\n"
196 + "If a local ID is given then the filename used is still that for the UUID",
197 HandleDumpObjectById);
198 } 141 }
199 142
200 public void RemoveRegion(Scene scene) 143 public void RemoveRegion(Scene scene)
@@ -207,75 +150,25 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
207// m_log.DebugFormat("[OBJECTS COMMANDS MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName); 150// m_log.DebugFormat("[OBJECTS COMMANDS MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName);
208 } 151 }
209 152
210 /// <summary> 153 private void HandleShowObjectByUuid(string module, string[] cmd)
211 /// Outputs the sogs to console.
212 /// </summary>
213 /// <param name='searchPredicate'></param>
214 /// <param name='showFull'>If true then output all part details. If false then output summary.</param>
215 private void OutputSogsToConsole(Predicate<SceneObjectGroup> searchPredicate, bool showFull)
216 {
217 List<SceneObjectGroup> sceneObjects = m_scene.GetSceneObjectGroups().FindAll(searchPredicate);
218
219 StringBuilder sb = new StringBuilder();
220
221 foreach (SceneObjectGroup so in sceneObjects)
222 {
223 AddSceneObjectReport(sb, so, showFull);
224 sb.Append("\n");
225 }
226
227 sb.AppendFormat("{0} object(s) found in {1}\n", sceneObjects.Count, m_scene.Name);
228
229 m_console.OutputFormat(sb.ToString());
230 }
231
232 private void OutputSopsToConsole(Predicate<SceneObjectPart> searchPredicate, bool showFull)
233 {
234 List<SceneObjectGroup> sceneObjects = m_scene.GetSceneObjectGroups();
235 List<SceneObjectPart> parts = new List<SceneObjectPart>();
236
237 sceneObjects.ForEach(so => parts.AddRange(Array.FindAll<SceneObjectPart>(so.Parts, searchPredicate)));
238
239 StringBuilder sb = new StringBuilder();
240
241 foreach (SceneObjectPart part in parts)
242 {
243 AddScenePartReport(sb, part, showFull);
244 sb.Append("\n");
245 }
246
247 sb.AppendFormat("{0} parts found in {1}\n", parts.Count, m_scene.Name);
248
249 m_console.OutputFormat(sb.ToString());
250 }
251
252 private void HandleShowObjectById(string module, string[] cmdparams)
253 { 154 {
254 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) 155 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
255 return; 156 return;
256 157
257 bool showFull = false; 158 if (cmd.Length < 4)
258 OptionSet options = new OptionSet().Add("full", v => showFull = v != null );
259
260 List<string> mainParams = options.Parse(cmdparams);
261
262 if (mainParams.Count < 4)
263 { 159 {
264 m_console.OutputFormat("Usage: show object uuid <uuid>"); 160 m_console.OutputFormat("Usage: show object uuid <uuid>");
265 return; 161 return;
266 } 162 }
267 163
268 UUID uuid; 164 UUID objectUuid;
269 uint localId; 165 if (!UUID.TryParse(cmd[3], out objectUuid))
270 if (!ConsoleUtil.TryParseConsoleId(m_console, mainParams[3], out uuid, out localId)) 166 {
167 m_console.OutputFormat("{0} is not a valid uuid", cmd[3]);
271 return; 168 return;
169 }
272 170
273 SceneObjectGroup so; 171 SceneObjectGroup so = m_scene.GetSceneObjectGroup(objectUuid);
274
275 if (localId != ConsoleUtil.LocalIdNotFound)
276 so = m_scene.GetSceneObjectGroup(localId);
277 else
278 so = m_scene.GetSceneObjectGroup(uuid);
279 172
280 if (so == null) 173 if (so == null)
281 { 174 {
@@ -284,7 +177,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
284 } 177 }
285 178
286 StringBuilder sb = new StringBuilder(); 179 StringBuilder sb = new StringBuilder();
287 AddSceneObjectReport(sb, so, showFull); 180 AddSceneObjectReport(sb, so);
288 181
289 m_console.OutputFormat(sb.ToString()); 182 m_console.OutputFormat(sb.ToString());
290 } 183 }
@@ -294,91 +187,70 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
294 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) 187 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
295 return; 188 return;
296 189
297 bool showFull = false;
298 bool useRegex = false; 190 bool useRegex = false;
299 OptionSet options = new OptionSet(); 191 OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null );
300 options.Add("full", v => showFull = v != null );
301 options.Add("regex", v => useRegex = v != null );
302 192
303 List<string> mainParams = options.Parse(cmdparams); 193 List<string> mainParams = options.Parse(cmdparams);
304 194
305 if (mainParams.Count < 4) 195 if (mainParams.Count < 4)
306 { 196 {
307 m_console.OutputFormat("Usage: show object name [--full] [--regex] <name>"); 197 m_console.OutputFormat("Usage: show object name [--regex] <name>");
308 return; 198 return;
309 } 199 }
310 200
311 string name = mainParams[3]; 201 string name = mainParams[3];
312 202
313 Predicate<SceneObjectGroup> searchPredicate; 203 List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>();
204 Action<SceneObjectGroup> searchAction;
314 205
315 if (useRegex) 206 if (useRegex)
316 { 207 {
317 Regex nameRegex = new Regex(name); 208 Regex nameRegex = new Regex(name);
318 searchPredicate = so => nameRegex.IsMatch(so.Name); 209 searchAction = so => { if (nameRegex.IsMatch(so.Name)) { sceneObjects.Add(so); }};
319 } 210 }
320 else 211 else
321 { 212 {
322 searchPredicate = so => so.Name == name; 213 searchAction = so => { if (so.Name == name) { sceneObjects.Add(so); }};
323 } 214 }
324 215
325 OutputSogsToConsole(searchPredicate, showFull); 216 m_scene.ForEachSOG(searchAction);
326 }
327
328 private void HandleShowObjectByPos(string module, string[] cmdparams)
329 {
330 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
331 return;
332
333 bool showFull = false;
334 OptionSet options = new OptionSet().Add("full", v => showFull = v != null );
335
336 List<string> mainParams = options.Parse(cmdparams);
337 217
338 if (mainParams.Count < 5) 218 if (sceneObjects.Count == 0)
339 { 219 {
340 m_console.OutputFormat("Usage: show object pos [--full] <start-coord> to <end-coord>"); 220 m_console.OutputFormat("No objects with name {0} found in {1}", name, m_scene.RegionInfo.RegionName);
341 return; 221 return;
342 } 222 }
343 223
344 Vector3 startVector, endVector; 224 StringBuilder sb = new StringBuilder();
345
346 if (!TryParseVectorRange(cmdparams.Skip(3).Take(3), out startVector, out endVector))
347 return;
348 225
349 Predicate<SceneObjectGroup> searchPredicate 226 foreach (SceneObjectGroup so in sceneObjects)
350 = so => Util.IsInsideBox(so.AbsolutePosition, startVector, endVector); 227 {
228 AddSceneObjectReport(sb, so);
229 sb.Append("\n");
230 }
351 231
352 OutputSogsToConsole(searchPredicate, showFull); 232 m_console.OutputFormat(sb.ToString());
353 } 233 }
354 234
355 private void HandleShowPartById(string module, string[] cmdparams) 235 private void HandleShowPartByUuid(string module, string[] cmd)
356 { 236 {
357 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) 237 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
358 return; 238 return;
359 239
360// bool showFull = false; 240 if (cmd.Length < 4)
361 OptionSet options = new OptionSet();
362// options.Add("full", v => showFull = v != null );
363
364 List<string> mainParams = options.Parse(cmdparams);
365
366 if (mainParams.Count < 4)
367 { 241 {
368 m_console.OutputFormat("Usage: show part id [--full] <UUID-or-localID>"); 242 m_console.OutputFormat("Usage: show part uuid <uuid>");
369 return; 243 return;
370 } 244 }
371 245
372 UUID objectUuid; 246 UUID objectUuid;
373 uint localId; 247 if (!UUID.TryParse(cmd[3], out objectUuid))
374 if (!ConsoleUtil.TryParseConsoleId(m_console, mainParams[3], out objectUuid, out localId)) 248 {
249 m_console.OutputFormat("{0} is not a valid uuid", cmd[3]);
375 return; 250 return;
251 }
376 252
377 SceneObjectPart sop; 253 SceneObjectPart sop = m_scene.GetSceneObjectPart(objectUuid);
378 if (localId == ConsoleUtil.LocalIdNotFound)
379 sop = m_scene.GetSceneObjectPart(objectUuid);
380 else
381 sop = m_scene.GetSceneObjectPart(localId);
382 254
383 if (sop == null) 255 if (sop == null)
384 { 256 {
@@ -387,239 +259,84 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
387 } 259 }
388 260
389 StringBuilder sb = new StringBuilder(); 261 StringBuilder sb = new StringBuilder();
390 AddScenePartReport(sb, sop, true); 262 AddScenePartReport(sb, sop);
391 263
392 m_console.OutputFormat(sb.ToString()); 264 m_console.OutputFormat(sb.ToString());
393 } 265 }
394 266
395 private void HandleShowPartByPos(string module, string[] cmdparams)
396 {
397 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
398 return;
399
400// bool showFull = false;
401 OptionSet options = new OptionSet();
402// options.Add("full", v => showFull = v != null );
403
404 List<string> mainParams = options.Parse(cmdparams);
405
406 if (mainParams.Count < 5)
407 {
408 m_console.OutputFormat("Usage: show part pos [--full] <start-coord> to <end-coord>");
409 return;
410 }
411
412 string rawConsoleStartVector = mainParams[3];
413 Vector3 startVector;
414
415 if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector))
416 {
417 m_console.OutputFormat("Error: Start vector {0} does not have a valid format", rawConsoleStartVector);
418 return;
419 }
420
421 string rawConsoleEndVector = mainParams[5];
422 Vector3 endVector;
423
424 if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector))
425 {
426 m_console.OutputFormat("Error: End vector {0} does not have a valid format", rawConsoleEndVector);
427 return;
428 }
429
430 OutputSopsToConsole(sop => Util.IsInsideBox(sop.AbsolutePosition, startVector, endVector), true);
431 }
432
433 private void HandleShowPartByName(string module, string[] cmdparams) 267 private void HandleShowPartByName(string module, string[] cmdparams)
434 { 268 {
435 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) 269 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
436 return; 270 return;
437 271
438// bool showFull = false;
439 bool useRegex = false; 272 bool useRegex = false;
440 OptionSet options = new OptionSet(); 273 OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null );
441// options.Add("full", v => showFull = v != null );
442 options.Add("regex", v => useRegex = v != null );
443 274
444 List<string> mainParams = options.Parse(cmdparams); 275 List<string> mainParams = options.Parse(cmdparams);
445 276
446 if (mainParams.Count < 4) 277 if (mainParams.Count < 4)
447 { 278 {
448 m_console.OutputFormat("Usage: show part name [--full] [--regex] <name>"); 279 m_console.OutputFormat("Usage: show part name [--regex] <name>");
449 return; 280 return;
450 } 281 }
451 282
452 string name = mainParams[3]; 283 string name = mainParams[3];
453 284
454 Predicate<SceneObjectPart> searchPredicate; 285 List<SceneObjectPart> parts = new List<SceneObjectPart>();
286
287 Action<SceneObjectGroup> searchAction;
455 288
456 if (useRegex) 289 if (useRegex)
457 { 290 {
458 Regex nameRegex = new Regex(name); 291 Regex nameRegex = new Regex(name);
459 searchPredicate = sop => nameRegex.IsMatch(sop.Name); 292 searchAction = so => so.ForEachPart(sop => { if (nameRegex.IsMatch(sop.Name)) { parts.Add(sop); } });
460 } 293 }
461 else 294 else
462 { 295 {
463 searchPredicate = sop => sop.Name == name; 296 searchAction = so => so.ForEachPart(sop => { if (sop.Name == name) { parts.Add(sop); } });
464 } 297 }
465 298
466 OutputSopsToConsole(searchPredicate, true); 299 m_scene.ForEachSOG(searchAction);
467 }
468
469 private void HandleDumpObjectById(string module, string[] cmdparams)
470 {
471 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
472 return;
473 300
474 if (cmdparams.Length < 4) 301 if (parts.Count == 0)
475 { 302 {
476 m_console.OutputFormat("Usage: dump object id <UUID-or-localID>"); 303 m_console.OutputFormat("No parts with name {0} found in {1}", name, m_scene.RegionInfo.RegionName);
477 return; 304 return;
478 } 305 }
479 306
480 UUID objectUuid; 307 StringBuilder sb = new StringBuilder();
481 uint localId;
482 if (!ConsoleUtil.TryParseConsoleId(m_console, cmdparams[3], out objectUuid, out localId))
483 return;
484
485 SceneObjectGroup so;
486 if (localId == ConsoleUtil.LocalIdNotFound)
487 so = m_scene.GetSceneObjectGroup(objectUuid);
488 else
489 so = m_scene.GetSceneObjectGroup(localId);
490 308
491 if (so == null) 309 foreach (SceneObjectPart part in parts)
492 { 310 {
493// m_console.OutputFormat("No part found with uuid {0}", objectUuid); 311 AddScenePartReport(sb, part);
494 return; 312 sb.Append("\n");
495 } 313 }
496 314
497 // In case we found it via local ID. 315 m_console.OutputFormat(sb.ToString());
498 objectUuid = so.UUID;
499
500 string fileName = string.Format("{0}.xml", objectUuid);
501
502 if (!ConsoleUtil.CheckFileDoesNotExist(m_console, fileName))
503 return;
504
505 using (XmlTextWriter xtw = new XmlTextWriter(fileName, Encoding.UTF8))
506 {
507 xtw.Formatting = Formatting.Indented;
508 SceneObjectSerializer.ToOriginalXmlFormat(so, xtw, true);
509 }
510
511 m_console.OutputFormat("Object dumped to file {0}", fileName);
512 } 316 }
513 317
514 /// <summary> 318 private StringBuilder AddSceneObjectReport(StringBuilder sb, SceneObjectGroup so)
515 /// Append a scene object report to an input StringBuilder
516 /// </summary>
517 /// <returns></returns>
518 /// <param name='sb'></param>
519 /// <param name='so'</param>
520 /// <param name='showFull'>
521 /// If true then information on all parts of an object is appended.
522 /// If false then only summary information about an object is appended.
523 /// </param>
524 private StringBuilder AddSceneObjectReport(StringBuilder sb, SceneObjectGroup so, bool showFull)
525 { 319 {
526 if (showFull) 320 sb.AppendFormat("Name: {0}\n", so.Name);
527 { 321 sb.AppendFormat("Description: {0}\n", so.Description);
528 foreach (SceneObjectPart sop in so.Parts) 322 sb.AppendFormat("Location: {0} @ {1}\n", so.AbsolutePosition, so.Scene.RegionInfo.RegionName);
529 { 323 sb.AppendFormat("Parts: {0}\n", so.PrimCount);
530 AddScenePartReport(sb, sop, false); 324 sb.AppendFormat("Flags: {0}\n", so.RootPart.Flags);
531 sb.Append("\n");
532 }
533 }
534 else
535 {
536 AddSummarySceneObjectReport(sb, so);
537 }
538 325
539 return sb; 326 return sb;
540 } 327 }
541 328
542 private StringBuilder AddSummarySceneObjectReport(StringBuilder sb, SceneObjectGroup so) 329 private StringBuilder AddScenePartReport(StringBuilder sb, SceneObjectPart sop)
543 {
544 ConsoleDisplayList cdl = new ConsoleDisplayList();
545 cdl.AddRow("Name", so.Name);
546 cdl.AddRow("Descrition", so.Description);
547 cdl.AddRow("Local ID", so.LocalId);
548 cdl.AddRow("UUID", so.UUID);
549 cdl.AddRow("Location", string.Format("{0} @ {1}", so.AbsolutePosition, so.Scene.Name));
550 cdl.AddRow("Parts", so.PrimCount);
551 cdl.AddRow("Flags", so.RootPart.Flags);
552
553 return sb.Append(cdl.ToString());
554 }
555
556 /// <summary>
557 /// Append a scene object part report to an input StringBuilder
558 /// </summary>
559 /// <returns></returns>
560 /// <param name='sb'></param>
561 /// <param name='sop'</param>
562 /// <param name='showFull'>
563 /// If true then information on each inventory item will be shown.
564 /// If false then only summary inventory information is shown.
565 /// </param>
566 private StringBuilder AddScenePartReport(StringBuilder sb, SceneObjectPart sop, bool showFull)
567 {
568 ConsoleDisplayList cdl = new ConsoleDisplayList();
569 cdl.AddRow("Name", sop.Name);
570 cdl.AddRow("Description", sop.Description);
571 cdl.AddRow("Local ID", sop.LocalId);
572 cdl.AddRow("UUID", sop.UUID);
573 cdl.AddRow("Location", string.Format("{0} @ {1}", sop.AbsolutePosition, sop.ParentGroup.Scene.Name));
574 cdl.AddRow(
575 "Parent",
576 sop.IsRoot ? "Is Root" : string.Format("{0} {1}", sop.ParentGroup.Name, sop.ParentGroup.UUID));
577 cdl.AddRow("Link number", sop.LinkNum);
578 cdl.AddRow("Flags", sop.Flags);
579
580 object itemsOutput;
581 if (showFull)
582 {
583 StringBuilder itemsSb = new StringBuilder("\n");
584 itemsOutput = AddScenePartItemsReport(itemsSb, sop.Inventory).ToString();
585 }
586 else
587 {
588 itemsOutput = sop.Inventory.Count;
589 }
590
591
592 cdl.AddRow("Items", itemsOutput);
593
594 return sb.Append(cdl.ToString());
595 }
596
597 private StringBuilder AddScenePartItemsReport(StringBuilder sb, IEntityInventory inv)
598 { 330 {
599 ConsoleDisplayTable cdt = new ConsoleDisplayTable(); 331 sb.AppendFormat("Name: {0}\n", sop.Name);
600 cdt.Indent = 2; 332 sb.AppendFormat("Description: {0}\n", sop.Description);
601 333 sb.AppendFormat("Location: {0} @ {1}\n", sop.AbsolutePosition, sop.ParentGroup.Scene.RegionInfo.RegionName);
602 cdt.AddColumn("Name", 50); 334 sb.AppendFormat("Parent: {0}",
603 cdt.AddColumn("Type", 12); 335 sop.IsRoot ? "Is Root\n" : string.Format("{0} {1}\n", sop.ParentGroup.Name, sop.ParentGroup.UUID));
604 cdt.AddColumn("Running", 7); 336 sb.AppendFormat("Link number: {0}\n", sop.LinkNum);
605 cdt.AddColumn("Item UUID", 36); 337 sb.AppendFormat("Flags: {0}\n", sop.Flags);
606 cdt.AddColumn("Asset UUID", 36);
607
608 foreach (TaskInventoryItem item in inv.GetInventoryItems())
609 {
610 bool foundScriptInstance, scriptRunning;
611 foundScriptInstance
612 = SceneObjectPartInventory.TryGetScriptInstanceRunning(m_scene, item, out scriptRunning);
613
614 cdt.AddRow(
615 item.Name,
616 ((InventoryType)item.InvType).ToString(),
617 foundScriptInstance ? scriptRunning.ToString() : "n/a",
618 item.ItemID.ToString(),
619 item.AssetID.ToString());
620 }
621 338
622 return sb.Append(cdt.ToString()); 339 return sb;
623 } 340 }
624 341
625 private void HandleDeleteObject(string module, string[] cmd) 342 private void HandleDeleteObject(string module, string[] cmd)
@@ -681,24 +398,19 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
681 398
682 break; 399 break;
683 400
684 case "id": 401 case "uuid":
685 UUID uuid; 402 if (!UUID.TryParse(o, out match))
686 uint localId;
687 if (!ConsoleUtil.TryParseConsoleId(m_console, o, out uuid, out localId))
688 return; 403 return;
689 404
690 requireConfirmation = false; 405 requireConfirmation = false;
691 deletes = new List<SceneObjectGroup>(); 406 deletes = new List<SceneObjectGroup>();
692 407
693 SceneObjectGroup so; 408 m_scene.ForEachSOG(delegate (SceneObjectGroup g)
694 if (localId == ConsoleUtil.LocalIdNotFound) 409 {
695 so = m_scene.GetSceneObjectGroup(uuid); 410 if (g.UUID == match && !g.IsAttachment)
696 else 411 deletes.Add(g);
697 so = m_scene.GetSceneObjectGroup(localId); 412 });
698 413
699 if (!so.IsAttachment)
700 deletes.Add(so);
701
702 // if (deletes.Count == 0) 414 // if (deletes.Count == 0)
703 // m_console.OutputFormat("No objects were found with uuid {0}", match); 415 // m_console.OutputFormat("No objects were found with uuid {0}", match);
704 416
@@ -738,10 +450,6 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
738 450
739 break; 451 break;
740 452
741 case "pos":
742 deletes = GetDeleteCandidatesByPos(module, cmd);
743 break;
744
745 default: 453 default:
746 m_console.OutputFormat("Unrecognized mode {0}", mode); 454 m_console.OutputFormat("Unrecognized mode {0}", mode);
747 return; 455 return;
@@ -756,7 +464,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
756 string.Format( 464 string.Format(
757 "Are you sure that you want to delete {0} objects from {1}", 465 "Are you sure that you want to delete {0} objects from {1}",
758 deletes.Count, m_scene.RegionInfo.RegionName), 466 deletes.Count, m_scene.RegionInfo.RegionName),
759 "y/N"); 467 "n");
760 468
761 if (response.ToLower() != "y") 469 if (response.ToLower() != "y")
762 { 470 {
@@ -778,6 +486,9 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
778 486
779 private List<SceneObjectGroup> GetDeleteCandidatesByName(string module, string[] cmdparams) 487 private List<SceneObjectGroup> GetDeleteCandidatesByName(string module, string[] cmdparams)
780 { 488 {
489 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
490 return null;
491
781 bool useRegex = false; 492 bool useRegex = false;
782 OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null ); 493 OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null );
783 494
@@ -811,52 +522,5 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
811 522
812 return sceneObjects; 523 return sceneObjects;
813 } 524 }
814
815 /// <summary>
816 /// Get scene object delete candidates by position
817 /// </summary>
818 /// <param name='module'></param>
819 /// <param name='cmdparams'></param>
820 /// <returns>null if parsing failed on one of the arguments, otherwise a list of objects to delete. If there
821 /// are no objects to delete then the list will be empty./returns>
822 private List<SceneObjectGroup> GetDeleteCandidatesByPos(string module, string[] cmdparams)
823 {
824 if (cmdparams.Length < 5)
825 {
826 m_console.OutputFormat("Usage: delete object pos <start-coord> to <end-coord>");
827 return null;
828 }
829
830 Vector3 startVector, endVector;
831
832 if (!TryParseVectorRange(cmdparams.Skip(3).Take(3), out startVector, out endVector))
833 return null;
834
835 return m_scene.GetSceneObjectGroups().FindAll(
836 so => !so.IsAttachment && Util.IsInsideBox(so.AbsolutePosition, startVector, endVector));
837 }
838
839 private bool TryParseVectorRange(IEnumerable<string> rawComponents, out Vector3 startVector, out Vector3 endVector)
840 {
841 string rawConsoleStartVector = rawComponents.Take(1).Single();
842
843 if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector))
844 {
845 m_console.OutputFormat("Error: Start vector {0} does not have a valid format", rawConsoleStartVector);
846 endVector = Vector3.Zero;
847
848 return false;
849 }
850
851 string rawConsoleEndVector = rawComponents.Skip(1).Take(1).Single();
852
853 if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector))
854 {
855 m_console.OutputFormat("Error: End vector {0} does not have a valid format", rawConsoleEndVector);
856 return false;
857 }
858
859 return true;
860 }
861 } 525 }
862} \ No newline at end of file 526} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
index 513a8f5..14c1a39 100644
--- a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
+++ b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
@@ -24,110 +24,56 @@
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;
28using System.IO;
29using System.Collections.Generic;
30using System.Reflection;
31 27
28using System;
32using Nini.Config; 29using Nini.Config;
33using OpenMetaverse; 30using OpenMetaverse;
34using log4net;
35using Mono.Addins;
36
37using OpenSim.Framework; 31using OpenSim.Framework;
38using OpenSim.Region.Framework.Interfaces; 32using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes; 33using OpenSim.Region.Framework.Scenes;
34using System.Reflection;
35using log4net;
40 36
41namespace OpenSim.Region.CoreModules.World.Sound 37namespace OpenSim.Region.CoreModules.World.Sound
42{ 38{
43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SoundModule")] 39 public class SoundModule : IRegionModule, ISoundModule
44 public class SoundModule : INonSharedRegionModule, ISoundModule
45 { 40 {
46 private static readonly ILog m_log = LogManager.GetLogger( 41// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 MethodBase.GetCurrentMethod().DeclaringType); 42
48 43 protected Scene m_scene;
49 private Scene m_scene; 44
50 45 public void Initialise(Scene scene, IConfigSource source)
51 public bool Enabled { get; private set; }
52
53 public float MaxDistance { get; private set; }
54
55 #region INonSharedRegionModule
56
57 public void Initialise(IConfigSource configSource)
58 {
59 IConfig config = configSource.Configs["Sounds"];
60
61 if (config == null)
62 {
63 Enabled = true;
64 MaxDistance = 100.0f;
65 }
66 else
67 {
68 Enabled = config.GetString("Module", "OpenSim.Region.CoreModules.dll:SoundModule") ==
69 Path.GetFileName(Assembly.GetExecutingAssembly().Location)
70 + ":" + MethodBase.GetCurrentMethod().DeclaringType.Name;
71 MaxDistance = config.GetFloat("MaxDistance", 100.0f);
72 }
73 }
74
75 public void AddRegion(Scene scene) { }
76
77 public void RemoveRegion(Scene scene)
78 { 46 {
79 m_scene.EventManager.OnClientLogin -= OnNewClient;
80 }
81
82 public void RegionLoaded(Scene scene)
83 {
84 if (!Enabled)
85 return;
86
87 m_scene = scene; 47 m_scene = scene;
88 m_scene.EventManager.OnClientLogin += OnNewClient; 48
89 49 m_scene.EventManager.OnNewClient += OnNewClient;
50
90 m_scene.RegisterModuleInterface<ISoundModule>(this); 51 m_scene.RegisterModuleInterface<ISoundModule>(this);
91 } 52 }
92 53
93 public void Close() { } 54 public void PostInitialise() {}
94 55 public void Close() {}
95 public Type ReplaceableInterface
96 {
97 get { return typeof(ISoundModule); }
98 }
99
100 public string Name { get { return "Sound Module"; } } 56 public string Name { get { return "Sound Module"; } }
101 57 public bool IsSharedModule { get { return false; } }
102 #endregion 58
103
104 #region Event Handlers
105
106 private void OnNewClient(IClientAPI client) 59 private void OnNewClient(IClientAPI client)
107 { 60 {
108 client.OnSoundTrigger += TriggerSound; 61 client.OnSoundTrigger += TriggerSound;
109 } 62 }
110 63
111 #endregion
112
113 #region ISoundModule
114
115 public virtual void PlayAttachedSound( 64 public virtual void PlayAttachedSound(
116 UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags, float radius) 65 UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags, float radius)
117 { 66 {
118 SceneObjectPart part; 67 SceneObjectPart part = m_scene.GetSceneObjectPart(objectID);
119 if (!m_scene.TryGetSceneObjectPart(objectID, out part)) 68 if (part == null)
120 return; 69 return;
121 70
122 SceneObjectGroup grp = part.ParentGroup; 71 SceneObjectGroup grp = part.ParentGroup;
123 72
124 if (radius == 0)
125 radius = MaxDistance;
126
127 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) 73 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
128 { 74 {
129 double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); 75 double dis = Util.GetDistanceTo(sp.AbsolutePosition, position);
130 if (dis > MaxDistance) // Max audio distance 76 if (dis > 100.0) // Max audio distance
131 return; 77 return;
132 78
133 if (grp.IsAttachment) 79 if (grp.IsAttachment)
@@ -140,21 +86,23 @@ namespace OpenSim.Region.CoreModules.World.Sound
140 } 86 }
141 87
142 // Scale by distance 88 // Scale by distance
143 double thisSpGain = gain * ((radius - dis) / radius); 89 if (radius == 0)
90 gain = (float)((double)gain * ((100.0 - dis) / 100.0));
91 else
92 gain = (float)((double)gain * ((radius - dis) / radius));
144 93
145 sp.ControllingClient.SendPlayAttachedSound(soundID, objectID, 94 sp.ControllingClient.SendPlayAttachedSound(soundID, objectID, ownerID, (float)gain, flags);
146 ownerID, (float)thisSpGain, flags);
147 }); 95 });
148 } 96 }
149 97
150 public virtual void TriggerSound( 98 public virtual void TriggerSound(
151 UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius) 99 UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius)
152 { 100 {
153 SceneObjectPart part; 101 SceneObjectPart part = m_scene.GetSceneObjectPart(objectID);
154 if (!m_scene.TryGetSceneObjectPart(objectID, out part)) 102 if (part == null)
155 { 103 {
156 ScenePresence sp; 104 ScenePresence sp;
157 if (!m_scene.TryGetScenePresence(ownerID, out sp)) 105 if (!m_scene.TryGetScenePresence(objectID, out sp))
158 return; 106 return;
159 } 107 }
160 else 108 else
@@ -168,207 +116,24 @@ namespace OpenSim.Region.CoreModules.World.Sound
168 } 116 }
169 } 117 }
170 118
171 if (radius == 0)
172 radius = MaxDistance;
173
174 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) 119 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
175 { 120 {
176 double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); 121 double dis = Util.GetDistanceTo(sp.AbsolutePosition, position);
177 122
178 if (dis > MaxDistance) // Max audio distance 123 if (dis > 100.0) // Max audio distance
179 return; 124 return;
180 125
181 // Scale by distance 126 float thisSpGain;
182 double thisSpGain = gain * ((radius - dis) / radius);
183
184 sp.ControllingClient.SendTriggeredSound(soundId, ownerID,
185 objectID, parentID, handle, position,
186 (float)thisSpGain);
187 });
188 }
189
190 public virtual void StopSound(UUID objectID)
191 {
192 SceneObjectPart m_host;
193 if (!m_scene.TryGetSceneObjectPart(objectID, out m_host))
194 return;
195
196 StopSound(m_host);
197 }
198
199 private static void StopSound(SceneObjectPart m_host)
200 {
201 m_host.AdjustSoundGain(0);
202 // Xantor 20080528: Clear prim data of sound instead
203 if (m_host.ParentGroup.LoopSoundSlavePrims.Contains(m_host))
204 {
205 if (m_host.ParentGroup.LoopSoundMasterPrim == m_host)
206 {
207 foreach (SceneObjectPart part in m_host.ParentGroup.LoopSoundSlavePrims)
208 {
209 part.Sound = UUID.Zero;
210 part.SoundFlags = 1 << 5;
211 part.SoundRadius = 0;
212 part.ScheduleFullUpdate();
213 part.SendFullUpdateToAllClients();
214 }
215 m_host.ParentGroup.LoopSoundMasterPrim = null;
216 m_host.ParentGroup.LoopSoundSlavePrims.Clear();
217 }
218 else
219 {
220 m_host.Sound = UUID.Zero;
221 m_host.SoundFlags = 1 << 5;
222 m_host.SoundRadius = 0;
223 m_host.ScheduleFullUpdate();
224 m_host.SendFullUpdateToAllClients();
225 }
226 }
227 else
228 {
229 m_host.Sound = UUID.Zero;
230 m_host.SoundFlags = 1 << 5;
231 m_host.SoundRadius = 0;
232 m_host.ScheduleFullUpdate();
233 m_host.SendFullUpdateToAllClients();
234 }
235 }
236
237 public virtual void PreloadSound(UUID objectID, UUID soundID, float radius)
238 {
239 SceneObjectPart part;
240 if (soundID == UUID.Zero
241 || !m_scene.TryGetSceneObjectPart(objectID, out part))
242 {
243 return;
244 }
245
246 if (radius == 0)
247 radius = MaxDistance;
248
249 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
250 {
251 if (!(Util.GetDistanceTo(sp.AbsolutePosition, part.AbsolutePosition) >= MaxDistance))
252 sp.ControllingClient.SendPreLoadSound(objectID, objectID, soundID);
253 });
254 }
255
256 // Xantor 20080528 we should do this differently.
257 // 1) apply the sound to the object
258 // 2) schedule full update
259 // just sending the sound out once doesn't work so well when other avatars come in view later on
260 // or when the prim gets moved, changed, sat on, whatever
261 // see large number of mantises (mantes?)
262 // 20080530 Updated to remove code duplication
263 // 20080530 Stop sound if there is one, otherwise volume only changes don't work
264 public void LoopSound(UUID objectID, UUID soundID,
265 double volume, double radius, bool isMaster)
266 {
267 SceneObjectPart m_host;
268 if (!m_scene.TryGetSceneObjectPart(objectID, out m_host))
269 return;
270
271 if (isMaster)
272 m_host.ParentGroup.LoopSoundMasterPrim = m_host;
273
274 if (m_host.Sound != UUID.Zero)
275 StopSound(m_host);
276
277 m_host.Sound = soundID;
278 m_host.SoundGain = volume;
279 m_host.SoundFlags = 1; // looping
280 m_host.SoundRadius = radius;
281
282 m_host.ScheduleFullUpdate();
283 m_host.SendFullUpdateToAllClients();
284 }
285
286 public void SendSound(UUID objectID, UUID soundID, double volume,
287 bool triggered, byte flags, float radius, bool useMaster,
288 bool isMaster)
289 {
290 if (soundID == UUID.Zero)
291 return;
292
293 SceneObjectPart part;
294 if (!m_scene.TryGetSceneObjectPart(objectID, out part))
295 return;
296
297 volume = Util.Clip((float)volume, 0, 1);
298
299 UUID parentID = part.ParentGroup.UUID;
300
301 Vector3 position = part.AbsolutePosition; // region local
302 ulong regionHandle = m_scene.RegionInfo.RegionHandle;
303
304 if (useMaster)
305 {
306 if (isMaster)
307 {
308 if (triggered)
309 TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius);
310 else
311 PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius);
312 part.ParentGroup.PlaySoundMasterPrim = part;
313 if (triggered)
314 TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius);
315 else
316 PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius);
317 foreach (SceneObjectPart prim in part.ParentGroup.PlaySoundSlavePrims)
318 {
319 position = prim.AbsolutePosition; // region local
320 if (triggered)
321 TriggerSound(soundID, part.OwnerID, prim.UUID, parentID, volume, position, regionHandle, radius);
322 else
323 PlayAttachedSound(soundID, part.OwnerID, prim.UUID, volume, position, flags, radius);
324 }
325 part.ParentGroup.PlaySoundSlavePrims.Clear();
326 part.ParentGroup.PlaySoundMasterPrim = null;
327 }
328 else
329 {
330 part.ParentGroup.PlaySoundSlavePrims.Add(part);
331 }
332 }
333 else
334 {
335 if (triggered)
336 TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius);
337 else
338 PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius);
339 }
340 }
341
342 public void TriggerSoundLimited(UUID objectID, UUID sound,
343 double volume, Vector3 min, Vector3 max)
344 {
345 if (sound == UUID.Zero)
346 return;
347
348 SceneObjectPart part;
349 if (!m_scene.TryGetSceneObjectPart(objectID, out part))
350 return;
351
352 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
353 {
354 double dis = Util.GetDistanceTo(sp.AbsolutePosition,
355 part.AbsolutePosition);
356
357 if (dis > MaxDistance) // Max audio distance
358 return;
359 else if (!Util.IsInsideBox(sp.AbsolutePosition, min, max))
360 return;
361 127
362 // Scale by distance 128 // Scale by distance
363 double thisSpGain = volume * ((MaxDistance - dis) / MaxDistance); 129 if (radius == 0)
130 thisSpGain = (float)((double)gain * ((100.0 - dis) / 100.0));
131 else
132 thisSpGain = (float)((double)gain * ((radius - dis) / radius));
364 133
365 sp.ControllingClient.SendTriggeredSound(sound, part.OwnerID, 134 sp.ControllingClient.SendTriggeredSound(
366 part.UUID, part.ParentGroup.UUID, 135 soundId, ownerID, objectID, parentID, handle, position, thisSpGain);
367 m_scene.RegionInfo.RegionHandle,
368 part.AbsolutePosition, (float)thisSpGain);
369 }); 136 });
370 } 137 }
371
372 #endregion
373 } 138 }
374} 139}
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
index d99567c..402b9fb 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
@@ -414,7 +414,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain
414 private void LoadPlugins() 414 private void LoadPlugins()
415 { 415 {
416 m_plugineffects = new Dictionary<string, ITerrainEffect>(); 416 m_plugineffects = new Dictionary<string, ITerrainEffect>();
417 LoadPlugins(Assembly.GetCallingAssembly());
418 string plugineffectsPath = "Terrain"; 417 string plugineffectsPath = "Terrain";
419 418
420 // Load the files in the Terrain/ dir 419 // Load the files in the Terrain/ dir
@@ -428,39 +427,34 @@ namespace OpenSim.Region.CoreModules.World.Terrain
428 try 427 try
429 { 428 {
430 Assembly library = Assembly.LoadFrom(file); 429 Assembly library = Assembly.LoadFrom(file);
431 LoadPlugins(library); 430 foreach (Type pluginType in library.GetTypes())
432 } 431 {
433 catch (BadImageFormatException) 432 try
434 { 433 {
435 } 434 if (pluginType.IsAbstract || pluginType.IsNotPublic)
436 } 435 continue;
437 }
438
439 private void LoadPlugins(Assembly library)
440 {
441 foreach (Type pluginType in library.GetTypes())
442 {
443 try
444 {
445 if (pluginType.IsAbstract || pluginType.IsNotPublic)
446 continue;
447 436
448 string typeName = pluginType.Name; 437 string typeName = pluginType.Name;
449 438
450 if (pluginType.GetInterface("ITerrainEffect", false) != null) 439 if (pluginType.GetInterface("ITerrainEffect", false) != null)
451 { 440 {
452 ITerrainEffect terEffect = (ITerrainEffect)Activator.CreateInstance(library.GetType(pluginType.ToString())); 441 ITerrainEffect terEffect = (ITerrainEffect) Activator.CreateInstance(library.GetType(pluginType.ToString()));
453 442
454 InstallPlugin(typeName, terEffect); 443 InstallPlugin(typeName, terEffect);
455 } 444 }
456 else if (pluginType.GetInterface("ITerrainLoader", false) != null) 445 else if (pluginType.GetInterface("ITerrainLoader", false) != null)
457 { 446 {
458 ITerrainLoader terLoader = (ITerrainLoader)Activator.CreateInstance(library.GetType(pluginType.ToString())); 447 ITerrainLoader terLoader = (ITerrainLoader) Activator.CreateInstance(library.GetType(pluginType.ToString()));
459 m_loaders[terLoader.FileExtension] = terLoader; 448 m_loaders[terLoader.FileExtension] = terLoader;
460 m_log.Info("L ... " + typeName); 449 m_log.Info("L ... " + typeName);
450 }
451 }
452 catch (AmbiguousMatchException)
453 {
454 }
461 } 455 }
462 } 456 }
463 catch (AmbiguousMatchException) 457 catch (BadImageFormatException)
464 { 458 {
465 } 459 }
466 } 460 }
@@ -1184,8 +1178,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1184 1178
1185 private void InterfaceRunPluginEffect(Object[] args) 1179 private void InterfaceRunPluginEffect(Object[] args)
1186 { 1180 {
1187 string firstArg = (string)args[0]; 1181 if ((string) args[0] == "list")
1188 if (firstArg == "list")
1189 { 1182 {
1190 m_log.Info("List of loaded plugins"); 1183 m_log.Info("List of loaded plugins");
1191 foreach (KeyValuePair<string, ITerrainEffect> kvp in m_plugineffects) 1184 foreach (KeyValuePair<string, ITerrainEffect> kvp in m_plugineffects)
@@ -1194,14 +1187,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1194 } 1187 }
1195 return; 1188 return;
1196 } 1189 }
1197 if (firstArg == "reload") 1190 if ((string) args[0] == "reload")
1198 { 1191 {
1199 LoadPlugins(); 1192 LoadPlugins();
1200 return; 1193 return;
1201 } 1194 }
1202 if (m_plugineffects.ContainsKey(firstArg)) 1195 if (m_plugineffects.ContainsKey((string) args[0]))
1203 { 1196 {
1204 m_plugineffects[firstArg].RunEffect(m_channel); 1197 m_plugineffects[(string) args[0]].RunEffect(m_channel);
1205 CheckForTerrainUpdates(); 1198 CheckForTerrainUpdates();
1206 } 1199 }
1207 else 1200 else
diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
index 33f6c3f..3c48d07 100644
--- a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
+++ b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
@@ -222,13 +222,6 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
222 bitmap = ImageUtils.ResizeImage(origBitmap, viewport.Width, viewport.Height); 222 bitmap = ImageUtils.ResizeImage(origBitmap, viewport.Width, viewport.Height);
223 } 223 }
224 224
225 // XXX: It shouldn't really be necesary to force a GC here as one should occur anyway pretty shortly
226 // afterwards. It's generally regarded as a bad idea to manually GC. If Warp3D is using lots of memory
227 // then this may be some issue with the Warp3D code itself, though it's also quite possible that generating
228 // this map tile simply takes a lot of memory.
229 GC.Collect();
230 m_log.Debug("[WARP 3D IMAGE MODULE]: GC.Collect()");
231
232 return bitmap; 225 return bitmap;
233 } 226 }
234 227
diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
index d781eae..90a13a7 100644
--- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
@@ -114,15 +114,6 @@ namespace OpenSim.Region.Framework.Interfaces
114 void DetachSingleAttachmentToGround(IScenePresence sp, uint objectLocalID); 114 void DetachSingleAttachmentToGround(IScenePresence sp, uint objectLocalID);
115 115
116 /// <summary> 116 /// <summary>
117 /// Detach the given item to the ground at the specified coordinates & rotation
118 /// </summary>
119 /// <param name="sp"></param>
120 /// <param name="objectLocalID"></param>
121 /// <param name="absolutePos"></param>
122 /// <param name="absoluteRot"></param>
123 void DetachSingleAttachmentToGround(IScenePresence sp, uint objectLocalID, Vector3 absolutePos, Quaternion absoluteRot);
124
125 /// <summary>
126 /// Detach the given attachment so that it remains in the user's inventory. 117 /// Detach the given attachment so that it remains in the user's inventory.
127 /// </summary> 118 /// </summary>
128 /// <param name="sp">/param> 119 /// <param name="sp">/param>
diff --git a/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs b/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs
index 6df5cc2..8954513 100644
--- a/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs
+++ b/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs
@@ -25,8 +25,6 @@
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;
29using System.Drawing;
30using System.IO; 28using System.IO;
31using OpenMetaverse; 29using OpenMetaverse;
32 30
@@ -35,14 +33,7 @@ namespace OpenSim.Region.Framework.Interfaces
35 public interface IDynamicTextureManager 33 public interface IDynamicTextureManager
36 { 34 {
37 void RegisterRender(string handleType, IDynamicTextureRender render); 35 void RegisterRender(string handleType, IDynamicTextureRender render);
38 36 void ReturnData(UUID id, byte[] data);
39 /// <summary>
40 /// Used by IDynamicTextureRender implementations to return renders
41 /// </summary>
42 /// <param name='id'></param>
43 /// <param name='data'></param>
44 /// <param name='isReuseable'></param>
45 void ReturnData(UUID id, IDynamicTexture texture);
46 37
47 UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams, 38 UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams,
48 int updateTimer); 39 int updateTimer);
@@ -122,65 +113,11 @@ namespace OpenSim.Region.Framework.Interfaces
122 string GetName(); 113 string GetName();
123 string GetContentType(); 114 string GetContentType();
124 bool SupportsAsynchronous(); 115 bool SupportsAsynchronous();
125 116 byte[] ConvertUrl(string url, string extraParams);
126// /// <summary> 117 byte[] ConvertStream(Stream data, string extraParams);
127// /// Return true if converting the input body and extra params data will always result in the same byte[] array
128// /// </summary>
129// /// <remarks>
130// /// This method allows the caller to use a previously generated asset if it has one.
131// /// </remarks>
132// /// <returns></returns>
133// /// <param name='bodyData'></param>
134// /// <param name='extraParams'></param>
135// bool AlwaysIdenticalConversion(string bodyData, string extraParams);
136
137 IDynamicTexture ConvertUrl(string url, string extraParams);
138 IDynamicTexture ConvertData(string bodyData, string extraParams);
139
140 bool AsyncConvertUrl(UUID id, string url, string extraParams); 118 bool AsyncConvertUrl(UUID id, string url, string extraParams);
141 bool AsyncConvertData(UUID id, string bodyData, string extraParams); 119 bool AsyncConvertData(UUID id, string bodyData, string extraParams);
142
143 void GetDrawStringSize(string text, string fontName, int fontSize, 120 void GetDrawStringSize(string text, string fontName, int fontSize,
144 out double xSize, out double ySize); 121 out double xSize, out double ySize);
145 } 122 }
146
147 public interface IDynamicTexture
148 {
149 /// <summary>
150 /// Input commands used to generate this data.
151 /// </summary>
152 /// <remarks>
153 /// Null if input commands were not used.
154 /// </remarks>
155 string InputCommands { get; }
156
157 /// <summary>
158 /// Uri used to generate this data.
159 /// </summary>
160 /// <remarks>
161 /// Null if a uri was not used.
162 /// </remarks>
163 Uri InputUri { get; }
164
165 /// <summary>
166 /// Extra input params used to generate this data.
167 /// </summary>
168 string InputParams { get; }
169
170 /// <summary>
171 /// Texture data.
172 /// </summary>
173 byte[] Data { get; }
174
175 /// <summary>
176 /// Size of texture.
177 /// </summary>
178 Size Size { get; }
179
180 /// <summary>
181 /// Signal whether the texture is reuseable (i.e. whether the same input data will always generate the same
182 /// texture).
183 /// </summary>
184 bool IsReuseable { get; }
185 }
186} 123}
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
index 8028d87..4274cbe 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
@@ -152,19 +152,6 @@ namespace OpenSim.Region.Framework.Interfaces
152 void StopScriptInstance(UUID itemId); 152 void StopScriptInstance(UUID itemId);
153 153
154 /// <summary> 154 /// <summary>
155 /// Try to get the script running status.
156 /// </summary>
157 /// <returns>
158 /// Returns true if a script for the item was found in one of the simulator's script engines. In this case,
159 /// the running parameter will reflect the running status.
160 /// Returns false if the item could not be found, if the item is not a script or if a script instance for the
161 /// item was not found in any of the script engines. In this case, running status is irrelevant.
162 /// </returns>
163 /// <param name='itemId'></param>
164 /// <param name='running'></param>
165 bool TryGetScriptInstanceRunning(UUID itemId, out bool running);
166
167 /// <summary>
168 /// Add an item to this entity's inventory. If an item with the same name already exists, then an alternative 155 /// Add an item to this entity's inventory. If an item with the same name already exists, then an alternative
169 /// name is chosen. 156 /// name is chosen.
170 /// </summary> 157 /// </summary>
@@ -283,25 +270,17 @@ namespace OpenSim.Region.Framework.Interfaces
283 void ApplyGodPermissions(uint perms); 270 void ApplyGodPermissions(uint perms);
284 271
285 /// <summary> 272 /// <summary>
286 /// Number of items in this inventory.
287 /// </summary>
288 int Count { get; }
289
290 /// <summary>
291 /// Returns true if this inventory contains any scripts 273 /// Returns true if this inventory contains any scripts
292 /// </summary></returns> 274 /// </summary></returns>
293 bool ContainsScripts(); 275 bool ContainsScripts();
294 276
295 /// <summary> 277 /// <summary>
296 /// Number of scripts in this inventory. 278 /// Returns the count of scripts contained
297 /// </summary> 279 /// </summary></returns>
298 /// <remarks>
299 /// Includes both running and non running scripts.
300 /// </remarks>
301 int ScriptCount(); 280 int ScriptCount();
302 281
303 /// <summary> 282 /// <summary>
304 /// Number of running scripts in this inventory. 283 /// Returns the count of running scripts contained
305 /// </summary></returns> 284 /// </summary></returns>
306 int RunningScriptCount(); 285 int RunningScriptCount();
307 286
diff --git a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
index 292efa4..ca2ad94 100644
--- a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
@@ -46,10 +46,6 @@ namespace OpenSim.Region.Framework.Interfaces
46 /// </summary> 46 /// </summary>
47 void sendRegionHandshakeToAll(); 47 void sendRegionHandshakeToAll();
48 void TriggerEstateInfoChange(); 48 void TriggerEstateInfoChange();
49
50 /// <summary>
51 /// Fires the OnRegionInfoChange event.
52 /// </summary>
53 void TriggerRegionInfoChange(); 49 void TriggerRegionInfoChange();
54 50
55 void setEstateTerrainBaseTexture(int level, UUID texture); 51 void setEstateTerrainBaseTexture(int level, UUID texture);
diff --git a/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs
index da39e95..baac6e8 100644
--- a/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs
@@ -35,7 +35,7 @@ namespace OpenSim.Region.Framework.Interfaces
35 35
36 public interface IJsonStoreModule 36 public interface IJsonStoreModule
37 { 37 {
38 bool CreateStore(string value, ref UUID result); 38 bool CreateStore(string value, out UUID result);
39 bool DestroyStore(UUID storeID); 39 bool DestroyStore(UUID storeID);
40 bool TestPath(UUID storeID, string path, bool useJson); 40 bool TestPath(UUID storeID, string path, bool useJson);
41 bool SetValue(UUID storeID, string path, string value, bool useJson); 41 bool SetValue(UUID storeID, string path, string value, bool useJson);
diff --git a/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs b/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs
index 70ff954..a76ffde 100644
--- a/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs
+++ b/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs
@@ -47,46 +47,9 @@ namespace OpenSim.Region.Framework.Interfaces
47 /// </summary> 47 /// </summary>
48 event ScriptCommand OnScriptCommand; 48 event ScriptCommand OnScriptCommand;
49 49
50 /// <summary>
51 /// Register an instance method as a script call by method name
52 /// </summary>
53 /// <param name="target"></param>
54 /// <param name="method"></param>
55 void RegisterScriptInvocation(object target, string method); 50 void RegisterScriptInvocation(object target, string method);
56
57 /// <summary>
58 /// Register a static or instance method as a script call by method info
59 /// </summary>
60 /// <param name="target">If target is a Type object, will assume method is static.</param>
61 /// <param name="method"></param>
62 void RegisterScriptInvocation(object target, MethodInfo method); 51 void RegisterScriptInvocation(object target, MethodInfo method);
63
64 /// <summary>
65 /// Register one or more instance methods as script calls by method name
66 /// </summary>
67 /// <param name="target"></param>
68 /// <param name="methods"></param>
69 void RegisterScriptInvocation(object target, string[] methods); 52 void RegisterScriptInvocation(object target, string[] methods);
70
71 /// <summary>
72 /// Register one or more static methods as script calls by method name
73 /// </summary>
74 /// <param name="target"></param>
75 /// <param name="methods"></param>
76 void RegisterScriptInvocation(Type target, string[] methods);
77
78 /// <summary>
79 /// Automatically register script invocations by checking for methods
80 /// with <see cref="ScriptInvocationAttribute"/>. Should only check
81 /// public methods.
82 /// </summary>
83 /// <param name="target"></param>
84 void RegisterScriptInvocations(IRegionModuleBase target);
85
86 /// <summary>
87 /// Returns an array of all registered script calls
88 /// </summary>
89 /// <returns></returns>
90 Delegate[] GetScriptInvocationList(); 53 Delegate[] GetScriptInvocationList();
91 54
92 Delegate LookupScriptInvocation(string fname); 55 Delegate LookupScriptInvocation(string fname);
@@ -105,44 +68,12 @@ namespace OpenSim.Region.Framework.Interfaces
105 /// <param name="key"></param> 68 /// <param name="key"></param>
106 void DispatchReply(UUID scriptId, int code, string text, string key); 69 void DispatchReply(UUID scriptId, int code, string text, string key);
107 70
108 /// <summary> 71 /// For constants
109 /// Operation to for a region module to register a constant to be used
110 /// by the script engine
111 /// </summary>
112 /// <param name="cname">
113 /// The name of the constant. LSL convention is for constant names to
114 /// be uppercase.
115 /// </param>
116 /// <param name="value">
117 /// The value of the constant. Should be of a type that can be
118 /// converted to one of <see cref="OpenSim.Region.ScriptEngine.Shared.LSL_Types"/>
119 /// </param>
120 void RegisterConstant(string cname, object value); 72 void RegisterConstant(string cname, object value);
121
122 /// <summary>
123 /// Automatically register all constants on a region module by
124 /// checking for fields with <see cref="ScriptConstantAttribute"/>.
125 /// </summary>
126 /// <param name="target"></param>
127 void RegisterConstants(IRegionModuleBase target);
128
129 /// <summary>
130 /// Operation to check for a registered constant
131 /// </summary>
132 /// <param name="cname">Name of constant</param>
133 /// <returns>Value of constant or null if none found.</returns>
134 object LookupModConstant(string cname); 73 object LookupModConstant(string cname);
135 Dictionary<string, object> GetConstants(); 74 Dictionary<string, object> GetConstants();
136 75
137 // For use ONLY by the script API 76 // For use ONLY by the script API
138 void RaiseEvent(UUID script, string id, string module, string command, string key); 77 void RaiseEvent(UUID script, string id, string module, string command, string key);
139 } 78 }
140
141 [AttributeUsage(AttributeTargets.Method)]
142 public class ScriptInvocationAttribute : Attribute
143 { }
144
145 [AttributeUsage(AttributeTargets.Field)]
146 public class ScriptConstantAttribute : Attribute
147 { }
148} 79}
diff --git a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs
index 68af492..6117a80 100644
--- a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs
@@ -32,96 +32,9 @@ namespace OpenSim.Region.Framework.Interfaces
32{ 32{
33 public interface ISoundModule 33 public interface ISoundModule
34 { 34 {
35 /// <summary> 35 void PlayAttachedSound(UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags, float radius);
36 /// Maximum distance between a sound source and a recipient. 36
37 /// </summary>
38 float MaxDistance { get; }
39
40 /// <summary>
41 /// Play a sound from an object.
42 /// </summary>
43 /// <param name="soundID">Sound asset ID</param>
44 /// <param name="ownerID">Sound source owner</param>
45 /// <param name="objectID">Sound source ID</param>
46 /// <param name="gain">Sound volume</param>
47 /// <param name="position">Sound source position</param>
48 /// <param name="flags">Sound flags</param>
49 /// <param name="radius">
50 /// Radius used to affect gain over distance.
51 /// </param>
52 void PlayAttachedSound(UUID soundID, UUID ownerID, UUID objectID,
53 double gain, Vector3 position, byte flags, float radius);
54
55 /// <summary>
56 /// Trigger a sound in the scene.
57 /// </summary>
58 /// <param name="soundId">Sound asset ID</param>
59 /// <param name="ownerID">Sound source owner</param>
60 /// <param name="objectID">Sound source ID</param>
61 /// <param name="parentID">Sound source parent.</param>
62 /// <param name="gain">Sound volume</param>
63 /// <param name="position">Sound source position</param>
64 /// <param name="handle"></param>
65 /// <param name="radius">
66 /// Radius used to affect gain over distance.
67 /// </param>
68 void TriggerSound( 37 void TriggerSound(
69 UUID soundId, UUID ownerID, UUID objectID, UUID parentID, 38 UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius);
70 double gain, Vector3 position, UInt64 handle, float radius);
71
72 /// <summary>
73 /// Stop sounds eminating from an object.
74 /// </summary>
75 /// <param name="objectID">Sound source ID</param>
76 void StopSound(UUID objectID);
77
78 /// <summary>
79 /// Preload sound to viewers within range.
80 /// </summary>
81 /// <param name="objectID">Sound source ID</param>
82 /// <param name="soundID">Sound asset ID</param>
83 /// <param name="radius">
84 /// Radius used to determine which viewers should preload the sound.
85 /// </param>
86 void PreloadSound(UUID objectID, UUID soundID, float radius);
87
88 /// <summary>
89 /// Loop specified sound at specified volume with specified radius,
90 /// optionally declaring object as new sync master.
91 /// </summary>
92 /// <param name="objectID">Sound source ID</param>
93 /// <param name="soundID">Sound asset ID</param>
94 /// <param name="gain">Sound volume</param>
95 /// <param name="radius">Sound radius</param>
96 /// <param name="isMaster">Set object to sync master if true</param>
97 void LoopSound(UUID objectID, UUID soundID, double gain,
98 double radius, bool isMaster);
99
100 /// <summary>
101 /// Trigger or play an attached sound in this part's inventory.
102 /// </summary>
103 /// <param name="objectID">Sound source ID</param>
104 /// <param name="sound">Sound asset ID</param>
105 /// <param name="volume">Sound volume</param>
106 /// <param name="triggered">Triggered or not.</param>
107 /// <param name="flags"></param>
108 /// <param name="radius">Sound radius</param>
109 /// <param name="useMaster">Play using sound master</param>
110 /// <param name="isMaster">Play as sound master</param>
111 void SendSound(UUID objectID, UUID sound, double volume,
112 bool triggered, byte flags, float radius, bool useMaster,
113 bool isMaster);
114
115 /// <summary>
116 /// Trigger a sound to be played to all agents within an axis-aligned
117 /// bounding box.
118 /// </summary>
119 /// <param name="objectID">Sound source ID</param>
120 /// <param name="sound">Sound asset ID</param>
121 /// <param name="volume">Sound volume</param>
122 /// <param name="min">AABB bottom south-west corner</param>
123 /// <param name="max">AABB top north-east corner</param>
124 void TriggerSoundLimited(UUID objectID, UUID sound, double volume,
125 Vector3 min, Vector3 max);
126 } 39 }
127} \ No newline at end of file 40} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Interfaces/IUrlModule.cs b/OpenSim/Region/Framework/Interfaces/IUrlModule.cs
index 79e9f9d..457444c 100644
--- a/OpenSim/Region/Framework/Interfaces/IUrlModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IUrlModule.cs
@@ -39,8 +39,6 @@ namespace OpenSim.Region.Framework.Interfaces
39 UUID RequestSecureURL(IScriptModule engine, SceneObjectPart host, UUID itemID); 39 UUID RequestSecureURL(IScriptModule engine, SceneObjectPart host, UUID itemID);
40 void ReleaseURL(string url); 40 void ReleaseURL(string url);
41 void HttpResponse(UUID request, int status, string body); 41 void HttpResponse(UUID request, int status, string body);
42 void HttpContentType(UUID request, string type);
43
44 string GetHttpHeader(UUID request, string header); 42 string GetHttpHeader(UUID request, string header);
45 int GetFreeUrls(); 43 int GetFreeUrls();
46 44
diff --git a/OpenSim/Region/Framework/Interfaces/IUserManagement.cs b/OpenSim/Region/Framework/Interfaces/IUserManagement.cs
index f8088c3..24cd069 100644
--- a/OpenSim/Region/Framework/Interfaces/IUserManagement.cs
+++ b/OpenSim/Region/Framework/Interfaces/IUserManagement.cs
@@ -1,31 +1,4 @@
1/* 1using System;
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; 2using System.Collections.Generic;
30 3
31using OpenMetaverse; 4using OpenMetaverse;
diff --git a/OpenSim/Region/Framework/Interfaces/IWorldComm.cs b/OpenSim/Region/Framework/Interfaces/IWorldComm.cs
index 20e0199..e8e375e 100644
--- a/OpenSim/Region/Framework/Interfaces/IWorldComm.cs
+++ b/OpenSim/Region/Framework/Interfaces/IWorldComm.cs
@@ -45,13 +45,6 @@ namespace OpenSim.Region.Framework.Interfaces
45 void Deactivate(); 45 void Deactivate();
46 void Activate(); 46 void Activate();
47 UUID GetID(); 47 UUID GetID();
48
49 /// <summary>
50 /// Bitfield indicating which strings should be processed as regex.
51 /// 1 corresponds to IWorldCommListenerInfo::GetName()
52 /// 2 corresponds to IWorldCommListenerInfo::GetMessage()
53 /// </summary>
54 int RegexBitfield { get; }
55 } 48 }
56 49
57 public interface IWorldComm 50 public interface IWorldComm
@@ -67,7 +60,7 @@ namespace OpenSim.Region.Framework.Interfaces
67 /// the script during 'peek' time. Parameter hostID is needed to 60 /// the script during 'peek' time. Parameter hostID is needed to
68 /// determine the position of the script. 61 /// determine the position of the script.
69 /// </summary> 62 /// </summary>
70 /// <param name="LocalID">localID of the script engine</param> 63 /// <param name="localID">localID of the script engine</param>
71 /// <param name="itemID">UUID of the script engine</param> 64 /// <param name="itemID">UUID of the script engine</param>
72 /// <param name="hostID">UUID of the SceneObjectPart</param> 65 /// <param name="hostID">UUID of the SceneObjectPart</param>
73 /// <param name="channel">channel to listen on</param> 66 /// <param name="channel">channel to listen on</param>
@@ -77,23 +70,6 @@ namespace OpenSim.Region.Framework.Interfaces
77 /// <returns>number of the scripts handle</returns> 70 /// <returns>number of the scripts handle</returns>
78 int Listen(uint LocalID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg); 71 int Listen(uint LocalID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg);
79 72
80 /// <summary>
81 /// Create a listen event callback with the specified filters.
82 /// The parameters localID,itemID are needed to uniquely identify
83 /// the script during 'peek' time. Parameter hostID is needed to
84 /// determine the position of the script.
85 /// </summary>
86 /// <param name="LocalID">localID of the script engine</param>
87 /// <param name="itemID">UUID of the script engine</param>
88 /// <param name="hostID">UUID of the SceneObjectPart</param>
89 /// <param name="channel">channel to listen on</param>
90 /// <param name="name">name to filter on</param>
91 /// <param name="id">key to filter on (user given, could be totally faked)</param>
92 /// <param name="msg">msg to filter on</param>
93 /// <param name="regexBitfield">Bitfield indicating which strings should be processed as regex.</param>
94 /// <returns>number of the scripts handle</returns>
95 int Listen(uint LocalID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg, int regexBitfield);
96
97 /// <summary> 73 /// <summary>
98 /// This method scans over the objects which registered an interest in listen callbacks. 74 /// This method scans over the objects which registered an interest in listen callbacks.
99 /// For everyone it finds, it checks if it fits the given filter. If it does, then 75 /// For everyone it finds, it checks if it fits the given filter. If it does, then
diff --git a/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs
index 65ae445..ad421ee 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs
@@ -41,7 +41,6 @@ namespace OpenSim.Region.Framework.Scenes.Animation
41 { 41 {
42// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 42// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43 43
44 private OpenSim.Framework.Animation m_implicitDefaultAnimation = new OpenSim.Framework.Animation();
45 private OpenSim.Framework.Animation m_defaultAnimation = new OpenSim.Framework.Animation(); 44 private OpenSim.Framework.Animation m_defaultAnimation = new OpenSim.Framework.Animation();
46 private List<OpenSim.Framework.Animation> m_animations = new List<OpenSim.Framework.Animation>(); 45 private List<OpenSim.Framework.Animation> m_animations = new List<OpenSim.Framework.Animation>();
47 46
@@ -50,11 +49,6 @@ namespace OpenSim.Region.Framework.Scenes.Animation
50 get { return m_defaultAnimation; } 49 get { return m_defaultAnimation; }
51 } 50 }
52 51
53 public OpenSim.Framework.Animation ImplicitDefaultAnimation
54 {
55 get { return m_implicitDefaultAnimation; }
56 }
57
58 public AnimationSet() 52 public AnimationSet()
59 { 53 {
60 ResetDefaultAnimation(); 54 ResetDefaultAnimation();
@@ -125,18 +119,11 @@ namespace OpenSim.Region.Framework.Scenes.Animation
125 if (m_defaultAnimation.AnimID != animID) 119 if (m_defaultAnimation.AnimID != animID)
126 { 120 {
127 m_defaultAnimation = new OpenSim.Framework.Animation(animID, sequenceNum, objectID); 121 m_defaultAnimation = new OpenSim.Framework.Animation(animID, sequenceNum, objectID);
128 m_implicitDefaultAnimation = m_defaultAnimation;
129 return true; 122 return true;
130 } 123 }
131 return false; 124 return false;
132 } 125 }
133 126
134 // Called from serialization only
135 public void SetImplicitDefaultAnimation(UUID animID, int sequenceNum, UUID objectID)
136 {
137 m_implicitDefaultAnimation = new OpenSim.Framework.Animation(animID, sequenceNum, objectID);
138 }
139
140 protected bool ResetDefaultAnimation() 127 protected bool ResetDefaultAnimation()
141 { 128 {
142 return TrySetDefaultAnimation("STAND", 1, UUID.Zero); 129 return TrySetDefaultAnimation("STAND", 1, UUID.Zero);
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index 5b1c9f4..4a19c3b 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -47,75 +47,30 @@ namespace OpenSim.Region.Framework.Scenes
47 47
48 public delegate void OnFrameDelegate(); 48 public delegate void OnFrameDelegate();
49 49
50 /// <summary>
51 /// Triggered on each sim frame.
52 /// </summary>
53 /// <remarks>
54 /// This gets triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.Update"/>
55 /// Core uses it for things like Sun, Wind & Clouds
56 /// The MRM module also uses it.
57 /// </remarks>
58 public event OnFrameDelegate OnFrame; 50 public event OnFrameDelegate OnFrame;
59 51
60 public delegate void ClientMovement(ScenePresence client); 52 public delegate void ClientMovement(ScenePresence client);
61 53
62 /// <summary>
63 /// Trigerred when an agent moves.
64 /// </summary>
65 /// <remarks>
66 /// This gets triggered in <see cref="OpenSim.Region.Framework.Scenes.ScenePresence.HandleAgentUpdate"/>
67 /// prior to <see cref="OpenSim.Region.Framework.Scenes.ScenePresence.TriggerScenePresenceUpdated"/>
68 /// </remarks>
69 public event ClientMovement OnClientMovement; 54 public event ClientMovement OnClientMovement;
70 55
71 public delegate void OnTerrainTaintedDelegate(); 56 public delegate void OnTerrainTaintedDelegate();
72 57
73 /// <summary>
74 /// Triggered if the terrain has been edited
75 /// </summary>
76 /// <remarks>
77 /// This gets triggered in <see cref="OpenSim.Region.CoreModules.World.Terrain.CheckForTerrainUpdates"/>
78 /// after it determines that an update has been made.
79 /// </remarks>
80 public event OnTerrainTaintedDelegate OnTerrainTainted; 58 public event OnTerrainTaintedDelegate OnTerrainTainted;
81 59
82 public delegate void OnTerrainTickDelegate(); 60 public delegate void OnTerrainTickDelegate();
83 61
84 /// <summary>
85 /// Triggered if the terrain has been edited
86 /// </summary>
87 /// <remarks>
88 /// This gets triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.UpdateTerrain"/>
89 /// but is used by core solely to update the physics engine.
90 /// </remarks>
91 public event OnTerrainTickDelegate OnTerrainTick;
92
93 public delegate void OnTerrainUpdateDelegate(); 62 public delegate void OnTerrainUpdateDelegate();
94 63
64 public event OnTerrainTickDelegate OnTerrainTick;
65
95 public event OnTerrainUpdateDelegate OnTerrainUpdate; 66 public event OnTerrainUpdateDelegate OnTerrainUpdate;
96 67
97 public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup); 68 public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup);
98 69
99 /// <summary>
100 /// Triggered when a region is backed up/persisted to storage
101 /// </summary>
102 /// <remarks>
103 /// This gets triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.Backup"/>
104 /// and is fired before the persistence occurs.
105 /// </remarks>
106 public event OnBackupDelegate OnBackup; 70 public event OnBackupDelegate OnBackup;
107 71
108 public delegate void OnClientConnectCoreDelegate(IClientCore client); 72 public delegate void OnClientConnectCoreDelegate(IClientCore client);
109 73
110 /// <summary>
111 /// Triggered when a new client connects to the scene.
112 /// </summary>
113 /// <remarks>
114 /// This gets triggered in <see cref="TriggerOnNewClient"/>,
115 /// which checks if an instance of <see cref="OpenSim.Framework.IClientAPI"/>
116 /// also implements <see cref="OpenSim.Framework.Client.IClientCore"/> and as such,
117 /// is not triggered by <see cref="OpenSim.Region.OptionalModules.World.NPC">NPCs</see>.
118 /// </remarks>
119 public event OnClientConnectCoreDelegate OnClientConnect; 74 public event OnClientConnectCoreDelegate OnClientConnect;
120 75
121 public delegate void OnNewClientDelegate(IClientAPI client); 76 public delegate void OnNewClientDelegate(IClientAPI client);
@@ -125,96 +80,33 @@ namespace OpenSim.Region.Framework.Scenes
125 /// </summary> 80 /// </summary>
126 /// <remarks> 81 /// <remarks>
127 /// This is triggered for both child and root agent client connections. 82 /// This is triggered for both child and root agent client connections.
128 ///
129 /// Triggered before OnClientLogin. 83 /// Triggered before OnClientLogin.
130 ///
131 /// This is triggered under per-agent lock. So if you want to perform any long-running operations, please
132 /// do this on a separate thread.
133 /// </remarks> 84 /// </remarks>
134 public event OnNewClientDelegate OnNewClient; 85 public event OnNewClientDelegate OnNewClient;
135 86
136 /// <summary> 87 /// <summary>
137 /// Fired if the client entering this sim is doing so as a new login 88 /// Fired if the client entering this sim is doing so as a new login
138 /// </summary> 89 /// </summary>
139 /// <remarks>
140 /// This is triggered under per-agent lock. So if you want to perform any long-running operations, please
141 /// do this on a separate thread.
142 /// </remarks>
143 public event Action<IClientAPI> OnClientLogin; 90 public event Action<IClientAPI> OnClientLogin;
144 91
145 public delegate void OnNewPresenceDelegate(ScenePresence presence); 92 public delegate void OnNewPresenceDelegate(ScenePresence presence);
146 93
147 /// <summary>
148 /// Triggered when a new presence is added to the scene
149 /// </summary>
150 /// <remarks>
151 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/> which is used by both
152 /// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see>
153 /// </remarks>
154 public event OnNewPresenceDelegate OnNewPresence; 94 public event OnNewPresenceDelegate OnNewPresence;
155 95
156 public delegate void OnRemovePresenceDelegate(UUID agentId); 96 public delegate void OnRemovePresenceDelegate(UUID agentId);
157 97
158 /// <summary>
159 /// Triggered when a presence is removed from the scene
160 /// </summary>
161 /// <remarks>
162 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/> which is used by both
163 /// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see>
164 ///
165 /// Triggered under per-agent lock. So if you want to perform any long-running operations, please
166 /// do this on a separate thread.
167 /// </remarks>
168 public event OnRemovePresenceDelegate OnRemovePresence; 98 public event OnRemovePresenceDelegate OnRemovePresence;
169 99
170 public delegate void OnParcelPrimCountUpdateDelegate(); 100 public delegate void OnParcelPrimCountUpdateDelegate();
171 101
172 /// <summary>
173 /// Triggered whenever the prim count may have been altered, or prior
174 /// to an action that requires the current prim count to be accurate.
175 /// </summary>
176 /// <remarks>
177 /// Triggered by <see cref="TriggerParcelPrimCountUpdate"/> in
178 /// <see cref="OpenSim.OpenSimBase.CreateRegion"/>,
179 /// <see cref="OpenSim.Region.CoreModules.World.Land.LandManagementModule.EventManagerOnRequestParcelPrimCountUpdate"/>,
180 /// <see cref="OpenSim.Region.CoreModules.World.Land.LandManagementModule.ClientOnParcelObjectOwnerRequest"/>,
181 /// <see cref="OpenSim.Region.CoreModules.World.Land.LandObject.GetPrimsFree"/>,
182 /// <see cref="OpenSim.Region.CoreModules.World.Land.LandObject.UpdateLandSold"/>,
183 /// <see cref="OpenSim.Region.CoreModules.World.Land.LandObject.DeedToGroup"/>,
184 /// <see cref="OpenSim.Region.CoreModules.World.Land.LandObject.SendLandUpdateToClient"/>
185 /// </remarks>
186 public event OnParcelPrimCountUpdateDelegate OnParcelPrimCountUpdate; 102 public event OnParcelPrimCountUpdateDelegate OnParcelPrimCountUpdate;
187 103
188 public delegate void OnParcelPrimCountAddDelegate(SceneObjectGroup obj); 104 public delegate void OnParcelPrimCountAddDelegate(SceneObjectGroup obj);
189 105
190 /// <summary>
191 /// Triggered in response to <see cref="OnParcelPrimCountUpdate"/> for
192 /// objects that actually contribute to parcel prim count.
193 /// </summary>
194 /// <remarks>
195 /// Triggered by <see cref="TriggerParcelPrimCountAdd"/> in
196 /// <see cref="OpenSim.Region.CoreModules.World.Land.LandManagementModule.EventManagerOnParcelPrimCountUpdate"/>
197 /// </remarks>
198 public event OnParcelPrimCountAddDelegate OnParcelPrimCountAdd; 106 public event OnParcelPrimCountAddDelegate OnParcelPrimCountAdd;
199 107
200 public delegate void OnPluginConsoleDelegate(string[] args); 108 public delegate void OnPluginConsoleDelegate(string[] args);
201 109
202 /// <summary>
203 /// Triggered after <see cref="OpenSim.IApplicationPlugin.PostInitialise"/>
204 /// has been called for all <see cref="OpenSim.IApplicationPlugin"/>
205 /// loaded via <see cref="OpenSim.OpenSimBase.LoadPlugins"/>.
206 /// Handlers for this event are typically used to parse the arguments
207 /// from <see cref="OnPluginConsoleDelegate"/> in order to process or
208 /// filter the arguments and pass them onto <see cref="OpenSim.Region.CoreModules.Framework.InterfaceCommander.Commander.ProcessConsoleCommand"/>
209 /// </summary>
210 /// <remarks>
211 /// Triggered by <see cref="TriggerOnPluginConsole"/> in
212 /// <see cref="Scene.SendCommandToPlugins"/> via
213 /// <see cref="SceneManager.SendCommandToPluginModules"/> via
214 /// <see cref="OpenSim.OpenSimBase.HandleCommanderCommand"/> via
215 /// <see cref="OpenSim.OpenSimBase.AddPluginCommands"/> via
216 /// <see cref="OpenSim.OpenSimBase.StartupSpecific"/>
217 /// </remarks>
218 public event OnPluginConsoleDelegate OnPluginConsole; 110 public event OnPluginConsoleDelegate OnPluginConsole;
219 111
220 /// <summary> 112 /// <summary>
@@ -229,28 +121,8 @@ namespace OpenSim.Region.Framework.Scenes
229 121
230 public delegate void OnSetRootAgentSceneDelegate(UUID agentID, Scene scene); 122 public delegate void OnSetRootAgentSceneDelegate(UUID agentID, Scene scene);
231 123
232 /// <summary>
233 /// Triggered before the grunt work for adding a root agent to a
234 /// scene has been performed (resuming attachment scripts, physics,
235 /// animations etc.)
236 /// </summary>
237 /// <remarks>
238 /// Triggered before <see cref="OnMakeRootAgent"/>
239 /// by <see cref="TriggerSetRootAgentScene"/>
240 /// in <see cref="ScenePresence.MakeRootAgent"/>
241 /// via <see cref="Scene.AgentCrossing"/>
242 /// and <see cref="ScenePresence.CompleteMovement"/>
243 /// </remarks>
244 public event OnSetRootAgentSceneDelegate OnSetRootAgentScene; 124 public event OnSetRootAgentSceneDelegate OnSetRootAgentScene;
245 125
246 /// <summary>
247 /// Triggered after parcel properties have been updated.
248 /// </summary>
249 /// <remarks>
250 /// Triggered by <see cref="TriggerOnParcelPropertiesUpdateRequest"/> in
251 /// <see cref="OpenSim.Region.CoreModules.World.Land.LandManagementModule.ClientOnParcelPropertiesUpdateRequest"/>,
252 /// <see cref="OpenSim.Region.CoreModules.World.Land.LandManagementModule.ProcessPropertiesUpdate"/>
253 /// </remarks>
254 public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest; 126 public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest;
255 127
256 /// <summary> 128 /// <summary>
@@ -265,45 +137,13 @@ namespace OpenSim.Region.Framework.Scenes
265 /// <summary> 137 /// <summary>
266 /// Fired when an object is touched/grabbed. 138 /// Fired when an object is touched/grabbed.
267 /// </summary> 139 /// </summary>
268 /// <remarks>
269 /// The originalID is the local ID of the part that was actually touched. The localID itself is always that of 140 /// The originalID is the local ID of the part that was actually touched. The localID itself is always that of
270 /// the root part. 141 /// the root part.
271 /// Triggerd in response to <see cref="OpenSim.Framework.IClientAPI.OnGrabObject"/>
272 /// via <see cref="TriggerObjectGrab"/>
273 /// in <see cref="Scene.ProcessObjectGrab"/>
274 /// </remarks>
275 public event ObjectGrabDelegate OnObjectGrab; 142 public event ObjectGrabDelegate OnObjectGrab;
276 public delegate void ObjectGrabDelegate(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs); 143 public delegate void ObjectGrabDelegate(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs);
277 144
278 /// <summary>
279 /// Triggered when an object is being touched/grabbed continuously.
280 /// </summary>
281 /// <remarks>
282 /// Triggered in response to <see cref="OpenSim.Framework.IClientAPI.OnGrabUpdate"/>
283 /// via <see cref="TriggerObjectGrabbing"/>
284 /// in <see cref="Scene.ProcessObjectGrabUpdate"/>
285 /// </remarks>
286 public event ObjectGrabDelegate OnObjectGrabbing; 145 public event ObjectGrabDelegate OnObjectGrabbing;
287
288 /// <summary>
289 /// Triggered when an object stops being touched/grabbed.
290 /// </summary>
291 /// <remarks>
292 /// Triggered in response to <see cref="OpenSim.Framework.IClientAPI.OnDeGrabObject"/>
293 /// via <see cref="TriggerObjectDeGrab"/>
294 /// in <see cref="Scene.ProcessObjectDeGrab"/>
295 /// </remarks>
296 public event ObjectDeGrabDelegate OnObjectDeGrab; 146 public event ObjectDeGrabDelegate OnObjectDeGrab;
297
298 /// <summary>
299 /// Triggered when a script resets.
300 /// </summary>
301 /// <remarks>
302 /// Triggered by <see cref="TriggerScriptReset"/>
303 /// in <see cref="Scene.ProcessScriptReset"/>
304 /// via <see cref="OpenSim.Framework.IClientAPI.OnScriptReset"/>
305 /// via <see cref="OpenSim.Region.ClientStack.LindenUDP.LLClientView.HandleScriptReset"/>
306 /// </remarks>
307 public event ScriptResetDelegate OnScriptReset; 147 public event ScriptResetDelegate OnScriptReset;
308 148
309 public event OnPermissionErrorDelegate OnPermissionError; 149 public event OnPermissionErrorDelegate OnPermissionError;
@@ -313,105 +153,29 @@ namespace OpenSim.Region.Framework.Scenes
313 /// </summary> 153 /// </summary>
314 /// <remarks> 154 /// <remarks>
315 /// Occurs after OnNewScript. 155 /// Occurs after OnNewScript.
316 /// Triggered by <see cref="TriggerRezScript"/>
317 /// in <see cref="SceneObjectPartInventory.CreateScriptInstance"/>
318 /// </remarks> 156 /// </remarks>
319 public event NewRezScript OnRezScript; 157 public event NewRezScript OnRezScript;
320 public delegate void NewRezScript(uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine, int stateSource); 158 public delegate void NewRezScript(uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine, int stateSource);
321 159
322 public delegate void RemoveScript(uint localID, UUID itemID); 160 public delegate void RemoveScript(uint localID, UUID itemID);
323
324 /// <summary>
325 /// Triggered when a script is removed from an object.
326 /// </summary>
327 /// <remarks>
328 /// Triggered by <see cref="TriggerRemoveScript"/>
329 /// in <see cref="Scene.RemoveTaskInventory"/>,
330 /// <see cref="Scene.CreateAgentInventoryItemFromTask"/>,
331 /// <see cref="SceneObjectPartInventory.RemoveScriptInstance"/>,
332 /// <see cref="SceneObjectPartInventory.RemoveInventoryItem"/>
333 /// </remarks>
334 public event RemoveScript OnRemoveScript; 161 public event RemoveScript OnRemoveScript;
335 162
336 public delegate void StartScript(uint localID, UUID itemID); 163 public delegate void StartScript(uint localID, UUID itemID);
337
338 /// <summary>
339 /// Triggered when a script starts.
340 /// </summary>
341 /// <remarks>
342 /// Triggered by <see cref="TriggerStartScript"/>
343 /// in <see cref="Scene.SetScriptRunning"/>
344 /// via <see cref="OpenSim.Framework.IClientAPI.OnSetScriptRunning"/>,
345 /// via <see cref="OpenSim.Region.ClientStack.LindenUDP.HandleSetScriptRunning"/>
346 /// </remarks>
347 public event StartScript OnStartScript; 164 public event StartScript OnStartScript;
348 165
349 public delegate void StopScript(uint localID, UUID itemID); 166 public delegate void StopScript(uint localID, UUID itemID);
350
351 /// <summary>
352 /// Triggered when a script stops.
353 /// </summary>
354 /// <remarks>
355 /// Triggered by <see cref="TriggerStopScript"/>,
356 /// in <see cref="SceneObjectPartInventory.CreateScriptInstance"/>,
357 /// <see cref="SceneObjectPartInventory.StopScriptInstance"/>,
358 /// <see cref="Scene.SetScriptRunning"/>
359 /// </remarks>
360 public event StopScript OnStopScript; 167 public event StopScript OnStopScript;
361 168
362 public delegate bool SceneGroupMoved(UUID groupID, Vector3 delta); 169 public delegate bool SceneGroupMoved(UUID groupID, Vector3 delta);
363
364 /// <summary>
365 /// Triggered when an object is moved.
366 /// </summary>
367 /// <remarks>
368 /// Triggered by <see cref="TriggerGroupMove"/>
369 /// in <see cref="SceneObjectGroup.UpdateGroupPosition"/>,
370 /// <see cref="SceneObjectGroup.GrabMovement"/>
371 /// </remarks>
372 public event SceneGroupMoved OnSceneGroupMove; 170 public event SceneGroupMoved OnSceneGroupMove;
373 171
374 public delegate void SceneGroupGrabed(UUID groupID, Vector3 offset, UUID userID); 172 public delegate void SceneGroupGrabed(UUID groupID, Vector3 offset, UUID userID);
375
376 /// <summary>
377 /// Triggered when an object is grabbed.
378 /// </summary>
379 /// <remarks>
380 /// Triggered by <see cref="TriggerGroupGrab"/>
381 /// in <see cref="SceneObjectGroup.OnGrabGroup"/>
382 /// via <see cref="SceneObjectGroup.ObjectGrabHandler"/>
383 /// via <see cref="Scene.ProcessObjectGrab"/>
384 /// via <see cref="OpenSim.Framework.IClientAPI.OnGrabObject"/>
385 /// via <see cref="OpenSim.Region.ClientStack.LindenUDP.LLClientView.HandleObjectGrab"/>
386 /// </remarks>
387 public event SceneGroupGrabed OnSceneGroupGrab; 173 public event SceneGroupGrabed OnSceneGroupGrab;
388 174
389 public delegate bool SceneGroupSpinStarted(UUID groupID); 175 public delegate bool SceneGroupSpinStarted(UUID groupID);
390
391 /// <summary>
392 /// Triggered when an object starts to spin.
393 /// </summary>
394 /// <remarks>
395 /// Triggered by <see cref="TriggerGroupSpinStart"/>
396 /// in <see cref="SceneObjectGroup.SpinStart"/>
397 /// via <see cref="SceneGraph.SpinStart"/>
398 /// via <see cref="OpenSim.Framework.IClientAPI.OnSpinStart"/>
399 /// via <see cref="OpenSim.Region.ClientStack.LindenUDP.LLClientView.HandleObjectSpinStart"/>
400 /// </remarks>
401 public event SceneGroupSpinStarted OnSceneGroupSpinStart; 176 public event SceneGroupSpinStarted OnSceneGroupSpinStart;
402 177
403 public delegate bool SceneGroupSpun(UUID groupID, Quaternion rotation); 178 public delegate bool SceneGroupSpun(UUID groupID, Quaternion rotation);
404
405 /// <summary>
406 /// Triggered when an object is being spun.
407 /// </summary>
408 /// <remarks>
409 /// Triggered by <see cref="TriggerGroupSpin"/>
410 /// in <see cref="SceneObjectGroup.SpinMovement"/>
411 /// via <see cref="SceneGraph.SpinObject"/>
412 /// via <see cref="OpenSim.Framework.IClientAPI.OnSpinUpdate"/>
413 /// via <see cref="OpenSim.Region.ClientStack.LindenUDP.LLClientView.HandleObjectSpinUpdate"/>
414 /// </remarks>
415 public event SceneGroupSpun OnSceneGroupSpin; 179 public event SceneGroupSpun OnSceneGroupSpin;
416 180
417 public delegate void LandObjectAdded(ILandObject newParcel); 181 public delegate void LandObjectAdded(ILandObject newParcel);
@@ -440,9 +204,6 @@ namespace OpenSim.Region.Framework.Scenes
440 /// </summary> 204 /// </summary>
441 /// <remarks> 205 /// <remarks>
442 /// At the point of firing, the scene still contains the client's scene presence. 206 /// At the point of firing, the scene still contains the client's scene presence.
443 ///
444 /// This is triggered under per-agent lock. So if you want to perform any long-running operations, please
445 /// do this on a separate thread.
446 /// </remarks> 207 /// </remarks>
447 public event ClientClosed OnClientClosed; 208 public event ClientClosed OnClientClosed;
448 209
@@ -453,9 +214,6 @@ namespace OpenSim.Region.Framework.Scenes
453 /// </summary> 214 /// </summary>
454 /// <remarks> 215 /// <remarks>
455 /// Occurs before OnRezScript 216 /// Occurs before OnRezScript
456 /// Triggered by <see cref="TriggerNewScript"/>
457 /// in <see cref="Scene.RezScriptFromAgentInventory"/>,
458 /// <see cref="Scene.RezNewScript"/>
459 /// </remarks> 217 /// </remarks>
460 public event NewScript OnNewScript; 218 public event NewScript OnNewScript;
461 219
@@ -490,12 +248,6 @@ namespace OpenSim.Region.Framework.Scenes
490 /// </summary> 248 /// </summary>
491 /// <remarks> 249 /// <remarks>
492 /// Triggered after the scene receives a client's upload of an updated script and has stored it in an asset. 250 /// Triggered after the scene receives a client's upload of an updated script and has stored it in an asset.
493 /// Triggered by <see cref="TriggerUpdateScript"/>
494 /// in <see cref="Scene.CapsUpdateTaskInventoryScriptAsset"/>
495 /// via <see cref="Scene.CapsUpdateTaskInventoryScriptAsset"/>
496 /// via <see cref="OpenSim.Region.ClientStack.Linden.BunchOfCaps.TaskScriptUpdated"/>
497 /// via <see cref="OpenSim.Region.ClientStack.Linden.TaskInventoryScriptUpdater.OnUpLoad"/>
498 /// via <see cref="OpenSim.Region.ClientStack.Linden.TaskInventoryScriptUpdater.uploaderCaps"/>
499 /// </remarks> 251 /// </remarks>
500 public event UpdateScript OnUpdateScript; 252 public event UpdateScript OnUpdateScript;
501 253
@@ -521,203 +273,48 @@ namespace OpenSim.Region.Framework.Scenes
521 } 273 }
522 274
523 /// <summary> 275 /// <summary>
524 /// Triggered when some scene object properties change.
525 /// </summary>
526 /// <remarks>
527 /// ScriptChangedEvent is fired when a scene object property that a script might be interested 276 /// ScriptChangedEvent is fired when a scene object property that a script might be interested
528 /// in (such as color, scale or inventory) changes. Only enough information sent is for the LSL changed event. 277 /// in (such as color, scale or inventory) changes. Only enough information sent is for the LSL changed event.
529 /// This is not an indication that the script has changed (see OnUpdateScript for that). 278 /// This is not an indication that the script has changed (see OnUpdateScript for that).
530 /// This event is sent to a script to tell it that some property changed on 279 /// This event is sent to a script to tell it that some property changed on
531 /// the object the script is in. See http://lslwiki.net/lslwiki/wakka.php?wakka=changed . 280 /// the object the script is in. See http://lslwiki.net/lslwiki/wakka.php?wakka=changed .
532 /// Triggered by <see cref="TriggerOnScriptChangedEvent"/> 281 /// </summary>
533 /// in <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.TeleportAgentWithinRegion"/>,
534 /// <see cref="SceneObjectPart.TriggerScriptChangedEvent"/>
535 /// </remarks>
536 public event ScriptChangedEvent OnScriptChangedEvent; 282 public event ScriptChangedEvent OnScriptChangedEvent;
537 public delegate void ScriptChangedEvent(uint localID, uint change); 283 public delegate void ScriptChangedEvent(uint localID, uint change);
538 284
539 public delegate void ScriptControlEvent(UUID item, UUID avatarID, uint held, uint changed); 285 public delegate void ScriptControlEvent(UUID item, UUID avatarID, uint held, uint changed);
540
541 /// <summary>
542 /// Triggered when a script receives control input from an agent.
543 /// </summary>
544 /// <remarks>
545 /// Triggered by <see cref="TriggerControlEvent"/>
546 /// in <see cref="ScenePresence.SendControlsToScripts"/>
547 /// via <see cref="ScenePresence.HandleAgentUpdate"/>
548 /// via <see cref="OpenSim.Framework.IClientAPI.OnAgentUpdate"/>
549 /// via <see cref="OpenSim.Region.ClientStack.LindenUDP.LLClientView.HandleAgentUpdate"/>
550 /// </remarks>
551 public event ScriptControlEvent OnScriptControlEvent; 286 public event ScriptControlEvent OnScriptControlEvent;
552 287
553 public delegate void ScriptAtTargetEvent(uint localID, uint handle, Vector3 targetpos, Vector3 atpos); 288 public delegate void ScriptAtTargetEvent(uint localID, uint handle, Vector3 targetpos, Vector3 atpos);
554
555 /// <summary>
556 /// Triggered when an object has arrived within a tolerance distance
557 /// of a motion target.
558 /// </summary>
559 /// <remarks>
560 /// Triggered by <see cref="TriggerAtTargetEvent"/>
561 /// in <see cref="SceneObjectGroup.checkAtTargets"/>
562 /// via <see cref="SceneObjectGroup.ScheduleGroupForFullUpdate"/>,
563 /// <see cref="Scene.CheckAtTargets"/> via <see cref="Scene.Update"/>
564 /// </remarks>
565 public event ScriptAtTargetEvent OnScriptAtTargetEvent; 289 public event ScriptAtTargetEvent OnScriptAtTargetEvent;
566 290
567 public delegate void ScriptNotAtTargetEvent(uint localID); 291 public delegate void ScriptNotAtTargetEvent(uint localID);
568
569 /// <summary>
570 /// Triggered when an object has a motion target but has not arrived
571 /// within a tolerance distance.
572 /// </summary>
573 /// <remarks>
574 /// Triggered by <see cref="TriggerNotAtTargetEvent"/>
575 /// in <see cref="SceneObjectGroup.checkAtTargets"/>
576 /// via <see cref="SceneObjectGroup.ScheduleGroupForFullUpdate"/>,
577 /// <see cref="Scene.CheckAtTargets"/> via <see cref="Scene.Update"/>
578 /// </remarks>
579 public event ScriptNotAtTargetEvent OnScriptNotAtTargetEvent; 292 public event ScriptNotAtTargetEvent OnScriptNotAtTargetEvent;
580 293
581 public delegate void ScriptAtRotTargetEvent(uint localID, uint handle, Quaternion targetrot, Quaternion atrot); 294 public delegate void ScriptAtRotTargetEvent(uint localID, uint handle, Quaternion targetrot, Quaternion atrot);
582
583 /// <summary>
584 /// Triggered when an object has arrived within a tolerance rotation
585 /// of a rotation target.
586 /// </summary>
587 /// <remarks>
588 /// Triggered by <see cref="TriggerAtRotTargetEvent"/>
589 /// in <see cref="SceneObjectGroup.checkAtTargets"/>
590 /// via <see cref="SceneObjectGroup.ScheduleGroupForFullUpdate"/>,
591 /// <see cref="Scene.CheckAtTargets"/> via <see cref="Scene.Update"/>
592 /// </remarks>
593 public event ScriptAtRotTargetEvent OnScriptAtRotTargetEvent; 295 public event ScriptAtRotTargetEvent OnScriptAtRotTargetEvent;
594 296
595 public delegate void ScriptNotAtRotTargetEvent(uint localID); 297 public delegate void ScriptNotAtRotTargetEvent(uint localID);
596
597 /// <summary>
598 /// Triggered when an object has a rotation target but has not arrived
599 /// within a tolerance rotation.
600 /// </summary>
601 /// <remarks>
602 /// Triggered by <see cref="TriggerNotAtRotTargetEvent"/>
603 /// in <see cref="SceneObjectGroup.checkAtTargets"/>
604 /// via <see cref="SceneObjectGroup.ScheduleGroupForFullUpdate"/>,
605 /// <see cref="Scene.CheckAtTargets"/> via <see cref="Scene.Update"/>
606 /// </remarks>
607 public event ScriptNotAtRotTargetEvent OnScriptNotAtRotTargetEvent; 298 public event ScriptNotAtRotTargetEvent OnScriptNotAtRotTargetEvent;
608 299
609 public delegate void ScriptColliding(uint localID, ColliderArgs colliders); 300 public delegate void ScriptColliding(uint localID, ColliderArgs colliders);
610
611 /// <summary>
612 /// Triggered when a physical collision has started between a prim
613 /// and something other than the region terrain.
614 /// </summary>
615 /// <remarks>
616 /// Triggered by <see cref="TriggerScriptCollidingStart"/>
617 /// in <see cref="SceneObjectPart.SendCollisionEvent"/>
618 /// via <see cref="SceneObjectPart.PhysicsCollision"/>
619 /// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.OnCollisionUpdate"/>
620 /// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.SendCollisionUpdate"/>
621 /// </remarks>
622 public event ScriptColliding OnScriptColliderStart; 301 public event ScriptColliding OnScriptColliderStart;
623
624 /// <summary>
625 /// Triggered when something that previously collided with a prim has
626 /// not stopped colliding with it.
627 /// </summary>
628 /// <remarks>
629 /// <seealso cref="OnScriptColliderStart"/>
630 /// Triggered by <see cref="TriggerScriptColliding"/>
631 /// in <see cref="SceneObjectPart.SendCollisionEvent"/>
632 /// via <see cref="SceneObjectPart.PhysicsCollision"/>
633 /// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.OnCollisionUpdate"/>
634 /// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.SendCollisionUpdate"/>
635 /// </remarks>
636 public event ScriptColliding OnScriptColliding; 302 public event ScriptColliding OnScriptColliding;
637
638 /// <summary>
639 /// Triggered when something that previously collided with a prim has
640 /// stopped colliding with it.
641 /// </summary>
642 /// <remarks>
643 /// Triggered by <see cref="TriggerScriptCollidingEnd"/>
644 /// in <see cref="SceneObjectPart.SendCollisionEvent"/>
645 /// via <see cref="SceneObjectPart.PhysicsCollision"/>
646 /// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.OnCollisionUpdate"/>
647 /// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.SendCollisionUpdate"/>
648 /// </remarks>
649 public event ScriptColliding OnScriptCollidingEnd; 303 public event ScriptColliding OnScriptCollidingEnd;
650
651 /// <summary>
652 /// Triggered when a physical collision has started between an object
653 /// and the region terrain.
654 /// </summary>
655 /// <remarks>
656 /// Triggered by <see cref="TriggerScriptLandCollidingStart"/>
657 /// in <see cref="SceneObjectPart.SendLandCollisionEvent"/>
658 /// via <see cref="SceneObjectPart.PhysicsCollision"/>
659 /// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.OnCollisionUpdate"/>
660 /// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.SendCollisionUpdate"/>
661 /// </remarks>
662 public event ScriptColliding OnScriptLandColliderStart; 304 public event ScriptColliding OnScriptLandColliderStart;
663
664 /// <summary>
665 /// Triggered when an object that previously collided with the region
666 /// terrain has not yet stopped colliding with it.
667 /// </summary>
668 /// <remarks>
669 /// Triggered by <see cref="TriggerScriptLandColliding"/>
670 /// in <see cref="SceneObjectPart.SendLandCollisionEvent"/>
671 /// via <see cref="SceneObjectPart.PhysicsCollision"/>
672 /// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.OnCollisionUpdate"/>
673 /// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.SendCollisionUpdate"/>
674 /// </remarks>
675 public event ScriptColliding OnScriptLandColliding; 305 public event ScriptColliding OnScriptLandColliding;
676
677 /// <summary>
678 /// Triggered when an object that previously collided with the region
679 /// terrain has stopped colliding with it.
680 /// </summary>
681 /// <remarks>
682 /// Triggered by <see cref="TriggerScriptLandCollidingEnd"/>
683 /// in <see cref="SceneObjectPart.SendLandCollisionEvent"/>
684 /// via <see cref="SceneObjectPart.PhysicsCollision"/>
685 /// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.OnCollisionUpdate"/>
686 /// via <see cref="OpenSim.Region.Physics.Manager.PhysicsActor.SendCollisionUpdate"/>
687 /// </remarks>
688 public event ScriptColliding OnScriptLandColliderEnd; 306 public event ScriptColliding OnScriptLandColliderEnd;
689 307
690 public delegate void OnMakeChildAgentDelegate(ScenePresence presence); 308 public delegate void OnMakeChildAgentDelegate(ScenePresence presence);
691
692 /// <summary>
693 /// Triggered when an agent has been made a child agent of a scene.
694 /// </summary>
695 /// <remarks>
696 /// Triggered by <see cref="TriggerOnMakeChildAgent"/>
697 /// in <see cref="ScenePresence.MakeChildAgent"/>
698 /// via <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.CrossAgentToNewRegionAsync"/>,
699 /// <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.DoTeleport"/>,
700 /// <see cref="OpenSim.Region.CoreModules.InterGrid.KillAUser.ShutdownNoLogout"/>
701 /// </remarks>
702 public event OnMakeChildAgentDelegate OnMakeChildAgent; 309 public event OnMakeChildAgentDelegate OnMakeChildAgent;
703 310
704 public delegate void OnSaveNewWindlightProfileDelegate(); 311 public delegate void OnSaveNewWindlightProfileDelegate();
705 public delegate void OnSendNewWindlightProfileTargetedDelegate(RegionLightShareData wl, UUID user); 312 public delegate void OnSendNewWindlightProfileTargetedDelegate(RegionLightShareData wl, UUID user);
706 313
707 /// <summary> 314 /// <summary>
708 /// Triggered after the grunt work for adding a root agent to a
709 /// scene has been performed (resuming attachment scripts, physics,
710 /// animations etc.)
711 /// </summary>
712 /// <remarks>
713 /// This event is on the critical path for transferring an avatar from one region to another. Try and do 315 /// This event is on the critical path for transferring an avatar from one region to another. Try and do
714 /// as little work on this event as possible, or do work asynchronously. 316 /// as little work on this event as possible, or do work asynchronously.
715 /// Triggered after <see cref="OnSetRootAgentScene"/> 317 /// </summary>
716 /// by <see cref="TriggerOnMakeRootAgent"/>
717 /// in <see cref="ScenePresence.MakeRootAgent"/>
718 /// via <see cref="Scene.AgentCrossing"/>
719 /// and <see cref="ScenePresence.CompleteMovement"/>
720 /// </remarks>
721 public event Action<ScenePresence> OnMakeRootAgent; 318 public event Action<ScenePresence> OnMakeRootAgent;
722 319
723 public event OnSendNewWindlightProfileTargetedDelegate OnSendNewWindlightProfileTargeted; 320 public event OnSendNewWindlightProfileTargetedDelegate OnSendNewWindlightProfileTargeted;
@@ -743,17 +340,9 @@ namespace OpenSim.Region.Framework.Scenes
743 public event AvatarKillData OnAvatarKilled; 340 public event AvatarKillData OnAvatarKilled;
744 public delegate void AvatarKillData(uint KillerLocalID, ScenePresence avatar); 341 public delegate void AvatarKillData(uint KillerLocalID, ScenePresence avatar);
745 342
746 /* 343// public delegate void ScriptTimerEvent(uint localID, double timerinterval);
747 public delegate void ScriptTimerEvent(uint localID, double timerinterval); 344
748 /// <summary> 345// public event ScriptTimerEvent OnScriptTimerEvent;
749 /// Used to be triggered when the LSL timer event fires.
750 /// </summary>
751 /// <remarks>
752 /// Triggered by <see cref="TriggerTimerEvent"/>
753 /// via <see cref="SceneObjectPart.handleTimerAccounting"/>
754 /// </remarks>
755 public event ScriptTimerEvent OnScriptTimerEvent;
756 */
757 346
758 public delegate void EstateToolsSunUpdate(ulong regionHandle, bool FixedTime, bool EstateSun, float LindenHour); 347 public delegate void EstateToolsSunUpdate(ulong regionHandle, bool FixedTime, bool EstateSun, float LindenHour);
759 public delegate void GetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID); 348 public delegate void GetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID);
@@ -763,27 +352,12 @@ namespace OpenSim.Region.Framework.Scenes
763 /// <summary> 352 /// <summary>
764 /// Triggered when an object is added to the scene. 353 /// Triggered when an object is added to the scene.
765 /// </summary> 354 /// </summary>
766 /// <remarks>
767 /// Triggered by <see cref="TriggerObjectAddedToScene"/>
768 /// in <see cref="Scene.AddNewSceneObject"/>,
769 /// <see cref="Scene.DuplicateObject"/>,
770 /// <see cref="Scene.doObjectDuplicateOnRay"/>
771 /// </remarks>
772 public event Action<SceneObjectGroup> OnObjectAddedToScene; 355 public event Action<SceneObjectGroup> OnObjectAddedToScene;
773 356
774 /// <summary> 357 /// <summary>
775 /// Delegate for <see cref="OnObjectBeingRemovedFromScene"/>
776 /// </summary>
777 /// <param name="obj">The object being removed from the scene</param>
778 public delegate void ObjectBeingRemovedFromScene(SceneObjectGroup obj);
779
780 /// <summary>
781 /// Triggered when an object is removed from the scene. 358 /// Triggered when an object is removed from the scene.
782 /// </summary> 359 /// </summary>
783 /// <remarks> 360 public delegate void ObjectBeingRemovedFromScene(SceneObjectGroup obj);
784 /// Triggered by <see cref="TriggerObjectBeingRemovedFromScene"/>
785 /// in <see cref="Scene.DeleteSceneObject"/>
786 /// </remarks>
787 public event ObjectBeingRemovedFromScene OnObjectBeingRemovedFromScene; 361 public event ObjectBeingRemovedFromScene OnObjectBeingRemovedFromScene;
788 362
789 public delegate void NoticeNoLandDataFromStorage(); 363 public delegate void NoticeNoLandDataFromStorage();
@@ -799,20 +373,6 @@ namespace OpenSim.Region.Framework.Scenes
799 public event RequestParcelPrimCountUpdate OnRequestParcelPrimCountUpdate; 373 public event RequestParcelPrimCountUpdate OnRequestParcelPrimCountUpdate;
800 374
801 public delegate void ParcelPrimCountTainted(); 375 public delegate void ParcelPrimCountTainted();
802
803 /// <summary>
804 /// Triggered when the parcel prim count has been altered.
805 /// </summary>
806 /// <remarks>
807 /// Triggered by <see cref="TriggerParcelPrimCountTainted"/> in
808 /// <see cref="OpenSim.Region.CoreModules.Avatar.Attachments.AttachmentsModule.DetachSingleAttachmentToGround"/>,
809 /// <see cref="OpenSim.Region.CoreModules.Avatar.Attachments.AttachmentsModule.AttachToAgent"/>,
810 /// <see cref="Scene.DeleteSceneObject"/>,
811 /// <see cref="Scene.SelectPrim"/>,
812 /// <see cref="Scene.DeselectPrim"/>,
813 /// <see cref="SceneObjectGroup.UpdatePrimFlags"/>,
814 /// <see cref="SceneObjectGroup.AbsolutePosition"/>
815 /// </remarks>
816 public event ParcelPrimCountTainted OnParcelPrimCountTainted; 376 public event ParcelPrimCountTainted OnParcelPrimCountTainted;
817 public event GetScriptRunning OnGetScriptRunning; 377 public event GetScriptRunning OnGetScriptRunning;
818 378
@@ -876,7 +436,7 @@ namespace OpenSim.Region.Framework.Scenes
876 /// the scripts may not have started yet 436 /// the scripts may not have started yet
877 /// Message is non empty string if there were problems loading the oar file 437 /// Message is non empty string if there were problems loading the oar file
878 /// </summary> 438 /// </summary>
879 public delegate void OarFileLoaded(Guid guid, List<UUID> loadedScenes, string message); 439 public delegate void OarFileLoaded(Guid guid, string message);
880 public event OarFileLoaded OnOarFileLoaded; 440 public event OarFileLoaded OnOarFileLoaded;
881 441
882 /// <summary> 442 /// <summary>
@@ -929,13 +489,10 @@ namespace OpenSim.Region.Framework.Scenes
929 /// <param name="copy"></param> 489 /// <param name="copy"></param>
930 /// <param name="original"></param> 490 /// <param name="original"></param>
931 /// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param> 491 /// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param>
932 /// <remarks>
933 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.SceneObjectPart.Copy"/>
934 /// </remarks>
935 public event SceneObjectPartCopyDelegate OnSceneObjectPartCopy; 492 public event SceneObjectPartCopyDelegate OnSceneObjectPartCopy;
936 public delegate void SceneObjectPartCopyDelegate(SceneObjectPart copy, SceneObjectPart original, bool userExposed); 493 public delegate void SceneObjectPartCopyDelegate(SceneObjectPart copy, SceneObjectPart original, bool userExposed);
937 494
938 public delegate void SceneObjectPartUpdated(SceneObjectPart sop, bool full); 495 public delegate void SceneObjectPartUpdated(SceneObjectPart sop);
939 public event SceneObjectPartUpdated OnSceneObjectPartUpdated; 496 public event SceneObjectPartUpdated OnSceneObjectPartUpdated;
940 497
941 public delegate void ScenePresenceUpdated(ScenePresence sp); 498 public delegate void ScenePresenceUpdated(ScenePresence sp);
@@ -973,28 +530,9 @@ namespace OpenSim.Region.Framework.Scenes
973 public event PrimsLoaded OnPrimsLoaded; 530 public event PrimsLoaded OnPrimsLoaded;
974 531
975 public delegate void TeleportStart(IClientAPI client, GridRegion destination, GridRegion finalDestination, uint teleportFlags, bool gridLogout); 532 public delegate void TeleportStart(IClientAPI client, GridRegion destination, GridRegion finalDestination, uint teleportFlags, bool gridLogout);
976
977 /// <summary>
978 /// Triggered when a teleport starts
979 /// </summary>
980 /// <remarks>
981 /// Triggered by <see cref="TriggerTeleportStart"/>
982 /// in <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.CreateAgent"/>
983 /// and <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.HGEntityTransferModule.CreateAgent"/>
984 /// via <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.DoTeleport"/>
985 /// </remarks>
986 public event TeleportStart OnTeleportStart; 533 public event TeleportStart OnTeleportStart;
987 534
988 public delegate void TeleportFail(IClientAPI client, bool gridLogout); 535 public delegate void TeleportFail(IClientAPI client, bool gridLogout);
989
990 /// <summary>
991 /// Trigered when a teleport fails.
992 /// </summary>
993 /// <remarks>
994 /// Triggered by <see cref="TriggerTeleportFail"/>
995 /// in <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.Fail"/>
996 /// via <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.DoTeleport"/>
997 /// </remarks>
998 public event TeleportFail OnTeleportFail; 536 public event TeleportFail OnTeleportFail;
999 537
1000 public class MoneyTransferArgs : EventArgs 538 public class MoneyTransferArgs : EventArgs
@@ -1002,9 +540,7 @@ namespace OpenSim.Region.Framework.Scenes
1002 public UUID sender; 540 public UUID sender;
1003 public UUID receiver; 541 public UUID receiver;
1004 542
1005 /// <summary> 543 // Always false. The SL protocol sucks.
1006 /// Always false. The SL protocol sucks.
1007 /// </summary>
1008 public bool authenticated = false; 544 public bool authenticated = false;
1009 545
1010 public int amount; 546 public int amount;
@@ -1061,29 +597,8 @@ namespace OpenSim.Region.Framework.Scenes
1061 597
1062 public delegate void LandBuy(Object sender, LandBuyArgs e); 598 public delegate void LandBuy(Object sender, LandBuyArgs e);
1063 599
1064 /// <summary>
1065 /// Triggered when an attempt to transfer grid currency occurs
1066 /// </summary>
1067 /// <remarks>
1068 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.ProcessMoneyTransferRequest"/>
1069 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.SubscribeToClientGridEvents"/>
1070 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.SubscribeToClientEvents"/>
1071 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/>
1072 /// </remarks>
1073 public event MoneyTransferEvent OnMoneyTransfer; 600 public event MoneyTransferEvent OnMoneyTransfer;
1074
1075 /// <summary>
1076 /// Triggered after after <see cref="OnValidateLandBuy"/>
1077 /// </summary>
1078 public event LandBuy OnLandBuy; 601 public event LandBuy OnLandBuy;
1079
1080 /// <summary>
1081 /// Triggered to allow or prevent a real estate transaction
1082 /// </summary>
1083 /// <remarks>
1084 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.ProcessParcelBuy"/>
1085 /// <seealso cref="OpenSim.Region.OptionalModules.World.MoneyModule.SampleMoneyModule.ValidateLandBuy"/>
1086 /// </remarks>
1087 public event LandBuy OnValidateLandBuy; 602 public event LandBuy OnValidateLandBuy;
1088 603
1089 public void TriggerOnAttach(uint localID, UUID itemID, UUID avatarID) 604 public void TriggerOnAttach(uint localID, UUID itemID, UUID avatarID)
@@ -2520,11 +2035,7 @@ namespace OpenSim.Region.Framework.Scenes
2520 } 2035 }
2521 } 2036 }
2522 2037
2523 /// <summary> 2038 // this lets us keep track of nasty script events like timer, etc.
2524 /// this lets us keep track of nasty script events like timer, etc.
2525 /// </summary>
2526 /// <param name="objLocalID"></param>
2527 /// <param name="Interval"></param>
2528 public void TriggerTimerEvent(uint objLocalID, double Interval) 2039 public void TriggerTimerEvent(uint objLocalID, double Interval)
2529 { 2040 {
2530 throw new NotImplementedException("TriggerTimerEvent was thought to be not used anymore and the registration for the event from scene object part has been commented out due to a memory leak"); 2041 throw new NotImplementedException("TriggerTimerEvent was thought to be not used anymore and the registration for the event from scene object part has been commented out due to a memory leak");
@@ -2586,7 +2097,7 @@ namespace OpenSim.Region.Framework.Scenes
2586 return 6; 2097 return 6;
2587 } 2098 }
2588 2099
2589 public void TriggerOarFileLoaded(Guid requestId, List<UUID> loadedScenes, string message) 2100 public void TriggerOarFileLoaded(Guid requestId, string message)
2590 { 2101 {
2591 OarFileLoaded handlerOarFileLoaded = OnOarFileLoaded; 2102 OarFileLoaded handlerOarFileLoaded = OnOarFileLoaded;
2592 if (handlerOarFileLoaded != null) 2103 if (handlerOarFileLoaded != null)
@@ -2595,7 +2106,7 @@ namespace OpenSim.Region.Framework.Scenes
2595 { 2106 {
2596 try 2107 try
2597 { 2108 {
2598 d(requestId, loadedScenes, message); 2109 d(requestId, message);
2599 } 2110 }
2600 catch (Exception e) 2111 catch (Exception e)
2601 { 2112 {
@@ -2880,7 +2391,7 @@ namespace OpenSim.Region.Framework.Scenes
2880 } 2391 }
2881 } 2392 }
2882 2393
2883 public void TriggerSceneObjectPartUpdated(SceneObjectPart sop, bool full) 2394 public void TriggerSceneObjectPartUpdated(SceneObjectPart sop)
2884 { 2395 {
2885 SceneObjectPartUpdated handler = OnSceneObjectPartUpdated; 2396 SceneObjectPartUpdated handler = OnSceneObjectPartUpdated;
2886 if (handler != null) 2397 if (handler != null)
@@ -2889,7 +2400,7 @@ namespace OpenSim.Region.Framework.Scenes
2889 { 2400 {
2890 try 2401 try
2891 { 2402 {
2892 d(sop, full); 2403 d(sop);
2893 } 2404 }
2894 catch (Exception e) 2405 catch (Exception e)
2895 { 2406 {
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 6208a57..906c1ee 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -93,7 +93,7 @@ namespace OpenSim.Region.Framework.Scenes
93 /// </summary> 93 /// </summary>
94 public void StartScripts() 94 public void StartScripts()
95 { 95 {
96// m_log.InfoFormat("[SCENE]: Starting scripts in {0}, please wait.", RegionInfo.RegionName); 96 m_log.InfoFormat("[SCENE]: Starting scripts in {0}, please wait.", RegionInfo.RegionName);
97 97
98 IScriptModule[] engines = RequestModuleInterfaces<IScriptModule>(); 98 IScriptModule[] engines = RequestModuleInterfaces<IScriptModule>();
99 99
@@ -1469,7 +1469,7 @@ namespace OpenSim.Region.Framework.Scenes
1469 return newFolderID; 1469 return newFolderID;
1470 } 1470 }
1471 1471
1472 public void SendInventoryUpdate(IClientAPI client, InventoryFolderBase folder, bool fetchFolders, bool fetchItems) 1472 private void SendInventoryUpdate(IClientAPI client, InventoryFolderBase folder, bool fetchFolders, bool fetchItems)
1473 { 1473 {
1474 if (folder == null) 1474 if (folder == null)
1475 return; 1475 return;
@@ -1997,9 +1997,6 @@ namespace OpenSim.Region.Framework.Scenes
1997 // If child prims have invalid perms, fix them 1997 // If child prims have invalid perms, fix them
1998 grp.AdjustChildPrimPermissions(); 1998 grp.AdjustChildPrimPermissions();
1999 1999
2000 // If child prims have invalid perms, fix them
2001 grp.AdjustChildPrimPermissions();
2002
2003 if (remoteClient == null) 2000 if (remoteClient == null)
2004 { 2001 {
2005 // Autoreturn has a null client. Nothing else does. So 2002 // Autoreturn has a null client. Nothing else does. So
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index ce6415a..e970543 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -38,20 +38,8 @@ namespace OpenSim.Region.Framework.Scenes
38{ 38{
39 public partial class Scene 39 public partial class Scene
40 { 40 {
41 /// <summary>
42 /// Send chat to listeners.
43 /// </summary>
44 /// <param name='message'></param>
45 /// <param name='type'>/param>
46 /// <param name='channel'></param>
47 /// <param name='fromPos'></param>
48 /// <param name='fromName'></param>
49 /// <param name='fromID'></param>
50 /// <param name='targetID'></param>
51 /// <param name='fromAgent'></param>
52 /// <param name='broadcast'></param>
53 public void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName, 41 public void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName,
54 UUID fromID, UUID targetID, bool fromAgent, bool broadcast) 42 UUID fromID, bool fromAgent, bool broadcast, UUID destination)
55 { 43 {
56 OSChatMessage args = new OSChatMessage(); 44 OSChatMessage args = new OSChatMessage();
57 45
@@ -61,7 +49,7 @@ namespace OpenSim.Region.Framework.Scenes
61 args.Position = fromPos; 49 args.Position = fromPos;
62 args.SenderUUID = fromID; 50 args.SenderUUID = fromID;
63 args.Scene = this; 51 args.Scene = this;
64 args.Destination = targetID; 52 args.Destination = destination;
65 53
66 if (fromAgent) 54 if (fromAgent)
67 { 55 {
@@ -78,10 +66,6 @@ namespace OpenSim.Region.Framework.Scenes
78 args.From = fromName; 66 args.From = fromName;
79 //args. 67 //args.
80 68
81// m_log.DebugFormat(
82// "[SCENE]: Sending message {0} on channel {1}, type {2} from {3}, broadcast {4}",
83// args.Message.Replace("\n", "\\n"), args.Channel, args.Type, fromName, broadcast);
84
85 if (broadcast) 69 if (broadcast)
86 EventManager.TriggerOnChatBroadcast(this, args); 70 EventManager.TriggerOnChatBroadcast(this, args);
87 else 71 else
@@ -91,7 +75,7 @@ namespace OpenSim.Region.Framework.Scenes
91 protected void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName, 75 protected void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName,
92 UUID fromID, bool fromAgent, bool broadcast) 76 UUID fromID, bool fromAgent, bool broadcast)
93 { 77 {
94 SimChat(message, type, channel, fromPos, fromName, fromID, UUID.Zero, fromAgent, broadcast); 78 SimChat(message, type, channel, fromPos, fromName, fromID, fromAgent, broadcast, UUID.Zero);
95 } 79 }
96 80
97 /// <summary> 81 /// <summary>
@@ -559,7 +543,7 @@ namespace OpenSim.Region.Framework.Scenes
559 if (!InventoryService.AddFolder(folder)) 543 if (!InventoryService.AddFolder(folder))
560 { 544 {
561 m_log.WarnFormat( 545 m_log.WarnFormat(
562 "[AGENT INVENTORY]: Failed to create folder for user {0} {1}", 546 "[AGENT INVENTORY]: Failed to move create folder for user {0} {1}",
563 remoteClient.Name, remoteClient.AgentId); 547 remoteClient.Name, remoteClient.AgentId);
564 } 548 }
565 } 549 }
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 2543333..649d545 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -80,11 +80,6 @@ namespace OpenSim.Region.Framework.Scenes
80 public SynchronizeSceneHandler SynchronizeScene; 80 public SynchronizeSceneHandler SynchronizeScene;
81 81
82 /// <summary> 82 /// <summary>
83 /// Used to prevent simultaneous calls to RemoveClient() for the same agent from interfering with each other.
84 /// </summary>
85 private object m_removeClientLock = new object();
86
87 /// <summary>
88 /// Statistical information for this scene. 83 /// Statistical information for this scene.
89 /// </summary> 84 /// </summary>
90 public SimStatsReporter StatsReporter { get; private set; } 85 public SimStatsReporter StatsReporter { get; private set; }
@@ -108,31 +103,8 @@ namespace OpenSim.Region.Framework.Scenes
108 /// </summary> 103 /// </summary>
109 public bool CollidablePrims { get; private set; } 104 public bool CollidablePrims { get; private set; }
110 105
111 /// <summary>
112 /// Minimum value of the size of a non-physical prim in each axis
113 /// </summary>
114 public float m_minNonphys = 0.001f;
115
116 /// <summary>
117 /// Maximum value of the size of a non-physical prim in each axis
118 /// </summary>
119 public float m_maxNonphys = 256; 106 public float m_maxNonphys = 256;
120
121 /// <summary>
122 /// Minimum value of the size of a physical prim in each axis
123 /// </summary>
124 public float m_minPhys = 0.01f;
125
126 /// <summary>
127 /// Maximum value of the size of a physical prim in each axis
128 /// </summary>
129 public float m_maxPhys = 10; 107 public float m_maxPhys = 10;
130
131 /// <summary>
132 /// Max prims an object will hold
133 /// </summary>
134 public int m_linksetCapacity = 0;
135
136 public bool m_clampPrimSize; 108 public bool m_clampPrimSize;
137 public bool m_trustBinaries; 109 public bool m_trustBinaries;
138 public bool m_allowScriptCrossings; 110 public bool m_allowScriptCrossings;
@@ -313,31 +285,6 @@ namespace OpenSim.Region.Framework.Scenes
313 } 285 }
314 private volatile bool m_shuttingDown; 286 private volatile bool m_shuttingDown;
315 287
316 /// <summary>
317 /// Is the scene active?
318 /// </summary>
319 /// <remarks>
320 /// If false, maintenance and update loops are not being run. Updates can still be triggered manually if
321 /// the scene is not active.
322 /// </remarks>
323 public bool Active
324 {
325 get { return m_active; }
326 set
327 {
328 if (value)
329 {
330 if (!m_active)
331 Start();
332 }
333 else
334 {
335 m_active = false;
336 }
337 }
338 }
339 private volatile bool m_active;
340
341// private int m_lastUpdate; 288// private int m_lastUpdate;
342 private bool m_firstHeartbeat = true; 289 private bool m_firstHeartbeat = true;
343 290
@@ -799,24 +746,12 @@ namespace OpenSim.Region.Framework.Scenes
799 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true); 746 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true);
800 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true); 747 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true);
801 748
802 m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys); 749 m_maxNonphys = startupConfig.GetFloat("NonphysicalPrimMax", m_maxNonphys);
803 if (RegionInfo.NonphysPrimMin > 0)
804 {
805 m_minNonphys = RegionInfo.NonphysPrimMin;
806 }
807
808 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys);
809 if (RegionInfo.NonphysPrimMax > 0) 750 if (RegionInfo.NonphysPrimMax > 0)
810 { 751 {
811 m_maxNonphys = RegionInfo.NonphysPrimMax; 752 m_maxNonphys = RegionInfo.NonphysPrimMax;
812 } 753 }
813 754
814 m_minPhys = startupConfig.GetFloat("PhysicalPrimMin", m_minPhys);
815 if (RegionInfo.PhysPrimMin > 0)
816 {
817 m_minPhys = RegionInfo.PhysPrimMin;
818 }
819
820 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys); 755 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys);
821 756
822 if (RegionInfo.PhysPrimMax > 0) 757 if (RegionInfo.PhysPrimMax > 0)
@@ -824,12 +759,6 @@ namespace OpenSim.Region.Framework.Scenes
824 m_maxPhys = RegionInfo.PhysPrimMax; 759 m_maxPhys = RegionInfo.PhysPrimMax;
825 } 760 }
826 761
827 m_linksetCapacity = startupConfig.GetInt("LinksetPrims", m_linksetCapacity);
828 if (RegionInfo.LinksetCapacity > 0)
829 {
830 m_linksetCapacity = RegionInfo.LinksetCapacity;
831 }
832
833 SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest"); 762 SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest");
834 TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false); 763 TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false);
835 764
@@ -855,6 +784,13 @@ namespace OpenSim.Region.Framework.Scenes
855 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); 784 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
856 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine); 785 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine);
857 786
787 IConfig packetConfig = m_config.Configs["PacketPool"];
788 if (packetConfig != null)
789 {
790 PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true);
791 PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true);
792 }
793
858 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); 794 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
859 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion); 795 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
860 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false); 796 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false);
@@ -918,8 +854,6 @@ namespace OpenSim.Region.Framework.Scenes
918 } 854 }
919 855
920 // FIXME: Ultimately this should be in a module. 856 // FIXME: Ultimately this should be in a module.
921 SendPeriodicAppearanceUpdates = true;
922
923 IConfig appearanceConfig = m_config.Configs["Appearance"]; 857 IConfig appearanceConfig = m_config.Configs["Appearance"];
924 if (appearanceConfig != null) 858 if (appearanceConfig != null)
925 { 859 {
@@ -1217,14 +1151,6 @@ namespace OpenSim.Region.Framework.Scenes
1217 1151
1218 public void SetSceneCoreDebug(Dictionary<string, string> options) 1152 public void SetSceneCoreDebug(Dictionary<string, string> options)
1219 { 1153 {
1220 if (options.ContainsKey("active"))
1221 {
1222 bool active;
1223
1224 if (bool.TryParse(options["active"], out active))
1225 Active = active;
1226 }
1227
1228 if (options.ContainsKey("scripting")) 1154 if (options.ContainsKey("scripting"))
1229 { 1155 {
1230 bool enableScripts = true; 1156 bool enableScripts = true;
@@ -1300,12 +1226,6 @@ namespace OpenSim.Region.Framework.Scenes
1300 // This is the method that shuts down the scene. 1226 // This is the method that shuts down the scene.
1301 public override void Close() 1227 public override void Close()
1302 { 1228 {
1303 if (m_shuttingDown)
1304 {
1305 m_log.WarnFormat("[SCENE]: Ignoring close request because already closing {0}", Name);
1306 return;
1307 }
1308
1309 m_log.InfoFormat("[SCENE]: Closing down the single simulator: {0}", RegionInfo.RegionName); 1229 m_log.InfoFormat("[SCENE]: Closing down the single simulator: {0}", RegionInfo.RegionName);
1310 1230
1311 StatsReporter.Close(); 1231 StatsReporter.Close();
@@ -1352,14 +1272,6 @@ namespace OpenSim.Region.Framework.Scenes
1352 m_log.Debug("[SCENE]: Graph close"); 1272 m_log.Debug("[SCENE]: Graph close");
1353 m_sceneGraph.Close(); 1273 m_sceneGraph.Close();
1354 1274
1355 if (!GridService.DeregisterRegion(RegionInfo.RegionID))
1356 m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", Name);
1357
1358 base.Close();
1359
1360 // XEngine currently listens to the EventManager.OnShutdown event to trigger script stop and persistence.
1361 // Therefore. we must dispose of the PhysicsScene after this to prevent a window where script code can
1362 // attempt to reference a null or disposed physics scene.
1363 if (PhysicsScene != null) 1275 if (PhysicsScene != null)
1364 { 1276 {
1365 m_log.Debug("[SCENE]: Dispose Physics"); 1277 m_log.Debug("[SCENE]: Dispose Physics");
@@ -1369,6 +1281,13 @@ namespace OpenSim.Region.Framework.Scenes
1369 phys.Dispose(); 1281 phys.Dispose();
1370 phys = null; 1282 phys = null;
1371 } 1283 }
1284
1285 if (!GridService.DeregisterRegion(RegionInfo.RegionID))
1286 m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", Name);
1287
1288 // call the base class Close method.
1289 m_log.Debug("[SCENE]: Base close");
1290 base.Close();
1372 } 1291 }
1373 1292
1374 /// <summary> 1293 /// <summary>
@@ -1376,8 +1295,6 @@ namespace OpenSim.Region.Framework.Scenes
1376 /// </summary> 1295 /// </summary>
1377 public void Start() 1296 public void Start()
1378 { 1297 {
1379 m_active = true;
1380
1381// m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName); 1298// m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName);
1382 1299
1383 //m_heartbeatTimer.Enabled = true; 1300 //m_heartbeatTimer.Enabled = true;
@@ -1437,7 +1354,7 @@ namespace OpenSim.Region.Framework.Scenes
1437 #region Update Methods 1354 #region Update Methods
1438 1355
1439 /// <summary> 1356 /// <summary>
1440 /// Activate the various loops necessary to continually update the scene. 1357 /// Performs per-frame updates regularly
1441 /// </summary> 1358 /// </summary>
1442 private void Heartbeat() 1359 private void Heartbeat()
1443 { 1360 {
@@ -1494,7 +1411,7 @@ namespace OpenSim.Region.Framework.Scenes
1494 List<Vector3> coarseLocations; 1411 List<Vector3> coarseLocations;
1495 List<UUID> avatarUUIDs; 1412 List<UUID> avatarUUIDs;
1496 1413
1497 while (!m_shuttingDown && ((endRun == null && Active) || MaintenanceRun < endRun)) 1414 while (!m_shuttingDown && (endRun == null || MaintenanceRun < endRun))
1498 { 1415 {
1499 runtc = Util.EnvironmentTickCount(); 1416 runtc = Util.EnvironmentTickCount();
1500 ++MaintenanceRun; 1417 ++MaintenanceRun;
@@ -1556,7 +1473,7 @@ namespace OpenSim.Region.Framework.Scenes
1556 int sleepMS; 1473 int sleepMS;
1557 int framestart; 1474 int framestart;
1558 1475
1559 while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame)) 1476 while (!m_shuttingDown && (endFrame == null || Frame < endFrame))
1560 { 1477 {
1561 framestart = Util.EnvironmentTickCount(); 1478 framestart = Util.EnvironmentTickCount();
1562 ++Frame; 1479 ++Frame;
@@ -1755,19 +1672,15 @@ namespace OpenSim.Region.Framework.Scenes
1755 1672
1756 private void CheckAtTargets() 1673 private void CheckAtTargets()
1757 { 1674 {
1758 List<SceneObjectGroup> objs = null; 1675 List<SceneObjectGroup> objs = new List<SceneObjectGroup>();
1759
1760 lock (m_groupsWithTargets) 1676 lock (m_groupsWithTargets)
1761 { 1677 {
1762 if (m_groupsWithTargets.Count != 0) 1678 foreach (SceneObjectGroup grp in m_groupsWithTargets.Values)
1763 objs = new List<SceneObjectGroup>(m_groupsWithTargets.Values); 1679 objs.Add(grp);
1764 } 1680 }
1765 1681
1766 if (objs != null) 1682 foreach (SceneObjectGroup entry in objs)
1767 { 1683 entry.checkAtTargets();
1768 foreach (SceneObjectGroup entry in objs)
1769 entry.checkAtTargets();
1770 }
1771 } 1684 }
1772 1685
1773 /// <summary> 1686 /// <summary>
@@ -2280,14 +2193,10 @@ namespace OpenSim.Region.Framework.Scenes
2280 public bool AddRestoredSceneObject( 2193 public bool AddRestoredSceneObject(
2281 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 2194 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
2282 { 2195 {
2283 if (m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates)) 2196 bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates);
2284 { 2197 if (result)
2285 sceneObject.IsDeleted = false; 2198 sceneObject.IsDeleted = false;
2286 EventManager.TriggerObjectAddedToScene(sceneObject); 2199 return result;
2287 return true;
2288 }
2289
2290 return false;
2291 } 2200 }
2292 2201
2293 /// <summary> 2202 /// <summary>
@@ -2928,89 +2837,77 @@ namespace OpenSim.Region.Framework.Scenes
2928 2837
2929 public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type) 2838 public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type)
2930 { 2839 {
2931 ScenePresence sp;
2932 bool vialogin;
2933
2934 // Validation occurs in LLUDPServer 2840 // Validation occurs in LLUDPServer
2935 //
2936 // XXX: A race condition exists here where two simultaneous calls to AddNewClient can interfere with
2937 // each other. In practice, this does not currently occur in the code.
2938 AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); 2841 AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode);
2939 2842
2940 // We lock here on AgentCircuitData to prevent a race condition between the thread adding a new connection 2843 bool vialogin
2941 // and a simultaneous one that removes it (as can happen if the client is closed at a particular point 2844 = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0
2942 // whilst connecting). 2845 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2943 //
2944 // It would be easier to lock across all NewUserConnection(), AddNewClient() and
2945 // RemoveClient() calls for all agents, but this would allow a slow call (e.g. because of slow service
2946 // response in some module listening to AddNewClient()) from holding up unrelated agent calls.
2947 //
2948 // In practice, the lock (this) in LLUDPServer.AddNewClient() currently lock across all
2949 // AddNewClient() operations (though not other ops).
2950 // In the future this can be relieved once locking per agent (not necessarily on AgentCircuitData) is improved.
2951 lock (aCircuit)
2952 {
2953 vialogin
2954 = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0
2955 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2956
2957 CheckHeartbeat();
2958
2959 sp = GetScenePresence(client.AgentId);
2960 2846
2961 // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this 2847 CheckHeartbeat();
2962 // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause 2848
2963 // other problems, and possible the code calling AddNewClient() should ensure that no client is already 2849 ScenePresence sp = GetScenePresence(client.AgentId);
2964 // connected. 2850
2965 if (sp == null) 2851 // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this
2966 { 2852 // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause
2967 m_log.DebugFormat( 2853 // other problems, and possible the code calling AddNewClient() should ensure that no client is already
2968 "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", 2854 // connected.
2969 client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); 2855 if (sp == null)
2970 2856 {
2971 m_clientManager.Add(client); 2857 m_log.DebugFormat(
2972 SubscribeToClientEvents(client); 2858 "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}",
2973 2859 client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos);
2974 sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type); 2860
2975 m_eventManager.TriggerOnNewPresence(sp); 2861 m_clientManager.Add(client);
2976 2862 SubscribeToClientEvents(client);
2977 sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags; 2863
2978 2864 sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type);
2979 // The first agent upon login is a root agent by design. 2865 m_eventManager.TriggerOnNewPresence(sp);
2980 // For this agent we will have to rez the attachments. 2866
2981 // All other AddNewClient calls find aCircuit.child to be true. 2867 sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags;
2982 if (aCircuit.child == false) 2868
2983 { 2869 // The first agent upon login is a root agent by design.
2984 // We have to set SP to be a root agent here so that SP.MakeRootAgent() will later not try to 2870 // For this agent we will have to rez the attachments.
2985 // start the scripts again (since this is done in RezAttachments()). 2871 // All other AddNewClient calls find aCircuit.child to be true.
2986 // XXX: This is convoluted. 2872 if (aCircuit.child == false)
2987 sp.IsChildAgent = false;
2988
2989 if (AttachmentsModule != null)
2990 Util.FireAndForget(delegate(object o) { AttachmentsModule.RezAttachments(sp); });
2991 }
2992 }
2993 else
2994 { 2873 {
2995 m_log.WarnFormat( 2874 // We have to set SP to be a root agent here so that SP.MakeRootAgent() will later not try to
2996 "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", 2875 // start the scripts again (since this is done in RezAttachments()).
2997 sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); 2876 // XXX: This is convoluted.
2998 } 2877 sp.IsChildAgent = false;
2999
3000 // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the
3001 // client is for a root or child agent.
3002 client.SceneAgent = sp;
3003 2878
3004 // Cache the user's name 2879 if (AttachmentsModule != null)
3005 CacheUserName(sp, aCircuit); 2880 Util.FireAndForget(delegate(object o) { AttachmentsModule.RezAttachments(sp); });
3006 2881 }
3007 EventManager.TriggerOnNewClient(client); 2882 }
3008 if (vialogin) 2883 else
3009 EventManager.TriggerOnClientLogin(client); 2884 {
2885 m_log.WarnFormat(
2886 "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence",
2887 sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName);
3010 } 2888 }
3011 2889
2890 // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the
2891 // client is for a root or child agent.
2892 client.SceneAgent = sp;
2893
3012 m_LastLogin = Util.EnvironmentTickCount(); 2894 m_LastLogin = Util.EnvironmentTickCount();
3013 2895
2896 // Cache the user's name
2897 CacheUserName(sp, aCircuit);
2898
2899 EventManager.TriggerOnNewClient(client);
2900 if (vialogin)
2901 {
2902 EventManager.TriggerOnClientLogin(client);
2903 // Send initial parcel data
2904/* this is done on TriggerOnNewClient by landmanegement respective event handler
2905 Vector3 pos = sp.AbsolutePosition;
2906 ILandObject land = LandChannel.GetLandObject(pos.X, pos.Y);
2907 land.SendLandUpdateToClient(client);
2908*/
2909 }
2910
3014 return sp; 2911 return sp;
3015 } 2912 }
3016 2913
@@ -3550,132 +3447,110 @@ namespace OpenSim.Region.Framework.Scenes
3550 { 3447 {
3551// CheckHeartbeat(); 3448// CheckHeartbeat();
3552 bool isChildAgent = false; 3449 bool isChildAgent = false;
3553 AgentCircuitData acd; 3450 ScenePresence avatar = GetScenePresence(agentID);
3554 3451
3555 lock (m_removeClientLock) 3452 if (avatar == null)
3556 { 3453 {
3557 acd = m_authenticateHandler.GetAgentCircuitData(agentID); 3454 m_log.WarnFormat(
3455 "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID);
3558 3456
3559 if (acd == null) 3457 return;
3560 {
3561 m_log.ErrorFormat("[SCENE]: No agent circuit found for {0}, aborting Scene.RemoveClient", agentID);
3562 return;
3563 }
3564 else
3565 {
3566 // We remove the acd up here to avoid later race conditions if two RemoveClient() calls occurred
3567 // simultaneously.
3568 // We also need to remove by agent ID since NPCs will have no circuit code.
3569 m_authenticateHandler.RemoveCircuit(agentID);
3570 }
3571 } 3458 }
3572 3459
3573 lock (acd) 3460 try
3574 { 3461 {
3575 ScenePresence avatar = GetScenePresence(agentID); 3462 isChildAgent = avatar.IsChildAgent;
3576
3577 if (avatar == null)
3578 {
3579 m_log.WarnFormat(
3580 "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID);
3581
3582 return;
3583 }
3584
3585 try
3586 {
3587 isChildAgent = avatar.IsChildAgent;
3588 3463
3589 m_log.DebugFormat( 3464 m_log.DebugFormat(
3590 "[SCENE]: Removing {0} agent {1} {2} from {3}", 3465 "[SCENE]: Removing {0} agent {1} {2} from {3}",
3591 (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName); 3466 (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName);
3592 3467
3593 // Don't do this to root agents, it's not nice for the viewer 3468 // Don't do this to root agents, it's not nice for the viewer
3594 if (closeChildAgents && isChildAgent) 3469 if (closeChildAgents && isChildAgent)
3470 {
3471 // Tell a single agent to disconnect from the region.
3472 IEventQueue eq = RequestModuleInterface<IEventQueue>();
3473 if (eq != null)
3595 { 3474 {
3596 // Tell a single agent to disconnect from the region. 3475 eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID);
3597 IEventQueue eq = RequestModuleInterface<IEventQueue>();
3598 if (eq != null)
3599 {
3600 eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID);
3601 }
3602 else
3603 {
3604 avatar.ControllingClient.SendShutdownConnectionNotice();
3605 }
3606 } 3476 }
3607 3477 else
3608 // Only applies to root agents.
3609 if (avatar.ParentID != 0)
3610 { 3478 {
3611 avatar.StandUp(); 3479 avatar.ControllingClient.SendShutdownConnectionNotice();
3612 } 3480 }
3613 3481 }
3614 m_sceneGraph.removeUserCount(!isChildAgent); 3482
3615 3483 // Only applies to root agents.
3616 // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop 3484 if (avatar.ParentID != 0)
3617 // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI 3485 {
3618 if (closeChildAgents && CapsModule != null) 3486 avatar.StandUp();
3619 CapsModule.RemoveCaps(agentID); 3487 }
3620 3488
3621// // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever 3489 m_sceneGraph.removeUserCount(!isChildAgent);
3622// // this method is doing is HORRIBLE!!! 3490
3623 // Commented pending deletion since this method no longer appears to do anything at all 3491 // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop
3624// avatar.Scene.NeedSceneCacheClear(avatar.UUID); 3492 // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI
3625 3493 if (closeChildAgents && CapsModule != null)
3626 if (closeChildAgents && !isChildAgent) 3494 CapsModule.RemoveCaps(agentID);
3495
3496 // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever
3497 // this method is doing is HORRIBLE!!!
3498 avatar.Scene.NeedSceneCacheClear(avatar.UUID);
3499
3500 if (closeChildAgents && !isChildAgent)
3501 {
3502 List<ulong> regions = avatar.KnownRegionHandles;
3503 regions.Remove(RegionInfo.RegionHandle);
3504 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions);
3505 }
3506
3507 m_eventManager.TriggerClientClosed(agentID, this);
3508 m_eventManager.TriggerOnRemovePresence(agentID);
3509
3510 if (!isChildAgent)
3511 {
3512 if (AttachmentsModule != null)
3627 { 3513 {
3628 List<ulong> regions = avatar.KnownRegionHandles; 3514 AttachmentsModule.DeRezAttachments(avatar);
3629 regions.Remove(RegionInfo.RegionHandle);
3630 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions);
3631 } 3515 }
3632 3516
3633 m_eventManager.TriggerClientClosed(agentID, this); 3517 ForEachClient(
3634 m_eventManager.TriggerOnRemovePresence(agentID); 3518 delegate(IClientAPI client)
3635
3636 if (!isChildAgent)
3637 {
3638 if (AttachmentsModule != null)
3639 { 3519 {
3640 AttachmentsModule.DeRezAttachments(avatar); 3520 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway
3641 } 3521 try { client.SendKillObject(avatar.RegionHandle, new List<uint> { avatar.LocalId }); }
3522 catch (NullReferenceException) { }
3523 });
3524 }
3642 3525
3643 ForEachClient( 3526 // It's possible for child agents to have transactions if changes are being made cross-border.
3644 delegate(IClientAPI client) 3527 if (AgentTransactionsModule != null)
3645 { 3528 AgentTransactionsModule.RemoveAgentAssetTransactions(agentID);
3646 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway 3529
3647 try { client.SendKillObject(avatar.RegionHandle, new List<uint> { avatar.LocalId }); } 3530 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode);
3648 catch (NullReferenceException) { } 3531 m_log.Debug("[Scene] The avatar has left the building");
3649 }); 3532 }
3650 } 3533 catch (Exception e)
3534 {
3535 m_log.Error(
3536 string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e);
3537 }
3538 finally
3539 {
3540 try
3541 {
3542 // Always clean these structures up so that any failure above doesn't cause them to remain in the
3543 // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering
3544 // the same cleanup exception continually.
3545 m_sceneGraph.RemoveScenePresence(agentID);
3546 m_clientManager.Remove(agentID);
3651 3547
3652 // It's possible for child agents to have transactions if changes are being made cross-border. 3548 avatar.Close();
3653 if (AgentTransactionsModule != null)
3654 AgentTransactionsModule.RemoveAgentAssetTransactions(agentID);
3655 m_log.Debug("[Scene] The avatar has left the building");
3656 } 3549 }
3657 catch (Exception e) 3550 catch (Exception e)
3658 { 3551 {
3659 m_log.Error( 3552 m_log.Error(
3660 string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e); 3553 string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e);
3661 }
3662 finally
3663 {
3664 try
3665 {
3666 // Always clean these structures up so that any failure above doesn't cause them to remain in the
3667 // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering
3668 // the same cleanup exception continually.
3669 m_sceneGraph.RemoveScenePresence(agentID);
3670 m_clientManager.Remove(agentID);
3671
3672 avatar.Close();
3673 }
3674 catch (Exception e)
3675 {
3676 m_log.Error(
3677 string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e);
3678 }
3679 } 3554 }
3680 } 3555 }
3681 3556
@@ -3734,9 +3609,11 @@ namespace OpenSim.Region.Framework.Scenes
3734 3609
3735 /// <summary> 3610 /// <summary>
3736 /// Do the work necessary to initiate a new user connection for a particular scene. 3611 /// Do the work necessary to initiate a new user connection for a particular scene.
3612 /// At the moment, this consists of setting up the caps infrastructure
3613 /// The return bool should allow for connections to be refused, but as not all calling paths
3614 /// take proper notice of it let, we allowed banned users in still.
3737 /// </summary> 3615 /// </summary>
3738 /// <param name="agent">CircuitData of the agent who is connecting</param> 3616 /// <param name="agent">CircuitData of the agent who is connecting</param>
3739 /// <param name="teleportFlags"></param>
3740 /// <param name="reason">Outputs the reason for the false response on this string</param> 3617 /// <param name="reason">Outputs the reason for the false response on this string</param>
3741 /// <returns>True if the region accepts this agent. False if it does not. False will 3618 /// <returns>True if the region accepts this agent. False if it does not. False will
3742 /// also return a reason.</returns> 3619 /// also return a reason.</returns>
@@ -3747,20 +3624,10 @@ namespace OpenSim.Region.Framework.Scenes
3747 3624
3748 /// <summary> 3625 /// <summary>
3749 /// Do the work necessary to initiate a new user connection for a particular scene. 3626 /// Do the work necessary to initiate a new user connection for a particular scene.
3750 /// </summary> 3627 /// At the moment, this consists of setting up the caps infrastructure
3751 /// <remarks>
3752 /// The return bool should allow for connections to be refused, but as not all calling paths
3753 /// take proper notice of it yet, we still allowed banned users in.
3754 ///
3755 /// At the moment this method consists of setting up the caps infrastructure
3756 /// The return bool should allow for connections to be refused, but as not all calling paths 3628 /// The return bool should allow for connections to be refused, but as not all calling paths
3757 /// take proper notice of it let, we allowed banned users in still. 3629 /// take proper notice of it let, we allowed banned users in still.
3758 /// 3630 /// </summary>
3759 /// This method is called by the login service (in the case of login) or another simulator (in the case of region
3760 /// cross or teleport) to initiate the connection. It is not triggered by the viewer itself - the connection
3761 /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of
3762 /// the LLUDP stack).
3763 /// </remarks>
3764 /// <param name="agent">CircuitData of the agent who is connecting</param> 3631 /// <param name="agent">CircuitData of the agent who is connecting</param>
3765 /// <param name="reason">Outputs the reason for the false response on this string</param> 3632 /// <param name="reason">Outputs the reason for the false response on this string</param>
3766 /// <param name="requirePresenceLookup">True for normal presence. False for NPC 3633 /// <param name="requirePresenceLookup">True for normal presence. False for NPC
@@ -3859,86 +3726,83 @@ namespace OpenSim.Region.Framework.Scenes
3859 "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", 3726 "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.",
3860 sp.Name, sp.UUID, RegionInfo.RegionName); 3727 sp.Name, sp.UUID, RegionInfo.RegionName);
3861 3728
3862 sp.ControllingClient.Close(true, true); 3729 sp.ControllingClient.Close();
3863 sp = null; 3730 sp = null;
3864 } 3731 }
3865 3732
3866 lock (agent) 3733
3734 //On login test land permisions
3735 if (vialogin)
3867 { 3736 {
3868 //On login test land permisions 3737 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3869 if (vialogin) 3738 if (cache != null)
3739 cache.Remove(agent.firstname + " " + agent.lastname);
3740 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y))
3870 { 3741 {
3871 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>(); 3742 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString());
3872 if (cache != null) 3743 return false;
3873 cache.Remove(agent.firstname + " " + agent.lastname);
3874 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y))
3875 {
3876 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString());
3877 return false;
3878 }
3879 } 3744 }
3745 }
3880 3746
3881 if (sp == null) // We don't have an [child] agent here already 3747 if (sp == null) // We don't have an [child] agent here already
3748 {
3749 if (requirePresenceLookup)
3882 { 3750 {
3883 if (requirePresenceLookup)
3884 {
3885 try
3886 {
3887 if (!VerifyUserPresence(agent, out reason))
3888 return false;
3889 } catch (Exception e)
3890 {
3891 m_log.ErrorFormat(
3892 "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace);
3893 return false;
3894 }
3895 }
3896
3897 try 3751 try
3898 { 3752 {
3899 // Always check estate if this is a login. Always 3753 if (!VerifyUserPresence(agent, out reason))
3900 // check if banned regions are to be blacked out. 3754 return false;
3901 if (vialogin || (!m_seeIntoBannedRegion)) 3755 } catch (Exception e)
3902 {
3903 if (!AuthorizeUser(agent, out reason))
3904 return false;
3905 }
3906 }
3907 catch (Exception e)
3908 { 3756 {
3909 m_log.ErrorFormat( 3757 m_log.ErrorFormat(
3910 "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); 3758 "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace);
3911 return false; 3759 return false;
3912 } 3760 }
3761 }
3913 3762
3914 m_log.InfoFormat( 3763 try
3915 "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", 3764 {
3916 RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname, 3765 // Always check estate if this is a login. Always
3917 agent.AgentID, agent.circuitcode); 3766 // check if banned regions are to be blacked out.
3918 3767 if (vialogin || (!m_seeIntoBannedRegion))
3919 if (CapsModule != null)
3920 { 3768 {
3921 CapsModule.SetAgentCapsSeeds(agent); 3769 if (!AuthorizeUser(agent, out reason))
3922 CapsModule.CreateCaps(agent.AgentID); 3770 return false;
3923 } 3771 }
3924 } 3772 }
3925 else 3773 catch (Exception e)
3926 { 3774 {
3927 // Let the SP know how we got here. This has a lot of interesting 3775 m_log.ErrorFormat(
3928 // uses down the line. 3776 "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace);
3929 sp.TeleportFlags = (TPFlags)teleportFlags; 3777 return false;
3778 }
3930 3779
3931 if (sp.IsChildAgent) 3780 m_log.InfoFormat(
3932 { 3781 "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})",
3933 m_log.DebugFormat( 3782 RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname,
3934 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", 3783 agent.AgentID, agent.circuitcode);
3935 agent.AgentID, RegionInfo.RegionName);
3936 3784
3937 sp.AdjustKnownSeeds(); 3785 if (CapsModule != null)
3786 {
3787 CapsModule.SetAgentCapsSeeds(agent);
3788 CapsModule.CreateCaps(agent.AgentID);
3789 }
3790 } else
3791 {
3792 // Let the SP know how we got here. This has a lot of interesting
3793 // uses down the line.
3794 sp.TeleportFlags = (TPFlags)teleportFlags;
3938 3795
3939 if (CapsModule != null) 3796 if (sp.IsChildAgent)
3940 CapsModule.SetAgentCapsSeeds(agent); 3797 {
3941 } 3798 m_log.DebugFormat(
3799 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}",
3800 agent.AgentID, RegionInfo.RegionName);
3801
3802 sp.AdjustKnownSeeds();
3803
3804 if (CapsModule != null)
3805 CapsModule.SetAgentCapsSeeds(agent);
3942 } 3806 }
3943 } 3807 }
3944 3808
@@ -4369,9 +4233,8 @@ namespace OpenSim.Region.Framework.Scenes
4369 return false; 4233 return false;
4370 } 4234 }
4371 4235
4372 // We have to wait until the viewer contacts this region 4236 // We have to wait until the viewer contacts this region after receiving EAC.
4373 // after receiving the EnableSimulator HTTP Event Queue message. This triggers the viewer to send 4237 // That calls AddNewClient, which finally creates the ScenePresence
4374 // a UseCircuitCode packet which in turn calls AddNewClient which finally creates the ScenePresence.
4375 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); 4238 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID);
4376 4239
4377 if (childAgentUpdate != null) 4240 if (childAgentUpdate != null)
@@ -4466,18 +4329,15 @@ namespace OpenSim.Region.Framework.Scenes
4466 /// Tell a single agent to disconnect from the region. 4329 /// Tell a single agent to disconnect from the region.
4467 /// </summary> 4330 /// </summary>
4468 /// <param name="agentID"></param> 4331 /// <param name="agentID"></param>
4469 /// <param name="force"> 4332 /// <param name="childOnly"></param>
4470 /// Force the agent to close even if it might be in the middle of some other operation. You do not want to 4333 public bool IncomingCloseAgent(UUID agentID, bool childOnly)
4471 /// force unless you are absolutely sure that the agent is dead and a normal close is not working.
4472 /// </param>
4473 public bool IncomingCloseAgent(UUID agentID, bool force)
4474 { 4334 {
4475 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 4335 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
4476 4336
4477 ScenePresence presence = m_sceneGraph.GetScenePresence(agentID); 4337 ScenePresence presence = m_sceneGraph.GetScenePresence(agentID);
4478 if (presence != null) 4338 if (presence != null)
4479 { 4339 {
4480 presence.ControllingClient.Close(force, force); 4340 presence.ControllingClient.Close(false);
4481 return true; 4341 return true;
4482 } 4342 }
4483 4343
@@ -4683,16 +4543,6 @@ namespace OpenSim.Region.Framework.Scenes
4683 return LandChannel.GetLandObject(x, y).LandData; 4543 return LandChannel.GetLandObject(x, y).LandData;
4684 } 4544 }
4685 4545
4686 /// <summary>
4687 /// Get LandData by position.
4688 /// </summary>
4689 /// <param name="pos"></param>
4690 /// <returns></returns>
4691 public LandData GetLandData(Vector3 pos)
4692 {
4693 return GetLandData(pos.X, pos.Y);
4694 }
4695
4696 public LandData GetLandData(uint x, uint y) 4546 public LandData GetLandData(uint x, uint y)
4697 { 4547 {
4698 m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y); 4548 m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y);
@@ -4923,24 +4773,13 @@ namespace OpenSim.Region.Framework.Scenes
4923 /// Get a group via its UUID 4773 /// Get a group via its UUID
4924 /// </summary> 4774 /// </summary>
4925 /// <param name="fullID"></param> 4775 /// <param name="fullID"></param>
4926 /// <returns>null if no group with that id exists</returns> 4776 /// <returns>null if no group with that name exists</returns>
4927 public SceneObjectGroup GetSceneObjectGroup(UUID fullID) 4777 public SceneObjectGroup GetSceneObjectGroup(UUID fullID)
4928 { 4778 {
4929 return m_sceneGraph.GetSceneObjectGroup(fullID); 4779 return m_sceneGraph.GetSceneObjectGroup(fullID);
4930 } 4780 }
4931 4781
4932 /// <summary> 4782 /// <summary>
4933 /// Get a group via its local ID
4934 /// </summary>
4935 /// <remarks>This will only return a group if the local ID matches a root part</remarks>
4936 /// <param name="localID"></param>
4937 /// <returns>null if no group with that id exists</returns>
4938 public SceneObjectGroup GetSceneObjectGroup(uint localID)
4939 {
4940 return m_sceneGraph.GetSceneObjectGroup(localID);
4941 }
4942
4943 /// <summary>
4944 /// Get a group by name from the scene (will return the first 4783 /// Get a group by name from the scene (will return the first
4945 /// found, if there are more than one prim with the same name) 4784 /// found, if there are more than one prim with the same name)
4946 /// </summary> 4785 /// </summary>
@@ -4952,18 +4791,6 @@ namespace OpenSim.Region.Framework.Scenes
4952 } 4791 }
4953 4792
4954 /// <summary> 4793 /// <summary>
4955 /// Attempt to get the SOG via its UUID
4956 /// </summary>
4957 /// <param name="fullID"></param>
4958 /// <param name="sog"></param>
4959 /// <returns></returns>
4960 public bool TryGetSceneObjectGroup(UUID fullID, out SceneObjectGroup sog)
4961 {
4962 sog = GetSceneObjectGroup(fullID);
4963 return sog != null;
4964 }
4965
4966 /// <summary>
4967 /// Get a prim by name from the scene (will return the first 4794 /// Get a prim by name from the scene (will return the first
4968 /// found, if there are more than one prim with the same name) 4795 /// found, if there are more than one prim with the same name)
4969 /// </summary> 4796 /// </summary>
@@ -4995,18 +4822,6 @@ namespace OpenSim.Region.Framework.Scenes
4995 } 4822 }
4996 4823
4997 /// <summary> 4824 /// <summary>
4998 /// Attempt to get a prim via its UUID
4999 /// </summary>
5000 /// <param name="fullID"></param>
5001 /// <param name="sop"></param>
5002 /// <returns></returns>
5003 public bool TryGetSceneObjectPart(UUID fullID, out SceneObjectPart sop)
5004 {
5005 sop = GetSceneObjectPart(fullID);
5006 return sop != null;
5007 }
5008
5009 /// <summary>
5010 /// Get a scene object group that contains the prim with the given local id 4825 /// Get a scene object group that contains the prim with the given local id
5011 /// </summary> 4826 /// </summary>
5012 /// <param name="localID"></param> 4827 /// <param name="localID"></param>
@@ -5100,15 +4915,14 @@ namespace OpenSim.Region.Framework.Scenes
5100 client.SendRegionHandle(regionID, handle); 4915 client.SendRegionHandle(regionID, handle);
5101 } 4916 }
5102 4917
5103// Commented pending deletion since this method no longer appears to do anything at all 4918 public bool NeedSceneCacheClear(UUID agentID)
5104// public bool NeedSceneCacheClear(UUID agentID) 4919 {
5105// { 4920 IInventoryTransferModule inv = RequestModuleInterface<IInventoryTransferModule>();
5106// IInventoryTransferModule inv = RequestModuleInterface<IInventoryTransferModule>(); 4921 if (inv == null)
5107// if (inv == null) 4922 return true;
5108// return true; 4923
5109// 4924 return inv.NeedSceneCacheClear(agentID, this);
5110// return inv.NeedSceneCacheClear(agentID, this); 4925 }
5111// }
5112 4926
5113 public void CleanTempObjects() 4927 public void CleanTempObjects()
5114 { 4928 {
@@ -6062,9 +5876,6 @@ Environment.Exit(1);
6062 5876
6063 public string GetExtraSetting(string name) 5877 public string GetExtraSetting(string name)
6064 { 5878 {
6065 if (m_extraSettings == null)
6066 return String.Empty;
6067
6068 string val; 5879 string val;
6069 5880
6070 if (!m_extraSettings.TryGetValue(name, out val)) 5881 if (!m_extraSettings.TryGetValue(name, out val))
@@ -6075,9 +5886,6 @@ Environment.Exit(1);
6075 5886
6076 public void StoreExtraSetting(string name, string val) 5887 public void StoreExtraSetting(string name, string val)
6077 { 5888 {
6078 if (m_extraSettings == null)
6079 return;
6080
6081 string oldVal; 5889 string oldVal;
6082 5890
6083 if (m_extraSettings.TryGetValue(name, out oldVal)) 5891 if (m_extraSettings.TryGetValue(name, out oldVal))
@@ -6095,9 +5903,6 @@ Environment.Exit(1);
6095 5903
6096 public void RemoveExtraSetting(string name) 5904 public void RemoveExtraSetting(string name)
6097 { 5905 {
6098 if (m_extraSettings == null)
6099 return;
6100
6101 if (!m_extraSettings.ContainsKey(name)) 5906 if (!m_extraSettings.ContainsKey(name))
6102 return; 5907 return;
6103 5908
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index e599e90..af13b46 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -342,7 +342,7 @@ namespace OpenSim.Region.Framework.Scenes
342 public bool AddNewSceneObject( 342 public bool AddNewSceneObject(
343 SceneObjectGroup sceneObject, bool attachToBackup, Vector3? pos, Quaternion? rot, Vector3 vel) 343 SceneObjectGroup sceneObject, bool attachToBackup, Vector3? pos, Quaternion? rot, Vector3 vel)
344 { 344 {
345 AddNewSceneObject(sceneObject, attachToBackup, false); 345 AddNewSceneObject(sceneObject, true, false);
346 346
347 if (pos != null) 347 if (pos != null)
348 sceneObject.AbsolutePosition = (Vector3)pos; 348 sceneObject.AbsolutePosition = (Vector3)pos;
@@ -421,9 +421,12 @@ namespace OpenSim.Region.Framework.Scenes
421 { 421 {
422 Vector3 scale = part.Shape.Scale; 422 Vector3 scale = part.Shape.Scale;
423 423
424 scale.X = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.X)); 424 if (scale.X > m_parentScene.m_maxNonphys)
425 scale.Y = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Y)); 425 scale.X = m_parentScene.m_maxNonphys;
426 scale.Z = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Z)); 426 if (scale.Y > m_parentScene.m_maxNonphys)
427 scale.Y = m_parentScene.m_maxNonphys;
428 if (scale.Z > m_parentScene.m_maxNonphys)
429 scale.Z = m_parentScene.m_maxNonphys;
427 430
428 part.Shape.Scale = scale; 431 part.Shape.Scale = scale;
429 } 432 }
@@ -1063,30 +1066,6 @@ namespace OpenSim.Region.Framework.Scenes
1063 } 1066 }
1064 1067
1065 /// <summary> 1068 /// <summary>
1066 /// Get a group in the scene
1067 /// </summary>
1068 /// <remarks>
1069 /// This will only return a group if the local ID matches the root part, not other parts.
1070 /// </remarks>
1071 /// <param name="localID">Local id of the root part of the group</param>
1072 /// <returns>null if no such group was found</returns>
1073 protected internal SceneObjectGroup GetSceneObjectGroup(uint localID)
1074 {
1075 lock (SceneObjectGroupsByLocalPartID)
1076 {
1077 if (SceneObjectGroupsByLocalPartID.ContainsKey(localID))
1078 {
1079 SceneObjectGroup so = SceneObjectGroupsByLocalPartID[localID];
1080
1081 if (so.LocalId == localID)
1082 return so;
1083 }
1084 }
1085
1086 return null;
1087 }
1088
1089 /// <summary>
1090 /// Get a group by name from the scene (will return the first 1069 /// Get a group by name from the scene (will return the first
1091 /// found, if there are more than one prim with the same name) 1070 /// found, if there are more than one prim with the same name)
1092 /// </summary> 1071 /// </summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs
index dba3a61..f1b09ca 100644
--- a/OpenSim/Region/Framework/Scenes/SceneManager.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs
@@ -92,11 +92,7 @@ namespace OpenSim.Region.Framework.Scenes
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 { return m_instance; }
96 if (m_instance == null)
97 m_instance = new SceneManager();
98 return m_instance;
99 }
100 } 96 }
101 97
102 private readonly DoubleDictionary<UUID, string, Scene> m_localScenes = new DoubleDictionary<UUID, string, Scene>(); 98 private readonly DoubleDictionary<UUID, string, Scene> m_localScenes = new DoubleDictionary<UUID, string, Scene>();
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 74d2629..ee61de6 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -2747,25 +2747,6 @@ namespace OpenSim.Region.Framework.Scenes
2747 if (objectGroup == this) 2747 if (objectGroup == this)
2748 return; 2748 return;
2749 2749
2750 // If the configured linkset capacity is greater than zero,
2751 // and the new linkset would have a prim count higher than this
2752 // value, do not link it.
2753 if (m_scene.m_linksetCapacity > 0 &&
2754 (PrimCount + objectGroup.PrimCount) >
2755 m_scene.m_linksetCapacity)
2756 {
2757 m_log.DebugFormat(
2758 "[SCENE OBJECT GROUP]: Cannot link group with root" +
2759 " part {0}, {1} ({2} prims) to group with root part" +
2760 " {3}, {4} ({5} prims) because the new linkset" +
2761 " would exceed the configured maximum of {6}",
2762 objectGroup.RootPart.Name, objectGroup.RootPart.UUID,
2763 objectGroup.PrimCount, RootPart.Name, RootPart.UUID,
2764 PrimCount, m_scene.m_linksetCapacity);
2765
2766 return;
2767 }
2768
2769 // 'linkPart' == the root of the group being linked into this group 2750 // 'linkPart' == the root of the group being linked into this group
2770 SceneObjectPart linkPart = objectGroup.m_rootPart; 2751 SceneObjectPart linkPart = objectGroup.m_rootPart;
2771 2752
@@ -3511,33 +3492,27 @@ namespace OpenSim.Region.Framework.Scenes
3511 /// <param name="scale"></param> 3492 /// <param name="scale"></param>
3512 public void GroupResize(Vector3 scale) 3493 public void GroupResize(Vector3 scale)
3513 { 3494 {
3514// m_log.DebugFormat( 3495 scale.X = Math.Min(scale.X, Scene.m_maxNonphys);
3515// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale); 3496 scale.Y = Math.Min(scale.Y, Scene.m_maxNonphys);
3497 scale.Z = Math.Min(scale.Z, Scene.m_maxNonphys);
3516 3498
3517 PhysicsActor pa = m_rootPart.PhysActor; 3499 PhysicsActor pa = m_rootPart.PhysActor;
3518 3500
3519 if (Scene != null) 3501 if (pa != null && pa.IsPhysical)
3520 { 3502 {
3521 scale.X = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.X)); 3503 scale.X = Math.Min(scale.X, Scene.m_maxPhys);
3522 scale.Y = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Y)); 3504 scale.Y = Math.Min(scale.Y, Scene.m_maxPhys);
3523 scale.Z = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Z)); 3505 scale.Z = Math.Min(scale.Z, Scene.m_maxPhys);
3524
3525 if (pa != null && pa.IsPhysical)
3526 {
3527 scale.X = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.X));
3528 scale.Y = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.Y));
3529 scale.Z = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.Z));
3530 }
3531 } 3506 }
3532 3507
3533 float x = (scale.X / RootPart.Scale.X); 3508 float x = (scale.X / RootPart.Scale.X);
3534 float y = (scale.Y / RootPart.Scale.Y); 3509 float y = (scale.Y / RootPart.Scale.Y);
3535 float z = (scale.Z / RootPart.Scale.Z); 3510 float z = (scale.Z / RootPart.Scale.Z);
3536 3511
3537 SceneObjectPart[] parts = m_parts.GetArray(); 3512 SceneObjectPart[] parts;
3538 3513 if (x > 1.0f || y > 1.0f || z > 1.0f)
3539 if (Scene != null & (x > 1.0f || y > 1.0f || z > 1.0f))
3540 { 3514 {
3515 parts = m_parts.GetArray();
3541 for (int i = 0; i < parts.Length; i++) 3516 for (int i = 0; i < parts.Length; i++)
3542 { 3517 {
3543 SceneObjectPart obPart = parts[i]; 3518 SceneObjectPart obPart = parts[i];
@@ -3550,7 +3525,7 @@ namespace OpenSim.Region.Framework.Scenes
3550 3525
3551 if (pa != null && pa.IsPhysical) 3526 if (pa != null && pa.IsPhysical)
3552 { 3527 {
3553 if (oldSize.X * x > Scene.m_maxPhys) 3528 if (oldSize.X * x > m_scene.m_maxPhys)
3554 { 3529 {
3555 f = m_scene.m_maxPhys / oldSize.X; 3530 f = m_scene.m_maxPhys / oldSize.X;
3556 a = f / x; 3531 a = f / x;
@@ -3558,16 +3533,8 @@ namespace OpenSim.Region.Framework.Scenes
3558 y *= a; 3533 y *= a;
3559 z *= a; 3534 z *= a;
3560 } 3535 }
3561 else if (oldSize.X * x < Scene.m_minPhys)
3562 {
3563 f = m_scene.m_minPhys / oldSize.X;
3564 a = f / x;
3565 x *= a;
3566 y *= a;
3567 z *= a;
3568 }
3569 3536
3570 if (oldSize.Y * y > Scene.m_maxPhys) 3537 if (oldSize.Y * y > m_scene.m_maxPhys)
3571 { 3538 {
3572 f = m_scene.m_maxPhys / oldSize.Y; 3539 f = m_scene.m_maxPhys / oldSize.Y;
3573 a = f / y; 3540 a = f / y;
@@ -3575,16 +3542,8 @@ namespace OpenSim.Region.Framework.Scenes
3575 y *= a; 3542 y *= a;
3576 z *= a; 3543 z *= a;
3577 } 3544 }
3578 else if (oldSize.Y * y < Scene.m_minPhys)
3579 {
3580 f = m_scene.m_minPhys / oldSize.Y;
3581 a = f / y;
3582 x *= a;
3583 y *= a;
3584 z *= a;
3585 }
3586 3545
3587 if (oldSize.Z * z > Scene.m_maxPhys) 3546 if (oldSize.Z * z > m_scene.m_maxPhys)
3588 { 3547 {
3589 f = m_scene.m_maxPhys / oldSize.Z; 3548 f = m_scene.m_maxPhys / oldSize.Z;
3590 a = f / z; 3549 a = f / z;
@@ -3592,18 +3551,10 @@ namespace OpenSim.Region.Framework.Scenes
3592 y *= a; 3551 y *= a;
3593 z *= a; 3552 z *= a;
3594 } 3553 }
3595 else if (oldSize.Z * z < Scene.m_minPhys)
3596 {
3597 f = m_scene.m_minPhys / oldSize.Z;
3598 a = f / z;
3599 x *= a;
3600 y *= a;
3601 z *= a;
3602 }
3603 } 3554 }
3604 else 3555 else
3605 { 3556 {
3606 if (oldSize.X * x > Scene.m_maxNonphys) 3557 if (oldSize.X * x > m_scene.m_maxNonphys)
3607 { 3558 {
3608 f = m_scene.m_maxNonphys / oldSize.X; 3559 f = m_scene.m_maxNonphys / oldSize.X;
3609 a = f / x; 3560 a = f / x;
@@ -3611,16 +3562,8 @@ namespace OpenSim.Region.Framework.Scenes
3611 y *= a; 3562 y *= a;
3612 z *= a; 3563 z *= a;
3613 } 3564 }
3614 else if (oldSize.X * x < Scene.m_minNonphys)
3615 {
3616 f = m_scene.m_minNonphys / oldSize.X;
3617 a = f / x;
3618 x *= a;
3619 y *= a;
3620 z *= a;
3621 }
3622 3565
3623 if (oldSize.Y * y > Scene.m_maxNonphys) 3566 if (oldSize.Y * y > m_scene.m_maxNonphys)
3624 { 3567 {
3625 f = m_scene.m_maxNonphys / oldSize.Y; 3568 f = m_scene.m_maxNonphys / oldSize.Y;
3626 a = f / y; 3569 a = f / y;
@@ -3628,16 +3571,8 @@ namespace OpenSim.Region.Framework.Scenes
3628 y *= a; 3571 y *= a;
3629 z *= a; 3572 z *= a;
3630 } 3573 }
3631 else if (oldSize.Y * y < Scene.m_minNonphys)
3632 {
3633 f = m_scene.m_minNonphys / oldSize.Y;
3634 a = f / y;
3635 x *= a;
3636 y *= a;
3637 z *= a;
3638 }
3639 3574
3640 if (oldSize.Z * z > Scene.m_maxNonphys) 3575 if (oldSize.Z * z > m_scene.m_maxNonphys)
3641 { 3576 {
3642 f = m_scene.m_maxNonphys / oldSize.Z; 3577 f = m_scene.m_maxNonphys / oldSize.Z;
3643 a = f / z; 3578 a = f / z;
@@ -3645,14 +3580,6 @@ namespace OpenSim.Region.Framework.Scenes
3645 y *= a; 3580 y *= a;
3646 z *= a; 3581 z *= a;
3647 } 3582 }
3648 else if (oldSize.Z * z < Scene.m_minNonphys)
3649 {
3650 f = m_scene.m_minNonphys / oldSize.Z;
3651 a = f / z;
3652 x *= a;
3653 y *= a;
3654 z *= a;
3655 }
3656 } 3583 }
3657 } 3584 }
3658 } 3585 }
@@ -3665,6 +3592,7 @@ namespace OpenSim.Region.Framework.Scenes
3665 3592
3666 RootPart.Resize(prevScale); 3593 RootPart.Resize(prevScale);
3667 3594
3595 parts = m_parts.GetArray();
3668 for (int i = 0; i < parts.Length; i++) 3596 for (int i = 0; i < parts.Length; i++)
3669 { 3597 {
3670 SceneObjectPart obPart = parts[i]; 3598 SceneObjectPart obPart = parts[i];
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 2191cfa..165dd85 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -790,7 +790,7 @@ namespace OpenSim.Region.Framework.Scenes
790 } 790 }
791 catch (Exception e) 791 catch (Exception e)
792 { 792 {
793 m_log.ErrorFormat("[SCENEOBJECTPART]: GROUP POSITION. {0}", e); 793 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message);
794 } 794 }
795 } 795 }
796 } 796 }
@@ -2864,35 +2864,6 @@ namespace OpenSim.Region.Framework.Scenes
2864 SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd); 2864 SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd);
2865 } 2865 }
2866 2866
2867 // The Collision sounds code calls this
2868 public void SendCollisionSound(UUID soundID, double volume, Vector3 position)
2869 {
2870 if (soundID == UUID.Zero)
2871 return;
2872
2873 ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>();
2874 if (soundModule == null)
2875 return;
2876
2877 if (volume > 1)
2878 volume = 1;
2879 if (volume < 0)
2880 volume = 0;
2881
2882 int now = Util.EnvironmentTickCount();
2883 if(Util.EnvironmentTickCountSubtract(now,LastColSoundSentTime) <200)
2884 return;
2885
2886 LastColSoundSentTime = now;
2887
2888 UUID ownerID = OwnerID;
2889 UUID objectID = ParentGroup.RootPart.UUID;
2890 UUID parentID = ParentGroup.UUID;
2891 ulong regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle;
2892
2893 soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, 0 );
2894 }
2895
2896 public void PhysicsOutOfBounds(Vector3 pos) 2867 public void PhysicsOutOfBounds(Vector3 pos)
2897 { 2868 {
2898 m_log.Error("[PHYSICS]: Physical Object went out of bounds."); 2869 m_log.Error("[PHYSICS]: Physical Object went out of bounds.");
@@ -2924,6 +2895,38 @@ namespace OpenSim.Region.Framework.Scenes
2924 ScheduleTerseUpdate(); 2895 ScheduleTerseUpdate();
2925 } 2896 }
2926 2897
2898 public void PreloadSound(string sound)
2899 {
2900 // UUID ownerID = OwnerID;
2901 UUID objectID = ParentGroup.RootPart.UUID;
2902 UUID soundID = UUID.Zero;
2903
2904 if (!UUID.TryParse(sound, out soundID))
2905 {
2906 //Trys to fetch sound id from prim's inventory.
2907 //Prim's inventory doesn't support non script items yet
2908
2909 TaskInventory.LockItemsForRead(true);
2910
2911 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2912 {
2913 if (item.Value.Name == sound)
2914 {
2915 soundID = item.Value.ItemID;
2916 break;
2917 }
2918 }
2919
2920 TaskInventory.LockItemsForRead(false);
2921 }
2922
2923 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp)
2924 {
2925 if (!(Util.GetDistanceTo(sp.AbsolutePosition, AbsolutePosition) >= 100))
2926 sp.ControllingClient.SendPreLoadSound(objectID, objectID, soundID);
2927 });
2928 }
2929
2927 public void RemFlag(PrimFlags flag) 2930 public void RemFlag(PrimFlags flag)
2928 { 2931 {
2929 // PrimFlags prevflag = Flags; 2932 // PrimFlags prevflag = Flags;
@@ -2976,20 +2979,17 @@ namespace OpenSim.Region.Framework.Scenes
2976 /// <param name="scale"></param> 2979 /// <param name="scale"></param>
2977 public void Resize(Vector3 scale) 2980 public void Resize(Vector3 scale)
2978 { 2981 {
2982 scale.X = Math.Min(scale.X, ParentGroup.Scene.m_maxNonphys);
2983 scale.Y = Math.Min(scale.Y, ParentGroup.Scene.m_maxNonphys);
2984 scale.Z = Math.Min(scale.Z, ParentGroup.Scene.m_maxNonphys);
2985
2979 PhysicsActor pa = PhysActor; 2986 PhysicsActor pa = PhysActor;
2980 2987
2981 if (ParentGroup.Scene != null) 2988 if (pa != null && pa.IsPhysical)
2982 { 2989 {
2983 scale.X = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.X)); 2990 scale.X = Math.Min(scale.X, ParentGroup.Scene.m_maxPhys);
2984 scale.Y = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Y)); 2991 scale.Y = Math.Min(scale.Y, ParentGroup.Scene.m_maxPhys);
2985 scale.Z = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Z)); 2992 scale.Z = Math.Min(scale.Z, ParentGroup.Scene.m_maxPhys);
2986
2987 if (pa != null && pa.IsPhysical)
2988 {
2989 scale.X = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.X));
2990 scale.Y = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Y));
2991 scale.Z = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Z));
2992 }
2993 } 2993 }
2994 2994
2995// m_log.DebugFormat("[SCENE OBJECT PART]: Resizing {0} {1} to {2}", Name, LocalId, scale); 2995// m_log.DebugFormat("[SCENE OBJECT PART]: Resizing {0} {1} to {2}", Name, LocalId, scale);
@@ -3086,7 +3086,7 @@ namespace OpenSim.Region.Framework.Scenes
3086 // UUID, Name, TimeStampFull); 3086 // UUID, Name, TimeStampFull);
3087 3087
3088 if (ParentGroup.Scene != null) 3088 if (ParentGroup.Scene != null)
3089 ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, true); 3089 ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this);
3090 } 3090 }
3091 3091
3092 /// <summary> 3092 /// <summary>
@@ -3120,7 +3120,7 @@ namespace OpenSim.Region.Framework.Scenes
3120 } 3120 }
3121 3121
3122 if (ParentGroup.Scene != null) 3122 if (ParentGroup.Scene != null)
3123 ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, false); 3123 ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this);
3124 } 3124 }
3125 3125
3126 public void ScriptSetPhysicsStatus(bool UsePhysics) 3126 public void ScriptSetPhysicsStatus(bool UsePhysics)
@@ -3295,6 +3295,126 @@ namespace OpenSim.Region.Framework.Scenes
3295 } 3295 }
3296 3296
3297 /// <summary> 3297 /// <summary>
3298 /// Trigger or play an attached sound in this part's inventory.
3299 /// </summary>
3300 /// <param name="sound"></param>
3301 /// <param name="volume"></param>
3302 /// <param name="triggered"></param>
3303 /// <param name="flags"></param>
3304 public void SendSound(string sound, double volume, bool triggered, byte flags, float radius, bool useMaster, bool isMaster)
3305 {
3306 if (volume > 1)
3307 volume = 1;
3308 if (volume < 0)
3309 volume = 0;
3310
3311 UUID ownerID = OwnerID;
3312 UUID objectID = ParentGroup.RootPart.UUID;
3313 UUID parentID = ParentGroup.UUID;
3314
3315 UUID soundID = UUID.Zero;
3316 Vector3 position = AbsolutePosition; // region local
3317 ulong regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle;
3318
3319 if (!UUID.TryParse(sound, out soundID))
3320 {
3321 // search sound file from inventory
3322 TaskInventory.LockItemsForRead(true);
3323 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
3324 {
3325 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
3326 {
3327 soundID = item.Value.ItemID;
3328 break;
3329 }
3330 }
3331 TaskInventory.LockItemsForRead(false);
3332 }
3333
3334 if (soundID == UUID.Zero)
3335 return;
3336
3337 ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>();
3338 if (soundModule != null)
3339 {
3340 if (useMaster)
3341 {
3342 if (isMaster)
3343 {
3344 if (triggered)
3345 soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius);
3346 else
3347 soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius);
3348 ParentGroup.PlaySoundMasterPrim = this;
3349 ownerID = OwnerID;
3350 objectID = ParentGroup.RootPart.UUID;
3351 parentID = ParentGroup.UUID;
3352 position = AbsolutePosition; // region local
3353 regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle;
3354 if (triggered)
3355 soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius);
3356 else
3357 soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius);
3358 foreach (SceneObjectPart prim in ParentGroup.PlaySoundSlavePrims)
3359 {
3360 ownerID = prim.OwnerID;
3361 objectID = prim.ParentGroup.RootPart.UUID;
3362 parentID = prim.ParentGroup.UUID;
3363 position = prim.AbsolutePosition; // region local
3364 regionHandle = prim.ParentGroup.Scene.RegionInfo.RegionHandle;
3365 if (triggered)
3366 soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius);
3367 else
3368 soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius);
3369 }
3370 ParentGroup.PlaySoundSlavePrims.Clear();
3371 ParentGroup.PlaySoundMasterPrim = null;
3372 }
3373 else
3374 {
3375 ParentGroup.PlaySoundSlavePrims.Add(this);
3376 }
3377 }
3378 else
3379 {
3380 if (triggered)
3381 soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius);
3382 else
3383 soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius);
3384 }
3385 }
3386 }
3387
3388 public void SendCollisionSound(UUID soundID, double volume, Vector3 position)
3389 {
3390 if (soundID == UUID.Zero)
3391 return;
3392
3393 ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>();
3394 if (soundModule == null)
3395 return;
3396
3397 if (volume > 1)
3398 volume = 1;
3399 if (volume < 0)
3400 volume = 0;
3401
3402 int now = Util.EnvironmentTickCount();
3403 if(Util.EnvironmentTickCountSubtract(now,LastColSoundSentTime) <200)
3404 return;
3405
3406 LastColSoundSentTime = now;
3407
3408 UUID ownerID = OwnerID;
3409 UUID objectID = ParentGroup.RootPart.UUID;
3410 UUID parentID = ParentGroup.UUID;
3411 ulong regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle;
3412
3413 soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, 0 );
3414 }
3415
3416
3417 /// <summary>
3298 /// Send a terse update to all clients 3418 /// Send a terse update to all clients
3299 /// </summary> 3419 /// </summary>
3300 public void SendTerseUpdateToAllClients() 3420 public void SendTerseUpdateToAllClients()
@@ -3455,32 +3575,23 @@ namespace OpenSim.Region.Framework.Scenes
3455 } 3575 }
3456 3576
3457 /// <summary> 3577 /// <summary>
3458 /// Set the color & alpha of prim faces 3578 /// Set the color of prim faces
3459 /// </summary> 3579 /// </summary>
3460 /// <param name="face"></param>
3461 /// <param name="color"></param> 3580 /// <param name="color"></param>
3462 /// <param name="alpha"></param> 3581 /// <param name="face"></param>
3463 public void SetFaceColorAlpha(int face, Vector3 color, double ?alpha) 3582 public void SetFaceColor(Vector3 color, int face)
3464 { 3583 {
3465 Vector3 clippedColor = Util.Clip(color, 0.0f, 1.0f);
3466 float clippedAlpha = alpha.HasValue ?
3467 Util.Clip((float)alpha.Value, 0.0f, 1.0f) : 0;
3468
3469 // The only way to get a deep copy/ If we don't do this, we can 3584 // The only way to get a deep copy/ If we don't do this, we can
3470 // never detect color changes further down. 3585 // mever detect color changes further down.
3471 Byte[] buf = Shape.Textures.GetBytes(); 3586 Byte[] buf = Shape.Textures.GetBytes();
3472 Primitive.TextureEntry tex = new Primitive.TextureEntry(buf, 0, buf.Length); 3587 Primitive.TextureEntry tex = new Primitive.TextureEntry(buf, 0, buf.Length);
3473 Color4 texcolor; 3588 Color4 texcolor;
3474 if (face >= 0 && face < GetNumberOfSides()) 3589 if (face >= 0 && face < GetNumberOfSides())
3475 { 3590 {
3476 texcolor = tex.CreateFace((uint)face).RGBA; 3591 texcolor = tex.CreateFace((uint)face).RGBA;
3477 texcolor.R = clippedColor.X; 3592 texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f);
3478 texcolor.G = clippedColor.Y; 3593 texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f);
3479 texcolor.B = clippedColor.Z; 3594 texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f);
3480 if (alpha.HasValue)
3481 {
3482 texcolor.A = clippedAlpha;
3483 }
3484 tex.FaceTextures[face].RGBA = texcolor; 3595 tex.FaceTextures[face].RGBA = texcolor;
3485 UpdateTextureEntry(tex.GetBytes()); 3596 UpdateTextureEntry(tex.GetBytes());
3486 return; 3597 return;
@@ -3492,23 +3603,15 @@ namespace OpenSim.Region.Framework.Scenes
3492 if (tex.FaceTextures[i] != null) 3603 if (tex.FaceTextures[i] != null)
3493 { 3604 {
3494 texcolor = tex.FaceTextures[i].RGBA; 3605 texcolor = tex.FaceTextures[i].RGBA;
3495 texcolor.R = clippedColor.X; 3606 texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f);
3496 texcolor.G = clippedColor.Y; 3607 texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f);
3497 texcolor.B = clippedColor.Z; 3608 texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f);
3498 if (alpha.HasValue)
3499 {
3500 texcolor.A = clippedAlpha;
3501 }
3502 tex.FaceTextures[i].RGBA = texcolor; 3609 tex.FaceTextures[i].RGBA = texcolor;
3503 } 3610 }
3504 texcolor = tex.DefaultTexture.RGBA; 3611 texcolor = tex.DefaultTexture.RGBA;
3505 texcolor.R = clippedColor.X; 3612 texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f);
3506 texcolor.G = clippedColor.Y; 3613 texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f);
3507 texcolor.B = clippedColor.Z; 3614 texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f);
3508 if (alpha.HasValue)
3509 {
3510 texcolor.A = clippedAlpha;
3511 }
3512 tex.DefaultTexture.RGBA = texcolor; 3615 tex.DefaultTexture.RGBA = texcolor;
3513 } 3616 }
3514 UpdateTextureEntry(tex.GetBytes()); 3617 UpdateTextureEntry(tex.GetBytes());
@@ -4796,57 +4899,6 @@ namespace OpenSim.Region.Framework.Scenes
4796 ScheduleFullUpdate(); 4899 ScheduleFullUpdate();
4797 } 4900 }
4798 4901
4799 public void UpdateSlice(float begin, float end)
4800 {
4801 if (end < begin)
4802 {
4803 float temp = begin;
4804 begin = end;
4805 end = temp;
4806 }
4807 end = Math.Min(1f, Math.Max(0f, end));
4808 begin = Math.Min(Math.Min(1f, Math.Max(0f, begin)), end - 0.02f);
4809 if (begin < 0.02f && end < 0.02f)
4810 {
4811 begin = 0f;
4812 end = 0.02f;
4813 }
4814
4815 ushort uBegin = (ushort)(50000.0 * begin);
4816 ushort uEnd = (ushort)(50000.0 * (1f - end));
4817 bool updatePossiblyNeeded = false;
4818 PrimType primType = GetPrimType();
4819 if (primType == PrimType.SPHERE || primType == PrimType.TORUS || primType == PrimType.TUBE || primType == PrimType.RING)
4820 {
4821 if (m_shape.ProfileBegin != uBegin || m_shape.ProfileEnd != uEnd)
4822 {
4823 m_shape.ProfileBegin = uBegin;
4824 m_shape.ProfileEnd = uEnd;
4825 updatePossiblyNeeded = true;
4826 }
4827 }
4828 else if (m_shape.PathBegin != uBegin || m_shape.PathEnd != uEnd)
4829 {
4830 m_shape.PathBegin = uBegin;
4831 m_shape.PathEnd = uEnd;
4832 updatePossiblyNeeded = true;
4833 }
4834
4835 if (updatePossiblyNeeded && ParentGroup != null)
4836 {
4837 ParentGroup.HasGroupChanged = true;
4838 }
4839 if (updatePossiblyNeeded && PhysActor != null)
4840 {
4841 PhysActor.Shape = m_shape;
4842 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor);
4843 }
4844 if (updatePossiblyNeeded)
4845 {
4846 ScheduleFullUpdate();
4847 }
4848 }
4849
4850 /// <summary> 4902 /// <summary>
4851 /// If the part is a sculpt/mesh, retrieve the mesh data and reinsert it into the shape so that the physics 4903 /// If the part is a sculpt/mesh, retrieve the mesh data and reinsert it into the shape so that the physics
4852 /// engine can use it. 4904 /// engine can use it.
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index 3a9a146..e010864 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -97,15 +97,6 @@ namespace OpenSim.Region.Framework.Scenes
97 QueryScriptStates(); 97 QueryScriptStates();
98 } 98 }
99 } 99 }
100
101 public int Count
102 {
103 get
104 {
105 lock (m_items)
106 return m_items.Count;
107 }
108 }
109 100
110 /// <summary> 101 /// <summary>
111 /// Constructor 102 /// Constructor
@@ -244,52 +235,31 @@ namespace OpenSim.Region.Framework.Scenes
244 if (m_part == null || m_part.ParentGroup == null || m_part.ParentGroup.Scene == null) 235 if (m_part == null || m_part.ParentGroup == null || m_part.ParentGroup.Scene == null)
245 return; 236 return;
246 237
238 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
239 if (engines == null) // No engine at all
240 return;
241
247 Items.LockItemsForRead(true); 242 Items.LockItemsForRead(true);
248 foreach (TaskInventoryItem item in Items.Values) 243 foreach (TaskInventoryItem item in Items.Values)
249 { 244 {
250 if (item.InvType == (int)InventoryType.LSL) 245 if (item.InvType == (int)InventoryType.LSL)
251 { 246 {
252 bool running; 247 foreach (IScriptModule e in engines)
253 if (TryGetScriptInstanceRunning(m_part.ParentGroup.Scene, item, out running)) 248 {
254 item.ScriptRunning = running; 249 bool running;
250
251 if (e.HasScript(item.ItemID, out running))
252 {
253 item.ScriptRunning = running;
254 break;
255 }
256 }
255 } 257 }
256 } 258 }
257 259
258 Items.LockItemsForRead(false); 260 Items.LockItemsForRead(false);
259 } 261 }
260 262
261 public bool TryGetScriptInstanceRunning(UUID itemId, out bool running)
262 {
263 running = false;
264
265 TaskInventoryItem item = GetInventoryItem(itemId);
266
267 if (item == null)
268 return false;
269
270 return TryGetScriptInstanceRunning(m_part.ParentGroup.Scene, item, out running);
271 }
272
273 public static bool TryGetScriptInstanceRunning(Scene scene, TaskInventoryItem item, out bool running)
274 {
275 running = false;
276
277 if (item.InvType != (int)InventoryType.LSL)
278 return false;
279
280 IScriptModule[] engines = scene.RequestModuleInterfaces<IScriptModule>();
281 if (engines == null) // No engine at all
282 return false;
283
284 foreach (IScriptModule e in engines)
285 {
286 if (e.HasScript(item.ItemID, out running))
287 return true;
288 }
289
290 return false;
291 }
292
293 public int CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) 263 public int CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource)
294 { 264 {
295 int scriptsValidForStarting = 0; 265 int scriptsValidForStarting = 0;
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 25a53b4..2b9665c 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
@@ -69,15 +69,14 @@ namespace OpenSim.Region.Framework.Scenes
69 public ScriptControlled eventControls; 69 public ScriptControlled eventControls;
70 } 70 }
71 71
72 public delegate void SendCoarseLocationsMethod(UUID scene, ScenePresence presence, List<Vector3> coarseLocations, List<UUID> avatarUUIDs); 72 public delegate void SendCourseLocationsMethod(UUID scene, ScenePresence presence, List<Vector3> coarseLocations, List<UUID> avatarUUIDs);
73 73
74 public class ScenePresence : EntityBase, IScenePresence 74 public class ScenePresence : EntityBase, IScenePresence
75 { 75 {
76// ~ScenePresence() 76// ~ScenePresence()
77// { 77// {
78// m_log.DebugFormat("[SCENE PRESENCE]: Destructor called on {0}", Name); 78// m_log.Debug("[SCENE PRESENCE] Destructor called");
79// } 79// }
80
81 private void TriggerScenePresenceUpdated() 80 private void TriggerScenePresenceUpdated()
82 { 81 {
83 if (m_scene != null) 82 if (m_scene != null)
@@ -189,7 +188,7 @@ namespace OpenSim.Region.Framework.Scenes
189 /// </summary> 188 /// </summary>
190 public bool SitGround { get; private set; } 189 public bool SitGround { get; private set; }
191 190
192 private SendCoarseLocationsMethod m_sendCoarseLocationsMethod; 191 private SendCourseLocationsMethod m_sendCourseLocationsMethod;
193 192
194 //private Vector3 m_requestedSitOffset = new Vector3(); 193 //private Vector3 m_requestedSitOffset = new Vector3();
195 194
@@ -547,7 +546,7 @@ namespace OpenSim.Region.Framework.Scenes
547 { 546 {
548 try 547 try
549 { 548 {
550 PhysicsActor.TargetVelocity = value; 549 PhysicsActor.Velocity = value;
551 } 550 }
552 catch (Exception e) 551 catch (Exception e)
553 { 552 {
@@ -712,7 +711,7 @@ namespace OpenSim.Region.Framework.Scenes
712 AttachmentsSyncLock = new Object(); 711 AttachmentsSyncLock = new Object();
713 AllowMovement = true; 712 AllowMovement = true;
714 IsChildAgent = true; 713 IsChildAgent = true;
715 m_sendCoarseLocationsMethod = SendCoarseLocationsDefault; 714 m_sendCourseLocationsMethod = SendCoarseLocationsDefault;
716 Animator = new ScenePresenceAnimator(this); 715 Animator = new ScenePresenceAnimator(this);
717 PresenceType = type; 716 PresenceType = type;
718 DrawDistance = world.DefaultDrawDistance; 717 DrawDistance = world.DefaultDrawDistance;
@@ -976,9 +975,7 @@ namespace OpenSim.Region.Framework.Scenes
976 { 975 {
977 if (wasChild && HasAttachments()) 976 if (wasChild && HasAttachments())
978 { 977 {
979 m_log.DebugFormat( 978 m_log.DebugFormat("[SCENE PRESENCE]: Restarting scripts in attachments...");
980 "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name);
981
982 // Resume scripts 979 // Resume scripts
983 Util.FireAndForget(delegate(object x) { 980 Util.FireAndForget(delegate(object x) {
984 foreach (SceneObjectGroup sog in m_attachments) 981 foreach (SceneObjectGroup sog in m_attachments)
@@ -1534,22 +1531,17 @@ namespace OpenSim.Region.Framework.Scenes
1534 bool DCFlagKeyPressed = false; 1531 bool DCFlagKeyPressed = false;
1535 Vector3 agent_control_v3 = Vector3.Zero; 1532 Vector3 agent_control_v3 = Vector3.Zero;
1536 1533
1537 bool newFlying = actor.Flying; 1534 bool oldflying = Flying;
1538 1535
1539 if (ForceFly) 1536 if (ForceFly)
1540 newFlying = true; 1537 actor.Flying = true;
1541 else if (FlyDisabled) 1538 else if (FlyDisabled)
1542 newFlying = false; 1539 actor.Flying = false;
1543 else 1540 else
1544 newFlying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); 1541 actor.Flying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
1545 1542
1546 if (actor.Flying != newFlying) 1543 if (actor.Flying != oldflying)
1547 {
1548 // Note: ScenePresence.Flying is actually fetched from the physical actor
1549 // so setting PhysActor.Flying here also sets the ScenePresence's value.
1550 actor.Flying = newFlying;
1551 update_movementflag = true; 1544 update_movementflag = true;
1552 }
1553 1545
1554 if (ParentID == 0) 1546 if (ParentID == 0)
1555 { 1547 {
@@ -2631,17 +2623,17 @@ namespace OpenSim.Region.Framework.Scenes
2631 2623
2632 public void SendCoarseLocations(List<Vector3> coarseLocations, List<UUID> avatarUUIDs) 2624 public void SendCoarseLocations(List<Vector3> coarseLocations, List<UUID> avatarUUIDs)
2633 { 2625 {
2634 SendCoarseLocationsMethod d = m_sendCoarseLocationsMethod; 2626 SendCourseLocationsMethod d = m_sendCourseLocationsMethod;
2635 if (d != null) 2627 if (d != null)
2636 { 2628 {
2637 d.Invoke(m_scene.RegionInfo.originRegionID, this, coarseLocations, avatarUUIDs); 2629 d.Invoke(m_scene.RegionInfo.originRegionID, this, coarseLocations, avatarUUIDs);
2638 } 2630 }
2639 } 2631 }
2640 2632
2641 public void SetSendCoarseLocationMethod(SendCoarseLocationsMethod d) 2633 public void SetSendCourseLocationMethod(SendCourseLocationsMethod d)
2642 { 2634 {
2643 if (d != null) 2635 if (d != null)
2644 m_sendCoarseLocationsMethod = d; 2636 m_sendCourseLocationsMethod = d;
2645 } 2637 }
2646 2638
2647 public void SendCoarseLocationsDefault(UUID sceneId, ScenePresence p, List<Vector3> coarseLocations, List<UUID> avatarUUIDs) 2639 public void SendCoarseLocationsDefault(UUID sceneId, ScenePresence p, List<Vector3> coarseLocations, List<UUID> avatarUUIDs)
@@ -2845,7 +2837,7 @@ namespace OpenSim.Region.Framework.Scenes
2845 #region Significant Movement Method 2837 #region Significant Movement Method
2846 2838
2847 /// <summary> 2839 /// <summary>
2848 /// This checks for a significant movement and sends a coarselocationchange update 2840 /// This checks for a significant movement and sends a courselocationchange update
2849 /// </summary> 2841 /// </summary>
2850 protected void CheckForSignificantMovement() 2842 protected void CheckForSignificantMovement()
2851 { 2843 {
@@ -3282,7 +3274,6 @@ namespace OpenSim.Region.Framework.Scenes
3282 } 3274 }
3283 catch { } 3275 catch { }
3284 cAgent.DefaultAnim = Animator.Animations.DefaultAnimation; 3276 cAgent.DefaultAnim = Animator.Animations.DefaultAnimation;
3285 cAgent.AnimState = Animator.Animations.ImplicitDefaultAnimation;
3286 3277
3287 if (Scene.AttachmentsModule != null) 3278 if (Scene.AttachmentsModule != null)
3288 Scene.AttachmentsModule.CopyAttachments(this, cAgent); 3279 Scene.AttachmentsModule.CopyAttachments(this, cAgent);
@@ -3359,8 +3350,6 @@ namespace OpenSim.Region.Framework.Scenes
3359 Animator.Animations.FromArray(cAgent.Anims); 3350 Animator.Animations.FromArray(cAgent.Anims);
3360 if (cAgent.DefaultAnim != null) 3351 if (cAgent.DefaultAnim != null)
3361 Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero); 3352 Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero);
3362 if (cAgent.AnimState != null)
3363 Animator.Animations.SetImplicitDefaultAnimation(cAgent.AnimState.AnimID, cAgent.AnimState.SequenceNum, UUID.Zero);
3364 3353
3365 if (Scene.AttachmentsModule != null) 3354 if (Scene.AttachmentsModule != null)
3366 Scene.AttachmentsModule.CopyAttachments(cAgent, this); 3355 Scene.AttachmentsModule.CopyAttachments(cAgent, this);
@@ -3643,16 +3632,13 @@ namespace OpenSim.Region.Framework.Scenes
3643 public List<SceneObjectGroup> GetAttachments(uint attachmentPoint) 3632 public List<SceneObjectGroup> GetAttachments(uint attachmentPoint)
3644 { 3633 {
3645 List<SceneObjectGroup> attachments = new List<SceneObjectGroup>(); 3634 List<SceneObjectGroup> attachments = new List<SceneObjectGroup>();
3646 3635
3647 if (attachmentPoint >= 0) 3636 lock (m_attachments)
3648 { 3637 {
3649 lock (m_attachments) 3638 foreach (SceneObjectGroup so in m_attachments)
3650 { 3639 {
3651 foreach (SceneObjectGroup so in m_attachments) 3640 if (attachmentPoint == so.AttachmentPoint)
3652 { 3641 attachments.Add(so);
3653 if (attachmentPoint == so.AttachmentPoint)
3654 attachments.Add(so);
3655 }
3656 } 3642 }
3657 } 3643 }
3658 3644
diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
index 5398ab9..756b1f4 100644
--- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
+++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
@@ -47,7 +47,6 @@ namespace OpenSim.Region.Framework.Scenes
47 = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 47 = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
48 48
49 public const string LastReportedObjectUpdateStatName = "LastReportedObjectUpdates"; 49 public const string LastReportedObjectUpdateStatName = "LastReportedObjectUpdates";
50 public const string SlowFramesStatName = "SlowFrames";
51 50
52 public delegate void SendStatResult(SimStats stats); 51 public delegate void SendStatResult(SimStats stats);
53 52
@@ -130,16 +129,6 @@ namespace OpenSim.Region.Framework.Scenes
130 } 129 }
131 130
132 /// <summary> 131 /// <summary>
133 /// Number of frames that have taken longer to process than Scene.MIN_FRAME_TIME
134 /// </summary>
135 public Stat SlowFramesStat { get; private set; }
136
137 /// <summary>
138 /// The threshold at which we log a slow frame.
139 /// </summary>
140 public int SlowFramesStatReportThreshold { get; private set; }
141
142 /// <summary>
143 /// Extra sim statistics that are used by monitors but not sent to the client. 132 /// Extra sim statistics that are used by monitors but not sent to the client.
144 /// </summary> 133 /// </summary>
145 /// <value> 134 /// <value>
@@ -237,24 +226,6 @@ namespace OpenSim.Region.Framework.Scenes
237 226
238 if (StatsManager.SimExtraStats != null) 227 if (StatsManager.SimExtraStats != null)
239 OnSendStatsResult += StatsManager.SimExtraStats.ReceiveClassicSimStatsPacket; 228 OnSendStatsResult += StatsManager.SimExtraStats.ReceiveClassicSimStatsPacket;
240
241 /// At the moment, we'll only report if a frame is over 120% of target, since commonly frames are a bit
242 /// longer than ideal (which in itself is a concern).
243 SlowFramesStatReportThreshold = (int)Math.Ceiling(m_scene.MinFrameTime * 1000 * 1.2);
244
245 SlowFramesStat
246 = new Stat(
247 "SlowFrames",
248 "Slow Frames",
249 "Number of frames where frame time has been significantly longer than the desired frame time.",
250 " frames",
251 "scene",
252 m_scene.Name,
253 StatType.Push,
254 null,
255 StatVerbosity.Info);
256
257 StatsManager.RegisterStat(SlowFramesStat);
258 } 229 }
259 230
260 public void Close() 231 public void Close()
@@ -472,7 +443,6 @@ namespace OpenSim.Region.Framework.Scenes
472 lock (m_lastReportedExtraSimStats) 443 lock (m_lastReportedExtraSimStats)
473 { 444 {
474 m_lastReportedExtraSimStats[LastReportedObjectUpdateStatName] = m_objectUpdates / m_statsUpdateFactor; 445 m_lastReportedExtraSimStats[LastReportedObjectUpdateStatName] = m_objectUpdates / m_statsUpdateFactor;
475 m_lastReportedExtraSimStats[SlowFramesStat.ShortName] = (float)SlowFramesStat.Value;
476 446
477 Dictionary<string, float> physicsStats = m_scene.PhysicsScene.GetStats(); 447 Dictionary<string, float> physicsStats = m_scene.PhysicsScene.GetStats();
478 448
@@ -593,11 +563,6 @@ namespace OpenSim.Region.Framework.Scenes
593 public void addFrameMS(int ms) 563 public void addFrameMS(int ms)
594 { 564 {
595 m_frameMS += ms; 565 m_frameMS += ms;
596
597 // At the moment, we'll only report if a frame is over 120% of target, since commonly frames are a bit
598 // longer than ideal due to the inaccuracy of the Sleep in Scene.Update() (which in itself is a concern).
599 if (ms > SlowFramesStatReportThreshold)
600 SlowFramesStat.Value++;
601 } 566 }
602 567
603 public void addNetMS(int ms) 568 public void addNetMS(int ms)
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
index 5faf131..5758869 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
@@ -141,7 +141,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
141 TestScene scene = new SceneHelpers().SetupScene(); 141 TestScene scene = new SceneHelpers().SetupScene();
142 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); 142 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1));
143 143
144 scene.IncomingCloseAgent(sp.UUID, false); 144 scene.IncomingCloseAgent(sp.UUID);
145 145
146 Assert.That(scene.GetScenePresence(sp.UUID), Is.Null); 146 Assert.That(scene.GetScenePresence(sp.UUID), Is.Null);
147 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Null); 147 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Null);
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs
index ac3da1e..d722a09 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs
@@ -65,22 +65,5 @@ namespace OpenSim.Region.Framework.Scenes.Tests
65 65
66 Assert.That(scene.Frame, Is.EqualTo(1)); 66 Assert.That(scene.Frame, Is.EqualTo(1));
67 } 67 }
68
69 [Test]
70 public void TestShutdownScene()
71 {
72 TestHelpers.InMethod();
73
74 Scene scene = new SceneHelpers().SetupScene();
75 scene.Close();
76
77 Assert.That(scene.ShuttingDown, Is.True);
78 Assert.That(scene.Active, Is.False);
79
80 // Trying to update a shutdown scene should result in no update
81 scene.Update(1);
82
83 Assert.That(scene.Frame, Is.EqualTo(0));
84 }
85 } 68 }
86} \ No newline at end of file 69} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs
index 9457ebb..44d2d45 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs
@@ -50,41 +50,9 @@ using OpenSim.Tests.Common.Mock;
50namespace OpenSim.Region.Framework.Tests 50namespace OpenSim.Region.Framework.Tests
51{ 51{
52 [TestFixture] 52 [TestFixture]
53 public class UserInventoryTests : OpenSimTestCase 53 public class UserInventoryTests
54 { 54 {
55 [Test] 55 [Test]
56 public void TestCreateInventoryFolders()
57 {
58 TestHelpers.InMethod();
59// TestHelpers.EnableLogging();
60
61 // For this test both folders will have the same name which is legal in SL user inventories.
62 string foldersName = "f1";
63
64 Scene scene = new SceneHelpers().SetupScene();
65 UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001));
66
67 UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, user1.PrincipalID, foldersName);
68
69 List<InventoryFolderBase> oneFolder
70 = UserInventoryHelpers.GetInventoryFolders(scene.InventoryService, user1.PrincipalID, foldersName);
71
72 Assert.That(oneFolder.Count, Is.EqualTo(1));
73 InventoryFolderBase firstRetrievedFolder = oneFolder[0];
74 Assert.That(firstRetrievedFolder.Name, Is.EqualTo(foldersName));
75
76 UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, user1.PrincipalID, foldersName);
77
78 List<InventoryFolderBase> twoFolders
79 = UserInventoryHelpers.GetInventoryFolders(scene.InventoryService, user1.PrincipalID, foldersName);
80
81 Assert.That(twoFolders.Count, Is.EqualTo(2));
82 Assert.That(twoFolders[0].Name, Is.EqualTo(foldersName));
83 Assert.That(twoFolders[1].Name, Is.EqualTo(foldersName));
84 Assert.That(twoFolders[0].ID, Is.Not.EqualTo(twoFolders[1].ID));
85 }
86
87 [Test]
88 public void TestGiveInventoryItem() 56 public void TestGiveInventoryItem()
89 { 57 {
90 TestHelpers.InMethod(); 58 TestHelpers.InMethod();
@@ -115,7 +83,7 @@ namespace OpenSim.Region.Framework.Tests
115 public void TestGiveInventoryFolder() 83 public void TestGiveInventoryFolder()
116 { 84 {
117 TestHelpers.InMethod(); 85 TestHelpers.InMethod();
118// TestHelpers.EnableLogging(); 86// log4net.Config.XmlConfigurator.Configure();
119 87
120 Scene scene = new SceneHelpers().SetupScene(); 88 Scene scene = new SceneHelpers().SetupScene();
121 UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001)); 89 UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001));
diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
index 2279e62..411e421 100644
--- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
+++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
@@ -52,23 +52,26 @@ namespace OpenSim.Region.Framework.Scenes
52 public class UuidGatherer 52 public class UuidGatherer
53 { 53 {
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
55
56 /// <summary>
57 /// Asset cache used for gathering assets
58 /// </summary>
59 protected IAssetService m_assetCache;
60
61 /// <summary>
62 /// Used as a temporary store of an asset which represents an object. This can be a null if no appropriate
63 /// asset was found by the asset service.
64 /// </summary>
65 private AssetBase m_requestedObjectAsset;
55 66
56 protected IAssetService m_assetService; 67 /// <summary>
57 68 /// Signal whether we are currently waiting for the asset service to deliver an asset.
58// /// <summary> 69 /// </summary>
59// /// Used as a temporary store of an asset which represents an object. This can be a null if no appropriate 70 private bool m_waitingForObjectAsset;
60// /// asset was found by the asset service.
61// /// </summary>
62// private AssetBase m_requestedObjectAsset;
63//
64// /// <summary>
65// /// Signal whether we are currently waiting for the asset service to deliver an asset.
66// /// </summary>
67// private bool m_waitingForObjectAsset;
68 71
69 public UuidGatherer(IAssetService assetService) 72 public UuidGatherer(IAssetService assetCache)
70 { 73 {
71 m_assetService = assetService; 74 m_assetCache = assetCache;
72 } 75 }
73 76
74 /// <summary> 77 /// <summary>
@@ -188,18 +191,18 @@ namespace OpenSim.Region.Framework.Scenes
188 } 191 }
189 } 192 }
190 193
191// /// <summary> 194 /// <summary>
192// /// The callback made when we request the asset for an object from the asset service. 195 /// The callback made when we request the asset for an object from the asset service.
193// /// </summary> 196 /// </summary>
194// private void AssetReceived(string id, Object sender, AssetBase asset) 197 private void AssetReceived(string id, Object sender, AssetBase asset)
195// { 198 {
196// lock (this) 199 lock (this)
197// { 200 {
198// m_requestedObjectAsset = asset; 201 m_requestedObjectAsset = asset;
199// m_waitingForObjectAsset = false; 202 m_waitingForObjectAsset = false;
200// Monitor.Pulse(this); 203 Monitor.Pulse(this);
201// } 204 }
202// } 205 }
203 206
204 /// <summary> 207 /// <summary>
205 /// Get an asset synchronously, potentially using an asynchronous callback. If the 208 /// Get an asset synchronously, potentially using an asynchronous callback. If the
@@ -209,29 +212,25 @@ namespace OpenSim.Region.Framework.Scenes
209 /// <returns></returns> 212 /// <returns></returns>
210 protected virtual AssetBase GetAsset(UUID uuid) 213 protected virtual AssetBase GetAsset(UUID uuid)
211 { 214 {
212 return m_assetService.Get(uuid.ToString()); 215 m_waitingForObjectAsset = true;
216 m_assetCache.Get(uuid.ToString(), this, AssetReceived);
217
218 // The asset cache callback can either
219 //
220 // 1. Complete on the same thread (if the asset is already in the cache) or
221 // 2. Come in via a different thread (if we need to go fetch it).
222 //
223 // The code below handles both these alternatives.
224 lock (this)
225 {
226 if (m_waitingForObjectAsset)
227 {
228 Monitor.Wait(this);
229 m_waitingForObjectAsset = false;
230 }
231 }
213 232
214 // XXX: Switching to do this synchronously where the call was async before but we always waited for it 233 return m_requestedObjectAsset;
215 // to complete anyway!
216// m_waitingForObjectAsset = true;
217// m_assetCache.Get(uuid.ToString(), this, AssetReceived);
218//
219// // The asset cache callback can either
220// //
221// // 1. Complete on the same thread (if the asset is already in the cache) or
222// // 2. Come in via a different thread (if we need to go fetch it).
223// //
224// // The code below handles both these alternatives.
225// lock (this)
226// {
227// if (m_waitingForObjectAsset)
228// {
229// Monitor.Wait(this);
230// m_waitingForObjectAsset = false;
231// }
232// }
233//
234// return m_requestedObjectAsset;
235 } 234 }
236 235
237 /// <summary> 236 /// <summary>
@@ -362,47 +361,4 @@ namespace OpenSim.Region.Framework.Scenes
362 } 361 }
363 } 362 }
364 } 363 }
365
366 public class HGUuidGatherer : UuidGatherer
367 {
368 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
369
370 protected string m_assetServerURL;
371
372 public HGUuidGatherer(IAssetService assetService, string assetServerURL)
373 : base(assetService)
374 {
375 m_assetServerURL = assetServerURL;
376 if (!m_assetServerURL.EndsWith("/") && !m_assetServerURL.EndsWith("="))
377 m_assetServerURL = m_assetServerURL + "/";
378 }
379
380 protected override AssetBase GetAsset(UUID uuid)
381 {
382 if (string.Empty == m_assetServerURL)
383 return base.GetAsset(uuid);
384 else
385 return FetchAsset(uuid);
386 }
387
388 public AssetBase FetchAsset(UUID assetID)
389 {
390
391 // Test if it's already here
392 AssetBase asset = m_assetService.Get(assetID.ToString());
393 if (asset == null)
394 {
395 // It's not, so fetch it from abroad
396 asset = m_assetService.Get(m_assetServerURL + assetID.ToString());
397 if (asset != null)
398 m_log.DebugFormat("[HGUUIDGatherer]: Copied asset {0} from {1} to local asset server", assetID, m_assetServerURL);
399 else
400 m_log.DebugFormat("[HGUUIDGatherer]: Failed to fetch asset {0} from {1}", assetID, m_assetServerURL);
401 }
402 //else
403 // m_log.DebugFormat("[HGUUIDGatherer]: Asset {0} from {1} was already here", assetID, m_assetServerURL);
404
405 return asset;
406 }
407 }
408} 364}
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
index 254eeb4..28b8293 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
@@ -891,10 +891,10 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
891 891
892 public void Close() 892 public void Close()
893 { 893 {
894 Close(true, false); 894 Close(true);
895 } 895 }
896 896
897 public void Close(bool sendStop, bool force) 897 public void Close(bool sendStop)
898 { 898 {
899 Disconnect(); 899 Disconnect();
900 } 900 }
@@ -959,8 +959,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
959 959
960 } 960 }
961 961
962 public void SendChatMessage( 962 public void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, byte source, byte audible)
963 string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, UUID ownerID, byte source, byte audible)
964 { 963 {
965 if (audible > 0 && message.Length > 0) 964 if (audible > 0 && message.Length > 0)
966 IRC_SendChannelPrivmsg(fromName, message); 965 IRC_SendChannelPrivmsg(fromName, message);
diff --git a/OpenSim/Region/OptionalModules/Asset/AssetInfoModule.cs b/OpenSim/Region/OptionalModules/Asset/AssetInfoModule.cs
index 7639c6c..41ec14f 100644
--- a/OpenSim/Region/OptionalModules/Asset/AssetInfoModule.cs
+++ b/OpenSim/Region/OptionalModules/Asset/AssetInfoModule.cs
@@ -127,9 +127,6 @@ namespace OpenSim.Region.OptionalModules.Asset
127 } 127 }
128 128
129 string fileName = rawAssetId; 129 string fileName = rawAssetId;
130
131 if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, fileName))
132 return;
133 130
134 using (FileStream fs = new FileStream(fileName, FileMode.CreateNew)) 131 using (FileStream fs = new FileStream(fileName, FileMode.CreateNew))
135 { 132 {
diff --git a/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs b/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs
index 68bcb4a..d68aabc 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs
@@ -146,7 +146,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
146 sb.AppendFormat("Attachments for {0}\n", sp.Name); 146 sb.AppendFormat("Attachments for {0}\n", sp.Name);
147 147
148 ConsoleDisplayTable ct = new ConsoleDisplayTable() { Indent = 2 }; 148 ConsoleDisplayTable ct = new ConsoleDisplayTable() { Indent = 2 };
149 ct.Columns.Add(new ConsoleDisplayTableColumn("Attachment Name", 50)); 149 ct.Columns.Add(new ConsoleDisplayTableColumn("Attachment Name", 36));
150 ct.Columns.Add(new ConsoleDisplayTableColumn("Local ID", 10)); 150 ct.Columns.Add(new ConsoleDisplayTableColumn("Local ID", 10));
151 ct.Columns.Add(new ConsoleDisplayTableColumn("Item ID", 36)); 151 ct.Columns.Add(new ConsoleDisplayTableColumn("Item ID", 36));
152 ct.Columns.Add(new ConsoleDisplayTableColumn("Attach Point", 14)); 152 ct.Columns.Add(new ConsoleDisplayTableColumn("Attach Point", 14));
diff --git a/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs b/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs
index 17971e3..31d0034 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs
@@ -130,37 +130,37 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
130 SendConsoleOutput(agentID, String.Format("auto_grant_attach_perms set to {0}", val)); 130 SendConsoleOutput(agentID, String.Format("auto_grant_attach_perms set to {0}", val));
131 } 131 }
132 132
133 private int llAttachToAvatarTemp(UUID host, UUID script, int attachmentPoint) 133 private void llAttachToAvatarTemp(UUID host, UUID script, int attachmentPoint)
134 { 134 {
135 SceneObjectPart hostPart = m_scene.GetSceneObjectPart(host); 135 SceneObjectPart hostPart = m_scene.GetSceneObjectPart(host);
136 136
137 if (hostPart == null) 137 if (hostPart == null)
138 return 0; 138 return;
139 139
140 if (hostPart.ParentGroup.IsAttachment) 140 if (hostPart.ParentGroup.IsAttachment)
141 return 0; 141 return;
142 142
143 IAttachmentsModule attachmentsModule = m_scene.RequestModuleInterface<IAttachmentsModule>(); 143 IAttachmentsModule attachmentsModule = m_scene.RequestModuleInterface<IAttachmentsModule>();
144 if (attachmentsModule == null) 144 if (attachmentsModule == null)
145 return 0; 145 return;
146 146
147 TaskInventoryItem item = hostPart.Inventory.GetInventoryItem(script); 147 TaskInventoryItem item = hostPart.Inventory.GetInventoryItem(script);
148 if (item == null) 148 if (item == null)
149 return 0; 149 return;
150 150
151 if ((item.PermsMask & 32) == 0) // PERMISSION_ATTACH 151 if ((item.PermsMask & 32) == 0) // PERMISSION_ATTACH
152 return 0; 152 return;
153 153
154 ScenePresence target; 154 ScenePresence target;
155 if (!m_scene.TryGetScenePresence(item.PermsGranter, out target)) 155 if (!m_scene.TryGetScenePresence(item.PermsGranter, out target))
156 return 0; 156 return;
157 157
158 if (target.UUID != hostPart.ParentGroup.OwnerID) 158 if (target.UUID != hostPart.ParentGroup.OwnerID)
159 { 159 {
160 uint effectivePerms = hostPart.ParentGroup.GetEffectivePermissions(); 160 uint effectivePerms = hostPart.ParentGroup.GetEffectivePermissions();
161 161
162 if ((effectivePerms & (uint)PermissionMask.Transfer) == 0) 162 if ((effectivePerms & (uint)PermissionMask.Transfer) == 0)
163 return 0; 163 return;
164 164
165 hostPart.ParentGroup.SetOwnerId(target.UUID); 165 hostPart.ParentGroup.SetOwnerId(target.UUID);
166 hostPart.ParentGroup.SetRootPartOwner(hostPart.ParentGroup.RootPart, target.UUID, target.ControllingClient.ActiveGroupId); 166 hostPart.ParentGroup.SetRootPartOwner(hostPart.ParentGroup.RootPart, target.UUID, target.ControllingClient.ActiveGroupId);
@@ -183,7 +183,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
183 hostPart.ParentGroup.RootPart.ScheduleFullUpdate(); 183 hostPart.ParentGroup.RootPart.ScheduleFullUpdate();
184 } 184 }
185 185
186 return attachmentsModule.AttachObject(target, hostPart.ParentGroup, (uint)attachmentPoint, false, true, true) ? 1 : 0; 186 attachmentsModule.AttachObject(target, hostPart.ParentGroup, (uint)attachmentPoint, false, true, true);
187 } 187 }
188 } 188 }
189} 189}
diff --git a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs
index a014798..ca956fb 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs
@@ -231,12 +231,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat
231 if (m_server == null || m_baseNick == null || m_ircChannel == null || m_user == null) 231 if (m_server == null || m_baseNick == null || m_ircChannel == null || m_user == null)
232 throw new Exception("Invalid connector configuration"); 232 throw new Exception("Invalid connector configuration");
233 233
234 // Generate an initial nickname 234 // Generate an initial nickname if randomizing is enabled
235 235
236 if (m_randomizeNick) 236 if (m_randomizeNick)
237 {
237 m_nick = m_baseNick + Util.RandomClass.Next(1, 99); 238 m_nick = m_baseNick + Util.RandomClass.Next(1, 99);
238 else 239 }
239 m_nick = m_baseNick;
240 240
241 m_log.InfoFormat("[IRC-Connector-{0}]: Initialization complete", idn); 241 m_log.InfoFormat("[IRC-Connector-{0}]: Initialization complete", idn);
242 242
diff --git a/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs b/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs
index 5c3be29..e22618d 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs
@@ -546,9 +546,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Concierge
546 c.SenderUUID = UUID.Zero; 546 c.SenderUUID = UUID.Zero;
547 c.Scene = agent.Scene; 547 c.Scene = agent.Scene;
548 548
549 agent.ControllingClient.SendChatMessage( 549 agent.ControllingClient.SendChatMessage(msg, (byte) ChatTypeEnum.Say, PosOfGod, m_whoami, UUID.Zero,
550 msg, (byte) ChatTypeEnum.Say, PosOfGod, m_whoami, UUID.Zero, UUID.Zero, 550 (byte)ChatSourceType.Object, (byte)ChatAudibleLevel.Fully);
551 (byte)ChatSourceType.Object, (byte)ChatAudibleLevel.Fully);
552 } 551 }
553 552
554 private static void checkStringParameters(XmlRpcRequest request, string[] param) 553 private static void checkStringParameters(XmlRpcRequest request, string[] param)
diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs
index f292a75..7b20446 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs
@@ -447,7 +447,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
447 // settings allow voice, then whether parcel allows 447 // settings allow voice, then whether parcel allows
448 // voice, if all do retrieve or obtain the parcel 448 // voice, if all do retrieve or obtain the parcel
449 // voice channel 449 // voice channel
450 LandData land = scene.GetLandData(avatar.AbsolutePosition); 450 LandData land = scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
451 451
452 //m_log.DebugFormat("[FreeSwitchVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": request: {4}, path: {5}, param: {6}", 452 //m_log.DebugFormat("[FreeSwitchVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": request: {4}, path: {5}, param: {6}",
453 // scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, request, path, param); 453 // scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, request, path, param);
diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs
index 8a8a31c..a30a38d 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs
@@ -623,7 +623,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
623 // settings allow voice, then whether parcel allows 623 // settings allow voice, then whether parcel allows
624 // voice, if all do retrieve or obtain the parcel 624 // voice, if all do retrieve or obtain the parcel
625 // voice channel 625 // voice channel
626 LandData land = scene.GetLandData(avatar.AbsolutePosition); 626 LandData land = scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
627 627
628// m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": request: {4}, path: {5}, param: {6}", 628// m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": request: {4}, path: {5}, param: {6}",
629// scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, request, path, param); 629// scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, request, path, param);
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs
index 1528330..10b83e6 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs
@@ -27,7 +27,6 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Linq;
31using System.Reflection; 30using System.Reflection;
32using log4net; 31using log4net;
33using Mono.Addins; 32using Mono.Addins;
@@ -37,8 +36,6 @@ using OpenMetaverse.StructuredData;
37using OpenSim.Framework; 36using OpenSim.Framework;
38using OpenSim.Region.Framework.Interfaces; 37using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes; 38using OpenSim.Region.Framework.Scenes;
40using OpenSim.Services.Interfaces;
41using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
42 39
43namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups 40namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
44{ 41{
@@ -48,7 +45,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49 46
50 private List<Scene> m_sceneList = new List<Scene>(); 47 private List<Scene> m_sceneList = new List<Scene>();
51 private IPresenceService m_presenceService;
52 48
53 private IMessageTransferModule m_msgTransferModule = null; 49 private IMessageTransferModule m_msgTransferModule = null;
54 50
@@ -58,27 +54,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
58 private bool m_groupMessagingEnabled = false; 54 private bool m_groupMessagingEnabled = false;
59 private bool m_debugEnabled = true; 55 private bool m_debugEnabled = true;
60 56
61 /// <summary>
62 /// If enabled, module only tries to send group IMs to online users by querying cached presence information.
63 /// </summary>
64 private bool m_messageOnlineAgentsOnly;
65
66 /// <summary>
67 /// Cache for online users.
68 /// </summary>
69 /// <remarks>
70 /// Group ID is key, presence information for online members is value.
71 /// Will only be non-null if m_messageOnlineAgentsOnly = true
72 /// We cache here so that group messages don't constantly have to re-request the online user list to avoid
73 /// attempted expensive sending of messages to offline users.
74 /// The tradeoff is that a user that comes online will not receive messages consistently from all other users
75 /// until caches have updated.
76 /// Therefore, we set the cache expiry to just 20 seconds.
77 /// </remarks>
78 private ExpiringCache<UUID, PresenceInfo[]> m_usersOnlineCache;
79
80 private int m_usersOnlineCacheExpirySeconds = 20;
81
82 #region IRegionModuleBase Members 57 #region IRegionModuleBase Members
83 58
84 public void Initialise(IConfigSource config) 59 public void Initialise(IConfigSource config)
@@ -108,17 +83,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
108 return; 83 return;
109 } 84 }
110 85
111 m_messageOnlineAgentsOnly = groupsConfig.GetBoolean("MessageOnlineUsersOnly", false);
112
113 if (m_messageOnlineAgentsOnly)
114 m_usersOnlineCache = new ExpiringCache<UUID, PresenceInfo[]>();
115
116 m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", true); 86 m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", true);
117 } 87 }
118 88
119 m_log.InfoFormat( 89 m_log.Info("[GROUPS-MESSAGING]: GroupsMessagingModule starting up");
120 "[GROUPS-MESSAGING]: GroupsMessagingModule enabled with MessageOnlineOnly = {0}, DebugEnabled = {1}",
121 m_messageOnlineAgentsOnly, m_debugEnabled);
122 } 90 }
123 91
124 public void AddRegion(Scene scene) 92 public void AddRegion(Scene scene)
@@ -158,8 +126,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
158 return; 126 return;
159 } 127 }
160 128
161 if (m_presenceService == null)
162 m_presenceService = scene.PresenceService;
163 129
164 m_sceneList.Add(scene); 130 m_sceneList.Add(scene);
165 131
@@ -241,42 +207,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
241 public void SendMessageToGroup(GridInstantMessage im, UUID groupID) 207 public void SendMessageToGroup(GridInstantMessage im, UUID groupID)
242 { 208 {
243 List<GroupMembersData> groupMembers = m_groupData.GetGroupMembers(new UUID(im.fromAgentID), groupID); 209 List<GroupMembersData> groupMembers = m_groupData.GetGroupMembers(new UUID(im.fromAgentID), groupID);
244 int groupMembersCount = groupMembers.Count; 210
245 211 if (m_debugEnabled)
246 if (m_messageOnlineAgentsOnly) 212 m_log.DebugFormat(
247 { 213 "[GROUPS-MESSAGING]: SendMessageToGroup called for group {0} with {1} visible members",
248 string[] t1 = groupMembers.ConvertAll<string>(gmd => gmd.AgentID.ToString()).ToArray(); 214 groupID, groupMembers.Count);
249 215
250 // We cache in order not to overwhlem the presence service on large grids with many groups. This does
251 // mean that members coming online will not see all group members until after m_usersOnlineCacheExpirySeconds has elapsed.
252 // (assuming this is the same across all grid simulators).
253 PresenceInfo[] onlineAgents;
254 if (!m_usersOnlineCache.TryGetValue(groupID, out onlineAgents))
255 {
256 onlineAgents = m_presenceService.GetAgents(t1);
257 m_usersOnlineCache.Add(groupID, onlineAgents, m_usersOnlineCacheExpirySeconds);
258 }
259
260 HashSet<string> onlineAgentsUuidSet = new HashSet<string>();
261 Array.ForEach<PresenceInfo>(onlineAgents, pi => onlineAgentsUuidSet.Add(pi.UserID));
262
263 groupMembers = groupMembers.Where(gmd => onlineAgentsUuidSet.Contains(gmd.AgentID.ToString())).ToList();
264
265 // if (m_debugEnabled)
266// m_log.DebugFormat(
267// "[GROUPS-MESSAGING]: SendMessageToGroup called for group {0} with {1} visible members, {2} online",
268// groupID, groupMembersCount, groupMembers.Count());
269 }
270 else
271 {
272 if (m_debugEnabled)
273 m_log.DebugFormat(
274 "[GROUPS-MESSAGING]: SendMessageToGroup called for group {0} with {1} visible members",
275 groupID, groupMembers.Count);
276 }
277
278 int requestStartTick = Environment.TickCount;
279
280 foreach (GroupMembersData member in groupMembers) 216 foreach (GroupMembersData member in groupMembers)
281 { 217 {
282 if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID, groupID)) 218 if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID, groupID))
@@ -318,12 +254,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
318 ProcessMessageFromGroupSession(msg); 254 ProcessMessageFromGroupSession(msg);
319 } 255 }
320 } 256 }
321
322 // Temporary for assessing how long it still takes to send messages to large online groups.
323 if (m_messageOnlineAgentsOnly)
324 m_log.DebugFormat(
325 "[GROUPS-MESSAGING]: SendMessageToGroup for group {0} with {1} visible members, {2} online took {3}ms",
326 groupID, groupMembersCount, groupMembers.Count(), Environment.TickCount - requestStartTick);
327 } 257 }
328 258
329 #region SimGridEventHandlers 259 #region SimGridEventHandlers
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
index 79e9994..65bd26c 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
@@ -123,36 +123,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
123 public void AddRegion(Scene scene) 123 public void AddRegion(Scene scene)
124 { 124 {
125 if (m_groupsEnabled) 125 if (m_groupsEnabled)
126 {
127 scene.RegisterModuleInterface<IGroupsModule>(this); 126 scene.RegisterModuleInterface<IGroupsModule>(this);
128 scene.AddCommand(
129 "debug",
130 this,
131 "debug groups verbose",
132 "debug groups verbose <true|false>",
133 "This setting turns on very verbose groups debugging",
134 HandleDebugGroupsVerbose);
135 }
136 }
137
138 private void HandleDebugGroupsVerbose(object modules, string[] args)
139 {
140 if (args.Length < 4)
141 {
142 MainConsole.Instance.Output("Usage: debug groups verbose <true|false>");
143 return;
144 }
145
146 bool verbose = false;
147 if (!bool.TryParse(args[3], out verbose))
148 {
149 MainConsole.Instance.Output("Usage: debug groups verbose <true|false>");
150 return;
151 }
152
153 m_debugEnabled = verbose;
154
155 MainConsole.Instance.OutputFormat("{0} verbose logging set to {1}", Name, m_debugEnabled);
156 } 127 }
157 128
158 public void RegionLoaded(Scene scene) 129 public void RegionLoaded(Scene scene)
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs
index 732c28f..311531c 100644
--- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs
@@ -175,15 +175,14 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
175 /// 175 ///
176 /// </summary> 176 /// </summary>
177 // ----------------------------------------------------------------- 177 // -----------------------------------------------------------------
178 public bool CreateStore(string value, ref UUID result) 178 public bool CreateStore(string value, out UUID result)
179 { 179 {
180 if (result == UUID.Zero) 180 result = UUID.Zero;
181 result = UUID.Random();
182
183 JsonStore map = null;
184 181
185 if (! m_enabled) return false; 182 if (! m_enabled) return false;
186 183
184 UUID uuid = UUID.Random();
185 JsonStore map = null;
187 186
188 try 187 try
189 { 188 {
@@ -196,8 +195,9 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
196 } 195 }
197 196
198 lock (m_JsonValueStore) 197 lock (m_JsonValueStore)
199 m_JsonValueStore.Add(result,map); 198 m_JsonValueStore.Add(uuid,map);
200 199
200 result = uuid;
201 return true; 201 return true;
202 } 202 }
203 203
@@ -231,7 +231,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
231 if (! m_JsonValueStore.TryGetValue(storeID,out map)) 231 if (! m_JsonValueStore.TryGetValue(storeID,out map))
232 { 232 {
233 m_log.InfoFormat("[JsonStore] Missing store {0}",storeID); 233 m_log.InfoFormat("[JsonStore] Missing store {0}",storeID);
234 return false; 234 return true;
235 } 235 }
236 } 236 }
237 237
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs
index 6910d14..eaba816 100644
--- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs
@@ -227,7 +227,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
227 protected UUID JsonCreateStore(UUID hostID, UUID scriptID, string value) 227 protected UUID JsonCreateStore(UUID hostID, UUID scriptID, string value)
228 { 228 {
229 UUID uuid = UUID.Zero; 229 UUID uuid = UUID.Zero;
230 if (! m_store.CreateStore(value, ref uuid)) 230 if (! m_store.CreateStore(value, out uuid))
231 GenerateRuntimeError("Failed to create Json store"); 231 GenerateRuntimeError("Failed to create Json store");
232 232
233 return uuid; 233 return uuid;
diff --git a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs
index 5ed1514..aa23fee 100644
--- a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs
@@ -821,11 +821,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule
821 { 821 {
822 if (!CanEdit()) 822 if (!CanEdit())
823 return; 823 return;
824 ISoundModule module = m_rootScene.RequestModuleInterface<ISoundModule>(); 824
825 if (module != null) 825 GetSOP().SendSound(asset.ToString(), volume, true, 0, 0, false, false);
826 {
827 module.SendSound(GetSOP().UUID, asset, volume, true, 0, 0, false, false);
828 }
829 } 826 }
830 827
831 #endregion 828 #endregion
diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs
index bad75f7..fff3a32 100644
--- a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs
@@ -181,7 +181,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady
181 } 181 }
182 } 182 }
183 183
184 void OnOarFileLoaded(Guid requestId, List<UUID> loadedScenes, string message) 184 void OnOarFileLoaded(Guid requestId, string message)
185 { 185 {
186 m_oarFileLoading = true; 186 m_oarFileLoading = true;
187 187
diff --git a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
index dc54c3f..c5c96a9 100644
--- a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
@@ -130,25 +130,13 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms
130 m_scriptModule.PostScriptEvent(script, "link_message", args); 130 m_scriptModule.PostScriptEvent(script, "link_message", args);
131 } 131 }
132 132
133 private static MethodInfo GetMethodInfoFromType(Type target, string meth, bool searchInstanceMethods)
134 {
135 BindingFlags getMethodFlags =
136 BindingFlags.NonPublic | BindingFlags.Public;
137
138 if (searchInstanceMethods)
139 getMethodFlags |= BindingFlags.Instance;
140 else
141 getMethodFlags |= BindingFlags.Static;
142
143 return target.GetMethod(meth, getMethodFlags);
144 }
145
146 public void RegisterScriptInvocation(object target, string meth) 133 public void RegisterScriptInvocation(object target, string meth)
147 { 134 {
148 MethodInfo mi = GetMethodInfoFromType(target.GetType(), meth, true); 135 MethodInfo mi = target.GetType().GetMethod(meth,
136 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
149 if (mi == null) 137 if (mi == null)
150 { 138 {
151 m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}", meth); 139 m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}",meth);
152 return; 140 return;
153 } 141 }
154 142
@@ -163,71 +151,38 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms
163 151
164 public void RegisterScriptInvocation(object target, MethodInfo mi) 152 public void RegisterScriptInvocation(object target, MethodInfo mi)
165 { 153 {
166 m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, (target is Type) ? ((Type)target).Name : target.GetType().Name); 154 m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, target.GetType().Name);
167 155
168 Type delegateType; 156 Type delegateType;
169 List<Type> typeArgs = mi.GetParameters() 157 var typeArgs = mi.GetParameters()
170 .Select(p => p.ParameterType) 158 .Select(p => p.ParameterType)
171 .ToList(); 159 .ToList();
172 160
173 if (mi.ReturnType == typeof(void)) 161 if (mi.ReturnType == typeof(void))
174 { 162 {
175 delegateType = Expression.GetActionType(typeArgs.ToArray()); 163 delegateType = Expression.GetActionType(typeArgs.ToArray());
176 } 164 }
177 else 165 else
178 { 166 {
179 typeArgs.Add(mi.ReturnType); 167 typeArgs.Add(mi.ReturnType);
180 delegateType = Expression.GetFuncType(typeArgs.ToArray()); 168 delegateType = Expression.GetFuncType(typeArgs.ToArray());
181 } 169 }
182 170
183 Delegate fcall; 171 Delegate fcall = Delegate.CreateDelegate(delegateType, target, mi);
184 if (!(target is Type))
185 fcall = Delegate.CreateDelegate(delegateType, target, mi);
186 else
187 fcall = Delegate.CreateDelegate(delegateType, (Type)target, mi.Name);
188 172
189 lock (m_scriptInvocation) 173 lock (m_scriptInvocation)
190 { 174 {
191 ParameterInfo[] parameters = fcall.Method.GetParameters(); 175 ParameterInfo[] parameters = fcall.Method.GetParameters ();
192 if (parameters.Length < 2) // Must have two UUID params 176 if (parameters.Length < 2) // Must have two UUID params
193 return; 177 return;
194 178
195 // Hide the first two parameters 179 // Hide the first two parameters
196 Type[] parmTypes = new Type[parameters.Length - 2]; 180 Type[] parmTypes = new Type[parameters.Length - 2];
197 for (int i = 2; i < parameters.Length; i++) 181 for (int i = 2 ; i < parameters.Length ; i++)
198 parmTypes[i - 2] = parameters[i].ParameterType; 182 parmTypes[i - 2] = parameters[i].ParameterType;
199 m_scriptInvocation[fcall.Method.Name] = new ScriptInvocationData(fcall.Method.Name, fcall, parmTypes, fcall.Method.ReturnType); 183 m_scriptInvocation[fcall.Method.Name] = new ScriptInvocationData(fcall.Method.Name, fcall, parmTypes, fcall.Method.ReturnType);
200 } 184 }
201 } 185 }
202
203 public void RegisterScriptInvocation(Type target, string[] methods)
204 {
205 foreach (string method in methods)
206 {
207 MethodInfo mi = GetMethodInfoFromType(target, method, false);
208 if (mi == null)
209 m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}", method);
210 else
211 RegisterScriptInvocation(target, mi);
212 }
213 }
214
215 public void RegisterScriptInvocations(IRegionModuleBase target)
216 {
217 foreach(MethodInfo method in target.GetType().GetMethods(
218 BindingFlags.Public | BindingFlags.Instance |
219 BindingFlags.Static))
220 {
221 if(method.GetCustomAttributes(
222 typeof(ScriptInvocationAttribute), true).Any())
223 {
224 if(method.IsStatic)
225 RegisterScriptInvocation(target.GetType(), method);
226 else
227 RegisterScriptInvocation(target, method);
228 }
229 }
230 }
231 186
232 public Delegate[] GetScriptInvocationList() 187 public Delegate[] GetScriptInvocationList()
233 { 188 {
@@ -330,20 +285,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms
330 } 285 }
331 } 286 }
332 287
333 public void RegisterConstants(IRegionModuleBase target)
334 {
335 foreach (FieldInfo field in target.GetType().GetFields(
336 BindingFlags.Public | BindingFlags.Static |
337 BindingFlags.Instance))
338 {
339 if (field.GetCustomAttributes(
340 typeof(ScriptConstantAttribute), true).Any())
341 {
342 RegisterConstant(field.Name, field.GetValue(target));
343 }
344 }
345 }
346
347 /// <summary> 288 /// <summary>
348 /// Operation to check for a registered constant 289 /// Operation to check for a registered constant
349 /// </summary> 290 /// </summary>
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
index 3a03101..6c8e2fc 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
@@ -148,7 +148,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
148 OnInstantMessage(this, new GridInstantMessage(m_scene, 148 OnInstantMessage(this, new GridInstantMessage(m_scene,
149 m_uuid, m_firstname + " " + m_lastname, 149 m_uuid, m_firstname + " " + m_lastname,
150 target, 0, false, message, 150 target, 0, false, message,
151 UUID.Zero, false, Position, new byte[0], true)); 151 UUID.Zero, false, Position, new byte[0]));
152 } 152 }
153 153
154 public void SendAgentOffline(UUID[] agentIDs) 154 public void SendAgentOffline(UUID[] agentIDs)
@@ -607,15 +607,13 @@ namespace OpenSim.Region.OptionalModules.World.NPC
607 { 607 {
608 } 608 }
609 609
610 public virtual void SendChatMessage( 610 public virtual void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName,
611 string message, byte type, Vector3 fromPos, string fromName, 611 UUID fromAgentID, byte source, byte audible)
612 UUID fromAgentID, UUID ownerID, byte source, byte audible)
613 { 612 {
614 } 613 }
615 614
616 public virtual void SendChatMessage( 615 public virtual void SendChatMessage(byte[] message, byte type, Vector3 fromPos, string fromName,
617 byte[] message, byte type, Vector3 fromPos, string fromName, 616 UUID fromAgentID, byte source, byte audible)
618 UUID fromAgentID, UUID ownerID, byte source, byte audible)
619 { 617 {
620 } 618 }
621 619
@@ -911,13 +909,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC
911 909
912 public void Close() 910 public void Close()
913 { 911 {
914 Close(true, false); 912 Close(true);
915 } 913 }
916 914
917 public void Close(bool sendStop, bool force) 915 public void Close(bool sendStop)
918 { 916 {
919 // Remove ourselves from the scene
920 m_scene.RemoveClient(AgentId, false);
921 } 917 }
922 918
923 public void Start() 919 public void Start()
diff --git a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
index 52ed846..9179966 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
@@ -117,12 +117,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
117 Assert.That(npc, Is.Not.Null); 117 Assert.That(npc, Is.Not.Null);
118 Assert.That(npc.Appearance.Texture.FaceTextures[8].TextureID, Is.EqualTo(originalFace8TextureId)); 118 Assert.That(npc.Appearance.Texture.FaceTextures[8].TextureID, Is.EqualTo(originalFace8TextureId));
119 Assert.That(m_umMod.GetUserName(npc.UUID), Is.EqualTo(string.Format("{0} {1}", npc.Firstname, npc.Lastname))); 119 Assert.That(m_umMod.GetUserName(npc.UUID), Is.EqualTo(string.Format("{0} {1}", npc.Firstname, npc.Lastname)));
120
121 IClientAPI client;
122 Assert.That(m_scene.TryGetClient(npcId, out client), Is.True);
123
124 // Have to account for both SP and NPC.
125 Assert.That(m_scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(2));
126 } 120 }
127 121
128 [Test] 122 [Test]
@@ -142,11 +136,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
142 ScenePresence deletedNpc = m_scene.GetScenePresence(npcId); 136 ScenePresence deletedNpc = m_scene.GetScenePresence(npcId);
143 137
144 Assert.That(deletedNpc, Is.Null); 138 Assert.That(deletedNpc, Is.Null);
145 IClientAPI client;
146 Assert.That(m_scene.TryGetClient(npcId, out client), Is.False);
147
148 // Have to account for SP still present.
149 Assert.That(m_scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1));
150 } 139 }
151 140
152 [Test] 141 [Test]
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs
index 23ef052..683bc51 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs
@@ -32,14 +32,10 @@ using OpenMetaverse;
32namespace OpenSim.Region.Physics.BulletSPlugin 32namespace OpenSim.Region.Physics.BulletSPlugin
33{ 33{
34 34
35public sealed class BSConstraint6Dof : BSConstraint 35public class BS6DofConstraint : BSConstraint
36{ 36{
37 private static string LogHeader = "[BULLETSIM 6DOF CONSTRAINT]";
38
39 public override ConstraintType Type { get { return ConstraintType.D6_CONSTRAINT_TYPE; } }
40
41 // Create a btGeneric6DofConstraint 37 // Create a btGeneric6DofConstraint
42 public BSConstraint6Dof(BulletSim world, BulletBody obj1, BulletBody obj2, 38 public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2,
43 Vector3 frame1, Quaternion frame1rot, 39 Vector3 frame1, Quaternion frame1rot,
44 Vector3 frame2, Quaternion frame2rot, 40 Vector3 frame2, Quaternion frame2rot,
45 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) 41 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
@@ -48,52 +44,25 @@ public sealed class BSConstraint6Dof : BSConstraint
48 m_body1 = obj1; 44 m_body1 = obj1;
49 m_body2 = obj2; 45 m_body2 = obj2;
50 m_constraint = new BulletConstraint( 46 m_constraint = new BulletConstraint(
51 BulletSimAPI.Create6DofConstraint2(m_world.ptr, m_body1.ptr, m_body2.ptr, 47 BulletSimAPI.Create6DofConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr,
52 frame1, frame1rot, 48 frame1, frame1rot,
53 frame2, frame2rot, 49 frame2, frame2rot,
54 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); 50 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
55 m_enabled = true; 51 m_enabled = true;
56 world.physicsScene.DetailLog("{0},BS6DofConstraint,createFrame,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}",
57 BSScene.DetailLogZero, world.worldID,
58 obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X"));
59 } 52 }
60 53
61 public BSConstraint6Dof(BulletSim world, BulletBody obj1, BulletBody obj2, 54 public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2,
62 Vector3 joinPoint, 55 Vector3 joinPoint,
63 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) 56 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
64 { 57 {
65 m_world = world; 58 m_world = world;
66 m_body1 = obj1; 59 m_body1 = obj1;
67 m_body2 = obj2; 60 m_body2 = obj2;
68 if (obj1.ptr == IntPtr.Zero || obj2.ptr == IntPtr.Zero) 61 m_constraint = new BulletConstraint(
69 { 62 BulletSimAPI.Create6DofConstraintToPoint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr,
70 world.physicsScene.DetailLog("{0},BS6DOFConstraint,badBodyPtr,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", 63 joinPoint,
71 BSScene.DetailLogZero, world.worldID, 64 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
72 obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); 65 m_enabled = true;
73 world.physicsScene.Logger.ErrorFormat("{0} Attempt to build 6DOF constraint with missing bodies: wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}",
74 LogHeader, world.worldID, obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X"));
75 m_enabled = false;
76 }
77 else
78 {
79 m_constraint = new BulletConstraint(
80 BulletSimAPI.Create6DofConstraintToPoint2(m_world.ptr, m_body1.ptr, m_body2.ptr,
81 joinPoint,
82 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
83 world.physicsScene.DetailLog("{0},BS6DofConstraint,createMidPoint,wID={1}, csrt={2}, rID={3}, rBody={4}, cID={5}, cBody={6}",
84 BSScene.DetailLogZero, world.worldID, m_constraint.ptr.ToString("X"),
85 obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X"));
86 if (m_constraint.ptr == IntPtr.Zero)
87 {
88 world.physicsScene.Logger.ErrorFormat("{0} Failed creation of 6Dof constraint. rootID={1}, childID={2}",
89 LogHeader, obj1.ID, obj2.ID);
90 m_enabled = false;
91 }
92 else
93 {
94 m_enabled = true;
95 }
96 }
97 } 66 }
98 67
99 public bool SetFrames(Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot) 68 public bool SetFrames(Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot)
@@ -101,7 +70,7 @@ public sealed class BSConstraint6Dof : BSConstraint
101 bool ret = false; 70 bool ret = false;
102 if (m_enabled) 71 if (m_enabled)
103 { 72 {
104 BulletSimAPI.SetFrames2(m_constraint.ptr, frameA, frameArot, frameB, frameBrot); 73 BulletSimAPI.SetFrames2(m_constraint.Ptr, frameA, frameArot, frameB, frameBrot);
105 ret = true; 74 ret = true;
106 } 75 }
107 return ret; 76 return ret;
@@ -112,9 +81,9 @@ public sealed class BSConstraint6Dof : BSConstraint
112 bool ret = false; 81 bool ret = false;
113 if (m_enabled) 82 if (m_enabled)
114 { 83 {
115 BulletSimAPI.SetConstraintParam2(m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL); 84 BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL);
116 BulletSimAPI.SetConstraintParam2(m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL); 85 BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL);
117 BulletSimAPI.SetConstraintParam2(m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL); 86 BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL);
118 ret = true; 87 ret = true;
119 } 88 }
120 return ret; 89 return ret;
@@ -125,7 +94,7 @@ public sealed class BSConstraint6Dof : BSConstraint
125 bool ret = false; 94 bool ret = false;
126 float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; 95 float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
127 if (m_enabled) 96 if (m_enabled)
128 ret = BulletSimAPI.UseFrameOffset2(m_constraint.ptr, onOff); 97 ret = BulletSimAPI.UseFrameOffset2(m_constraint.Ptr, onOff);
129 return ret; 98 return ret;
130 } 99 }
131 100
@@ -134,11 +103,7 @@ public sealed class BSConstraint6Dof : BSConstraint
134 bool ret = false; 103 bool ret = false;
135 float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; 104 float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
136 if (m_enabled) 105 if (m_enabled)
137 { 106 ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.Ptr, onOff, targetVelocity, maxMotorForce);
138 ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.ptr, onOff, targetVelocity, maxMotorForce);
139 m_world.physicsScene.DetailLog("{0},BS6DOFConstraint,TransLimitMotor,enable={1},vel={2},maxForce={3}",
140 BSScene.DetailLogZero, enable, targetVelocity, maxMotorForce);
141 }
142 return ret; 107 return ret;
143 } 108 }
144 109
@@ -146,7 +111,7 @@ public sealed class BSConstraint6Dof : BSConstraint
146 { 111 {
147 bool ret = false; 112 bool ret = false;
148 if (m_enabled) 113 if (m_enabled)
149 ret = BulletSimAPI.SetBreakingImpulseThreshold2(m_constraint.ptr, threshold); 114 ret = BulletSimAPI.SetBreakingImpulseThreshold2(m_constraint.Ptr, threshold);
150 return ret; 115 return ret;
151 } 116 }
152} 117}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index 2a5397e..e2f7af9 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -28,48 +28,62 @@ using System;
28using System.Collections.Generic; 28using System.Collections.Generic;
29using System.Reflection; 29using System.Reflection;
30using log4net; 30using log4net;
31using OMV = OpenMetaverse; 31using OpenMetaverse;
32using OpenSim.Framework; 32using OpenSim.Framework;
33using OpenSim.Region.Physics.Manager; 33using OpenSim.Region.Physics.Manager;
34 34
35namespace OpenSim.Region.Physics.BulletSPlugin 35namespace OpenSim.Region.Physics.BulletSPlugin
36{ 36{
37public sealed class BSCharacter : BSPhysObject 37public class BSCharacter : PhysicsActor
38{ 38{
39 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 39 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
40 private static readonly string LogHeader = "[BULLETS CHAR]"; 40 private static readonly string LogHeader = "[BULLETS CHAR]";
41 41
42 private BSScene _scene;
43 public BSScene Scene { get { return _scene; } }
44 private String _avName;
42 // private bool _stopped; 45 // private bool _stopped;
43 private OMV.Vector3 _size; 46 private Vector3 _size;
47 private Vector3 _scale;
48 private PrimitiveBaseShape _pbs;
49 private uint _localID = 0;
44 private bool _grabbed; 50 private bool _grabbed;
45 private bool _selected; 51 private bool _selected;
46 private OMV.Vector3 _position; 52 private Vector3 _position;
47 private float _mass; 53 private float _mass;
48 private float _avatarDensity; 54 public float _density;
49 private float _avatarVolume; 55 public float _avatarVolume;
50 private OMV.Vector3 _force; 56 private Vector3 _force;
51 private OMV.Vector3 _velocity; 57 private Vector3 _velocity;
52 private OMV.Vector3 _torque; 58 private Vector3 _torque;
53 private float _collisionScore; 59 private float _collisionScore;
54 private OMV.Vector3 _acceleration; 60 private Vector3 _acceleration;
55 private OMV.Quaternion _orientation; 61 private Quaternion _orientation;
56 private int _physicsActorType; 62 private int _physicsActorType;
57 private bool _isPhysical; 63 private bool _isPhysical;
58 private bool _flying; 64 private bool _flying;
59 private bool _setAlwaysRun; 65 private bool _setAlwaysRun;
60 private bool _throttleUpdates; 66 private bool _throttleUpdates;
61 private bool _isColliding; 67 private bool _isColliding;
68 private long _collidingStep;
69 private bool _collidingGround;
70 private long _collidingGroundStep;
62 private bool _collidingObj; 71 private bool _collidingObj;
63 private bool _floatOnWater; 72 private bool _floatOnWater;
64 private OMV.Vector3 _rotationalVelocity; 73 private Vector3 _rotationalVelocity;
65 private bool _kinematic; 74 private bool _kinematic;
66 private float _buoyancy; 75 private float _buoyancy;
67 76
68 // The friction and velocity of the avatar is modified depending on whether walking or not. 77 private BulletBody m_body;
69 private OMV.Vector3 _appliedVelocity; // the last velocity applied to the avatar 78 public BulletBody Body {
70 private float _currentFriction; // the friction currently being used (changed by setVelocity). 79 get { return m_body; }
80 set { m_body = value; }
81 }
82
83 private int _subscribedEventsMs = 0;
84 private int _nextCollisionOkTime = 0;
71 85
72 private OMV.Vector3 _PIDTarget; 86 private Vector3 _PIDTarget;
73 private bool _usePID; 87 private bool _usePID;
74 private float _PIDTau; 88 private float _PIDTau;
75 private bool _useHoverPID; 89 private bool _useHoverPID;
@@ -77,507 +91,332 @@ public sealed class BSCharacter : BSPhysObject
77 private PIDHoverType _PIDHoverType; 91 private PIDHoverType _PIDHoverType;
78 private float _PIDHoverTao; 92 private float _PIDHoverTao;
79 93
80 public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying) 94 public BSCharacter(uint localID, String avName, BSScene parent_scene, Vector3 pos, Vector3 size, bool isFlying)
81 { 95 {
82 base.BaseInitialize(parent_scene, localID, avName, "BSCharacter"); 96 _localID = localID;
83 _physicsActorType = (int)ActorTypes.Agent; 97 _avName = avName;
98 _scene = parent_scene;
84 _position = pos; 99 _position = pos;
85 _size = size; 100 _size = size;
86 _flying = isFlying; 101 _flying = isFlying;
87 _orientation = OMV.Quaternion.Identity; 102 _orientation = Quaternion.Identity;
88 _velocity = OMV.Vector3.Zero; 103 _velocity = Vector3.Zero;
89 _appliedVelocity = OMV.Vector3.Zero;
90 _buoyancy = ComputeBuoyancyFromFlying(isFlying); 104 _buoyancy = ComputeBuoyancyFromFlying(isFlying);
91 _currentFriction = PhysicsScene.Params.avatarStandingFriction;
92 _avatarDensity = PhysicsScene.Params.avatarDensity;
93
94 // The dimensions of the avatar capsule are kept in the scale. 105 // The dimensions of the avatar capsule are kept in the scale.
95 // Physics creates a unit capsule which is scaled by the physics engine. 106 // Physics creates a unit capsule which is scaled by the physics engine.
96 ComputeAvatarScale(_size); 107 _scale = new Vector3(_scene.Params.avatarCapsuleRadius, _scene.Params.avatarCapsuleRadius, size.Z);
97 // set _avatarVolume and _mass based on capsule size, _density and Scale 108 _density = _scene.Params.avatarDensity;
98 ComputeAvatarVolumeAndMass(); 109 ComputeAvatarVolumeAndMass(); // set _avatarVolume and _mass based on capsule size, _density and _scale
99 DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}", 110
100 LocalID, _size, Scale, _avatarDensity, _avatarVolume, RawMass); 111 ShapeData shapeData = new ShapeData();
112 shapeData.ID = _localID;
113 shapeData.Type = ShapeData.PhysicsShapeType.SHAPE_AVATAR;
114 shapeData.Position = _position;
115 shapeData.Rotation = _orientation;
116 shapeData.Velocity = _velocity;
117 shapeData.Scale = _scale;
118 shapeData.Mass = _mass;
119 shapeData.Buoyancy = _buoyancy;
120 shapeData.Static = ShapeData.numericFalse;
121 shapeData.Friction = _scene.Params.avatarFriction;
122 shapeData.Restitution = _scene.Params.avatarRestitution;
101 123
102 // do actual create at taint time 124 // do actual create at taint time
103 PhysicsScene.TaintedObject("BSCharacter.create", delegate() 125 _scene.TaintedObject("BSCharacter.create", delegate()
104 { 126 {
105 DetailLog("{0},BSCharacter.create,taint", LocalID); 127 BulletSimAPI.CreateObject(parent_scene.WorldID, shapeData);
106 // New body and shape into BSBody and BSShape
107 PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this, null, null);
108 128
109 SetPhysicalProperties(); 129 m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
130 // avatars get all collisions no matter what
131 BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
110 }); 132 });
133
111 return; 134 return;
112 } 135 }
113 136
114 // called when this character is being destroyed and the resources should be released 137 // called when this character is being destroyed and the resources should be released
115 public override void Destroy() 138 public void Destroy()
116 { 139 {
117 DetailLog("{0},BSCharacter.Destroy", LocalID); 140 // DetailLog("{0},BSCharacter.Destroy", LocalID);
118 PhysicsScene.TaintedObject("BSCharacter.destroy", delegate() 141 _scene.TaintedObject("BSCharacter.destroy", delegate()
119 { 142 {
120 PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null); 143 BulletSimAPI.DestroyObject(_scene.WorldID, _localID);
121 PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null);
122 }); 144 });
123 } 145 }
124 146
125 private void SetPhysicalProperties()
126 {
127 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, PhysBody.ptr);
128
129 ZeroMotion();
130 ForcePosition = _position;
131 // Set the velocity and compute the proper friction
132 ForceVelocity = _velocity;
133
134 BulletSimAPI.SetRestitution2(PhysBody.ptr, PhysicsScene.Params.avatarRestitution);
135 BulletSimAPI.SetMargin2(PhysShape.ptr, PhysicsScene.Params.collisionMargin);
136 BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale);
137 BulletSimAPI.SetContactProcessingThreshold2(PhysBody.ptr, PhysicsScene.Params.contactProcessingThreshold);
138 if (PhysicsScene.Params.ccdMotionThreshold > 0f)
139 {
140 BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold);
141 BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius);
142 }
143
144 UpdatePhysicalMassProperties(RawMass);
145
146 // Make so capsule does not fall over
147 BulletSimAPI.SetAngularFactorV2(PhysBody.ptr, OMV.Vector3.Zero);
148
149 BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_CHARACTER_OBJECT);
150
151 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, PhysBody.ptr);
152
153 // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ACTIVE_TAG);
154 BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.DISABLE_DEACTIVATION);
155 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr);
156
157 // Do this after the object has been added to the world
158 BulletSimAPI.SetCollisionFilterMask2(PhysBody.ptr,
159 (uint)CollisionFilterGroups.AvatarFilter,
160 (uint)CollisionFilterGroups.AvatarMask);
161 }
162
163 public override void RequestPhysicsterseUpdate() 147 public override void RequestPhysicsterseUpdate()
164 { 148 {
165 base.RequestPhysicsterseUpdate(); 149 base.RequestPhysicsterseUpdate();
166 } 150 }
167 // No one calls this method so I don't know what it could possibly mean 151 // No one calls this method so I don't know what it could possibly mean
168 public override bool Stopped { get { return false; } } 152 public override bool Stopped {
169 153 get { return false; }
170 public override OMV.Vector3 Size { 154 }
155 public override Vector3 Size {
171 get 156 get
172 { 157 {
173 // Avatar capsule size is kept in the scale parameter. 158 // Avatar capsule size is kept in the scale parameter.
174 // return _size; 159 return new Vector3(_scale.X * 2, _scale.Y * 2, _scale.Z);
175 return new OMV.Vector3(Scale.X * 2f, Scale.Y * 2f, Scale.Z);
176 } 160 }
177 161
178 set { 162 set {
179 // When an avatar's size is set, only the height is changed. 163 // When an avatar's size is set, only the height is changed
164 // and that really only depends on the radius.
180 _size = value; 165 _size = value;
181 ComputeAvatarScale(_size); 166 _scale.Z = (_size.Z * 1.15f) - (_scale.X + _scale.Y);
167
168 // TODO: something has to be done with the avatar's vertical position
169
182 ComputeAvatarVolumeAndMass(); 170 ComputeAvatarVolumeAndMass();
183 DetailLog("{0},BSCharacter.setSize,call,scale={1},density={2},volume={3},mass={4}",
184 LocalID, Scale, _avatarDensity, _avatarVolume, RawMass);
185 171
186 PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() 172 _scene.TaintedObject("BSCharacter.setSize", delegate()
187 { 173 {
188 BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale); 174 BulletSimAPI.SetObjectScaleMass(_scene.WorldID, LocalID, _scale, _mass, true);
189 UpdatePhysicalMassProperties(RawMass);
190 }); 175 });
191 176
192 } 177 }
193 } 178 }
194 179 public override PrimitiveBaseShape Shape {
195 public override OMV.Vector3 Scale { get; set; } 180 set { _pbs = value;
196 181 }
197 public override PrimitiveBaseShape Shape
198 {
199 set { BaseShape = value; }
200 } 182 }
201 // I want the physics engine to make an avatar capsule 183 public override uint LocalID {
202 public override ShapeData.PhysicsShapeType PreferredPhysicalShape 184 set { _localID = value;
203 { 185 }
204 get {return ShapeData.PhysicsShapeType.SHAPE_AVATAR; } 186 get { return _localID; }
205 } 187 }
206 188 public override bool Grabbed {
207 public override bool Grabbed { 189 set { _grabbed = value;
208 set { _grabbed = value; } 190 }
209 } 191 }
210 public override bool Selected { 192 public override bool Selected {
211 set { _selected = value; } 193 set { _selected = value;
194 }
212 } 195 }
213 public override void CrossingFailure() { return; } 196 public override void CrossingFailure() { return; }
214 public override void link(PhysicsActor obj) { return; } 197 public override void link(PhysicsActor obj) { return; }
215 public override void delink() { return; } 198 public override void delink() { return; }
199 public override void LockAngularMotion(Vector3 axis) { return; }
216 200
217 // Set motion values to zero. 201 public override Vector3 Position {
218 // Do it to the properties so the values get set in the physics engine.
219 // Push the setting of the values to the viewer.
220 // Called at taint time!
221 public override void ZeroMotion()
222 {
223 _velocity = OMV.Vector3.Zero;
224 _acceleration = OMV.Vector3.Zero;
225 _rotationalVelocity = OMV.Vector3.Zero;
226
227 // Zero some other properties directly into the physics engine
228 BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, OMV.Vector3.Zero);
229 BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero);
230 BulletSimAPI.SetInterpolationVelocity2(PhysBody.ptr, OMV.Vector3.Zero, OMV.Vector3.Zero);
231 BulletSimAPI.ClearForces2(PhysBody.ptr);
232 }
233
234 public override void LockAngularMotion(OMV.Vector3 axis) { return; }
235
236 public override OMV.Vector3 RawPosition
237 {
238 get { return _position; }
239 set { _position = value; }
240 }
241 public override OMV.Vector3 Position {
242 get { 202 get {
243 // Don't refetch the position because this function is called a zillion times 203 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
244 // _position = BulletSimAPI.GetObjectPosition2(Scene.World.ptr, LocalID); 204 return _position;
245 return _position; 205 }
246 }
247 set { 206 set {
248 _position = value; 207 _position = value;
249 PositionSanityCheck(); 208 PositionSanityCheck();
250 209
251 PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate() 210 _scene.TaintedObject("BSCharacter.setPosition", delegate()
252 { 211 {
253 DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 212 DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
254 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); 213 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
255 }); 214 });
256 } 215 }
257 }
258 public override OMV.Vector3 ForcePosition {
259 get {
260 _position = BulletSimAPI.GetPosition2(PhysBody.ptr);
261 return _position;
262 }
263 set {
264 _position = value;
265 PositionSanityCheck();
266 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
267 }
268 } 216 }
269 217
270
271 // Check that the current position is sane and, if not, modify the position to make it so. 218 // Check that the current position is sane and, if not, modify the position to make it so.
272 // Check for being below terrain or on water. 219 // Check for being below terrain and being out of bounds.
273 // Returns 'true' of the position was made sane by some action. 220 // Returns 'true' of the position was made sane by some action.
274 private bool PositionSanityCheck() 221 private bool PositionSanityCheck()
275 { 222 {
276 bool ret = false; 223 bool ret = false;
277 224
278 // If below the ground, move the avatar up 225 // If below the ground, move the avatar up
279 float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); 226 float terrainHeight = Scene.GetTerrainHeightAtXYZ(_position);
280 if (Position.Z < terrainHeight) 227 if (_position.Z < terrainHeight)
281 { 228 {
282 DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); 229 DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},orient={2}", LocalID, _position, _orientation);
283 _position.Z = terrainHeight + 2.0f; 230 _position.Z = terrainHeight + 2.0f;
284 ret = true; 231 ret = true;
285 } 232 }
286 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0)
287 {
288 float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position);
289 if (Position.Z < waterHeight)
290 {
291 _position.Z = waterHeight;
292 ret = true;
293 }
294 }
295 233
296 // TODO: check for out of bounds 234 // TODO: check for out of bounds
297 return ret;
298 }
299 235
300 // A version of the sanity check that also makes sure a new position value is
301 // pushed back to the physics engine. This routine would be used by anyone
302 // who is not already pushing the value.
303 private bool PositionSanityCheck(bool inTaintTime)
304 {
305 bool ret = false;
306 if (PositionSanityCheck())
307 {
308 // The new position value must be pushed into the physics engine but we can't
309 // just assign to "Position" because of potential call loops.
310 PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate()
311 {
312 DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
313 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
314 });
315 ret = true;
316 }
317 return ret; 236 return ret;
318 } 237 }
319 238
320 public override float Mass { get { return _mass; } } 239 public override float Mass {
321 240 get {
322 // used when we only want this prim's mass and not the linkset thing 241 return _mass;
323 public override float RawMass { 242 }
324 get {return _mass; }
325 }
326 public override void UpdatePhysicalMassProperties(float physMass)
327 {
328 OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass);
329 BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, localInertia);
330 } 243 }
331 244 public override Vector3 Force {
332 public override OMV.Vector3 Force { 245 get { return _force; }
333 get { return _force; }
334 set { 246 set {
335 _force = value; 247 _force = value;
336 // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force); 248 // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force);
337 PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate() 249 Scene.TaintedObject("BSCharacter.SetForce", delegate()
338 { 250 {
339 DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force); 251 DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force);
340 BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force); 252 BulletSimAPI.SetObjectForce(Scene.WorldID, LocalID, _force);
341 }); 253 });
342 } 254 }
343 } 255 }
344 256
345 // Avatars don't do vehicles 257 public override int VehicleType {
346 public override int VehicleType { get { return (int)Vehicle.TYPE_NONE; } set { return; } } 258 get { return 0; }
259 set { return; }
260 }
347 public override void VehicleFloatParam(int param, float value) { } 261 public override void VehicleFloatParam(int param, float value) { }
348 public override void VehicleVectorParam(int param, OMV.Vector3 value) {} 262 public override void VehicleVectorParam(int param, Vector3 value) {}
349 public override void VehicleRotationParam(int param, OMV.Quaternion rotation) { } 263 public override void VehicleRotationParam(int param, Quaternion rotation) { }
350 public override void VehicleFlags(int param, bool remove) { } 264 public override void VehicleFlags(int param, bool remove) { }
351 265
352 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more 266 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more
353 public override void SetVolumeDetect(int param) { return; } 267 public override void SetVolumeDetect(int param) { return; }
354 268
355 public override OMV.Vector3 GeometricCenter { get { return OMV.Vector3.Zero; } } 269 public override Vector3 GeometricCenter { get { return Vector3.Zero; } }
356 public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } } 270 public override Vector3 CenterOfMass { get { return Vector3.Zero; } }
357 public override OMV.Vector3 Velocity { 271 public override Vector3 Velocity {
358 get { return _velocity; } 272 get { return _velocity; }
359 set { 273 set {
360 _velocity = value; 274 _velocity = value;
361 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity); 275 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity);
362 PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate() 276 _scene.TaintedObject("BSCharacter.setVelocity", delegate()
363 { 277 {
364 DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity); 278 DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity);
365 ForceVelocity = _velocity; 279 BulletSimAPI.SetObjectVelocity(_scene.WorldID, _localID, _velocity);
366 }); 280 });
367 } 281 }
368 }
369 public override OMV.Vector3 ForceVelocity {
370 get { return _velocity; }
371 set {
372 // Depending on whether the avatar is moving or not, change the friction
373 // to keep the avatar from slipping around
374 if (_velocity.Length() == 0)
375 {
376 if (_currentFriction != PhysicsScene.Params.avatarStandingFriction)
377 {
378 _currentFriction = PhysicsScene.Params.avatarStandingFriction;
379 BulletSimAPI.SetFriction2(PhysBody.ptr, _currentFriction);
380 }
381 }
382 else
383 {
384 if (_currentFriction != PhysicsScene.Params.avatarFriction)
385 {
386 _currentFriction = PhysicsScene.Params.avatarFriction;
387 BulletSimAPI.SetFriction2(PhysBody.ptr, _currentFriction);
388 }
389 }
390 _velocity = value;
391 // Remember the set velocity so we can suppress the reduction by friction, ...
392 _appliedVelocity = value;
393
394 BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity);
395 BulletSimAPI.Activate2(PhysBody.ptr, true);
396 }
397 } 282 }
398 public override OMV.Vector3 Torque { 283 public override Vector3 Torque {
399 get { return _torque; } 284 get { return _torque; }
400 set { _torque = value; 285 set { _torque = value;
401 } 286 }
402 } 287 }
403 public override float CollisionScore { 288 public override float CollisionScore {
404 get { return _collisionScore; } 289 get { return _collisionScore; }
405 set { _collisionScore = value; 290 set { _collisionScore = value;
406 } 291 }
407 } 292 }
408 public override OMV.Vector3 Acceleration { 293 public override Vector3 Acceleration {
409 get { return _acceleration; } 294 get { return _acceleration; }
410 set { _acceleration = value; } 295 set { _acceleration = value; }
411 } 296 }
412 public override OMV.Quaternion RawOrientation 297 public override Quaternion Orientation {
413 { 298 get { return _orientation; }
414 get { return _orientation; }
415 set { _orientation = value; }
416 }
417 public override OMV.Quaternion Orientation {
418 get { return _orientation; }
419 set { 299 set {
420 _orientation = value; 300 _orientation = value;
421 // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation); 301 // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation);
422 PhysicsScene.TaintedObject("BSCharacter.setOrientation", delegate() 302 _scene.TaintedObject("BSCharacter.setOrientation", delegate()
423 { 303 {
424 // _position = BulletSimAPI.GetPosition2(BSBody.ptr); 304 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
425 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); 305 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
426 }); 306 });
427 } 307 }
428 } 308 }
429 // Go directly to Bullet to get/set the value. 309 public override int PhysicsActorType {
430 public override OMV.Quaternion ForceOrientation 310 get { return _physicsActorType; }
431 { 311 set { _physicsActorType = value;
432 get 312 }
433 {
434 _orientation = BulletSimAPI.GetOrientation2(PhysBody.ptr);
435 return _orientation;
436 }
437 set
438 {
439 _orientation = value;
440 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
441 }
442 }
443 public override int PhysicsActorType {
444 get { return _physicsActorType; }
445 set { _physicsActorType = value;
446 }
447 } 313 }
448 public override bool IsPhysical { 314 public override bool IsPhysical {
449 get { return _isPhysical; } 315 get { return _isPhysical; }
450 set { _isPhysical = value; 316 set { _isPhysical = value;
451 } 317 }
452 }
453 public override bool IsSolid {
454 get { return true; }
455 } 318 }
456 public override bool IsStatic { 319 public override bool Flying {
457 get { return false; } 320 get { return _flying; }
458 }
459 public override bool Flying {
460 get { return _flying; }
461 set { 321 set {
462 _flying = value; 322 if (_flying != value)
463 // simulate flying by changing the effect of gravity 323 {
464 Buoyancy = ComputeBuoyancyFromFlying(_flying); 324 _flying = value;
465 } 325 // simulate flying by changing the effect of gravity
326 this.Buoyancy = ComputeBuoyancyFromFlying(_flying);
327 }
328 }
466 } 329 }
467 // Flying is implimented by changing the avatar's buoyancy.
468 // Would this be done better with a vehicle type?
469 private float ComputeBuoyancyFromFlying(bool ifFlying) { 330 private float ComputeBuoyancyFromFlying(bool ifFlying) {
470 return ifFlying ? 1f : 0f; 331 return ifFlying ? 1f : 0f;
471 } 332 }
472 public override bool 333 public override bool
473 SetAlwaysRun { 334 SetAlwaysRun {
474 get { return _setAlwaysRun; } 335 get { return _setAlwaysRun; }
475 set { _setAlwaysRun = value; } 336 set { _setAlwaysRun = value; }
476 } 337 }
477 public override bool ThrottleUpdates { 338 public override bool ThrottleUpdates {
478 get { return _throttleUpdates; } 339 get { return _throttleUpdates; }
479 set { _throttleUpdates = value; } 340 set { _throttleUpdates = value; }
480 } 341 }
481 public override bool IsColliding { 342 public override bool IsColliding {
482 get { return (CollidingStep == PhysicsScene.SimulationStep); } 343 get { return (_collidingStep == _scene.SimulationStep); }
483 set { _isColliding = value; } 344 set { _isColliding = value; }
484 } 345 }
485 public override bool CollidingGround { 346 public override bool CollidingGround {
486 get { return (CollidingGroundStep == PhysicsScene.SimulationStep); } 347 get { return (_collidingGroundStep == _scene.SimulationStep); }
487 set { CollidingGround = value; } 348 set { _collidingGround = value; }
488 }
489 public override bool CollidingObj {
490 get { return _collidingObj; }
491 set { _collidingObj = value; }
492 } 349 }
493 public override bool FloatOnWater { 350 public override bool CollidingObj {
494 set { 351 get { return _collidingObj; }
495 _floatOnWater = value; 352 set { _collidingObj = value; }
496 PhysicsScene.TaintedObject("BSCharacter.setFloatOnWater", delegate()
497 {
498 if (_floatOnWater)
499 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER);
500 else
501 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER);
502 });
503 }
504 } 353 }
505 public override OMV.Vector3 RotationalVelocity { 354 public override bool FloatOnWater {
506 get { return _rotationalVelocity; } 355 set { _floatOnWater = value; }
507 set { _rotationalVelocity = value; }
508 } 356 }
509 public override OMV.Vector3 ForceRotationalVelocity { 357 public override Vector3 RotationalVelocity {
510 get { return _rotationalVelocity; } 358 get { return _rotationalVelocity; }
511 set { _rotationalVelocity = value; } 359 set { _rotationalVelocity = value; }
512 } 360 }
513 public override bool Kinematic { 361 public override bool Kinematic {
514 get { return _kinematic; } 362 get { return _kinematic; }
515 set { _kinematic = value; } 363 set { _kinematic = value; }
516 } 364 }
517 // neg=fall quickly, 0=1g, 1=0g, pos=float up 365 // neg=fall quickly, 0=1g, 1=0g, pos=float up
518 public override float Buoyancy { 366 public override float Buoyancy {
519 get { return _buoyancy; } 367 get { return _buoyancy; }
520 set { _buoyancy = value; 368 set { _buoyancy = value;
521 PhysicsScene.TaintedObject("BSCharacter.setBuoyancy", delegate() 369 _scene.TaintedObject("BSCharacter.setBuoyancy", delegate()
522 { 370 {
523 DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 371 DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
524 ForceBuoyancy = _buoyancy; 372 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy);
525 }); 373 });
526 } 374 }
527 }
528 public override float ForceBuoyancy {
529 get { return _buoyancy; }
530 set { _buoyancy = value;
531 DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
532 // Buoyancy is faked by changing the gravity applied to the object
533 float grav = PhysicsScene.Params.gravity * (1f - _buoyancy);
534 BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav));
535 }
536 } 375 }
537 376
538 // Used for MoveTo 377 // Used for MoveTo
539 public override OMV.Vector3 PIDTarget { 378 public override Vector3 PIDTarget {
540 set { _PIDTarget = value; } 379 set { _PIDTarget = value; }
541 } 380 }
542 public override bool PIDActive { 381 public override bool PIDActive {
543 set { _usePID = value; } 382 set { _usePID = value; }
544 } 383 }
545 public override float PIDTau { 384 public override float PIDTau {
546 set { _PIDTau = value; } 385 set { _PIDTau = value; }
547 } 386 }
548 387
549 // Used for llSetHoverHeight and maybe vehicle height 388 // Used for llSetHoverHeight and maybe vehicle height
550 // Hover Height will override MoveTo target's Z 389 // Hover Height will override MoveTo target's Z
551 public override bool PIDHoverActive { 390 public override bool PIDHoverActive {
552 set { _useHoverPID = value; } 391 set { _useHoverPID = value; }
553 } 392 }
554 public override float PIDHoverHeight { 393 public override float PIDHoverHeight {
555 set { _PIDHoverHeight = value; } 394 set { _PIDHoverHeight = value; }
556 } 395 }
557 public override PIDHoverType PIDHoverType { 396 public override PIDHoverType PIDHoverType {
558 set { _PIDHoverType = value; } 397 set { _PIDHoverType = value; }
559 } 398 }
560 public override float PIDHoverTau { 399 public override float PIDHoverTau {
561 set { _PIDHoverTao = value; } 400 set { _PIDHoverTao = value; }
562 } 401 }
563 402
564 // For RotLookAt 403 // For RotLookAt
565 public override OMV.Quaternion APIDTarget { set { return; } } 404 public override Quaternion APIDTarget { set { return; } }
566 public override bool APIDActive { set { return; } } 405 public override bool APIDActive { set { return; } }
567 public override float APIDStrength { set { return; } } 406 public override float APIDStrength { set { return; } }
568 public override float APIDDamping { set { return; } } 407 public override float APIDDamping { set { return; } }
569 408
570 public override void AddForce(OMV.Vector3 force, bool pushforce) { 409 public override void AddForce(Vector3 force, bool pushforce) {
571 if (force.IsFinite()) 410 if (force.IsFinite())
572 { 411 {
573 _force.X += force.X; 412 _force.X += force.X;
574 _force.Y += force.Y; 413 _force.Y += force.Y;
575 _force.Z += force.Z; 414 _force.Z += force.Z;
576 // m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force); 415 // m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force);
577 PhysicsScene.TaintedObject("BSCharacter.AddForce", delegate() 416 _scene.TaintedObject("BSCharacter.AddForce", delegate()
578 { 417 {
579 DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force); 418 DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force);
580 BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force); 419 BulletSimAPI.AddObjectForce2(Body.Ptr, _force);
581 }); 420 });
582 } 421 }
583 else 422 else
@@ -587,75 +426,129 @@ public sealed class BSCharacter : BSPhysObject
587 //m_lastUpdateSent = false; 426 //m_lastUpdateSent = false;
588 } 427 }
589 428
590 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { 429 public override void AddAngularForce(Vector3 force, bool pushforce) {
591 } 430 }
592 public override void SetMomentum(OMV.Vector3 momentum) { 431 public override void SetMomentum(Vector3 momentum) {
593 } 432 }
594 433
595 private void ComputeAvatarScale(OMV.Vector3 size) 434 // Turn on collision events at a rate no faster than one every the given milliseconds
596 { 435 public override void SubscribeEvents(int ms) {
597 // The 'size' given by the simulator is the mid-point of the avatar 436 _subscribedEventsMs = ms;
598 // and X and Y are unspecified. 437 if (ms > 0)
599 438 {
600 OMV.Vector3 newScale = OMV.Vector3.Zero; 439 // make sure first collision happens
601 newScale.X = PhysicsScene.Params.avatarCapsuleRadius; 440 _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs;
602 newScale.Y = PhysicsScene.Params.avatarCapsuleRadius;
603 441
604 // From the total height, remove the capsule half spheres that are at each end 442 Scene.TaintedObject("BSCharacter.SubscribeEvents", delegate()
605 newScale.Z = size.Z- (newScale.X + newScale.Y); 443 {
606 Scale = newScale; 444 BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
445 });
446 }
447 }
448 // Stop collision events
449 public override void UnSubscribeEvents() {
450 _subscribedEventsMs = 0;
451 // Avatars get all their collision events
452 // Scene.TaintedObject("BSCharacter.UnSubscribeEvents", delegate()
453 // {
454 // BulletSimAPI.RemoveFromCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
455 // });
456 }
457 // Return 'true' if someone has subscribed to events
458 public override bool SubscribedEvents() {
459 return (_subscribedEventsMs > 0);
607 } 460 }
608 461
609 // set _avatarVolume and _mass based on capsule size, _density and Scale 462 // set _avatarVolume and _mass based on capsule size, _density and _scale
610 private void ComputeAvatarVolumeAndMass() 463 private void ComputeAvatarVolumeAndMass()
611 { 464 {
612 _avatarVolume = (float)( 465 _avatarVolume = (float)(
613 Math.PI 466 Math.PI
614 * Scale.X 467 * _scale.X
615 * Scale.Y // the area of capsule cylinder 468 * _scale.Y // the area of capsule cylinder
616 * Scale.Z // times height of capsule cylinder 469 * _scale.Z // times height of capsule cylinder
617 + 1.33333333f 470 + 1.33333333f
618 * Math.PI 471 * Math.PI
619 * Scale.X 472 * _scale.X
620 * Math.Min(Scale.X, Scale.Y) 473 * Math.Min(_scale.X, _scale.Y)
621 * Scale.Y // plus the volume of the capsule end caps 474 * _scale.Y // plus the volume of the capsule end caps
622 ); 475 );
623 _mass = _avatarDensity * _avatarVolume; 476 _mass = _density * _avatarVolume;
624 } 477 }
625 478
626 // The physics engine says that properties have updated. Update same and inform 479 // The physics engine says that properties have updated. Update same and inform
627 // the world that things have changed. 480 // the world that things have changed.
628 public override void UpdateProperties(EntityProperties entprop) 481 public void UpdateProperties(EntityProperties entprop)
629 { 482 {
630 _position = entprop.Position; 483 _position = entprop.Position;
631 _orientation = entprop.Rotation; 484 _orientation = entprop.Rotation;
632 _velocity = entprop.Velocity; 485 _velocity = entprop.Velocity;
633 _acceleration = entprop.Acceleration; 486 _acceleration = entprop.Acceleration;
634 _rotationalVelocity = entprop.RotationalVelocity; 487 _rotationalVelocity = entprop.RotationalVelocity;
635 // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. 488 // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop.
636 PositionSanityCheck(true); 489 // base.RequestPhysicsterseUpdate();
490
491 /*
492 DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
493 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
494 entprop.Acceleration, entprop.RotationalVelocity);
495 */
496 }
637 497
638 // remember the current and last set values 498 // Called by the scene when a collision with this object is reported
639 LastEntityProperties = CurrentEntityProperties; 499 // The collision, if it should be reported to the character, is placed in a collection
640 CurrentEntityProperties = entprop; 500 // that will later be sent to the simulator when SendCollisions() is called.
501 CollisionEventUpdate collisionCollection = null;
502 public void Collide(uint collidingWith, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth)
503 {
504 // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith);
641 505
642 if (entprop.Velocity != LastEntityProperties.Velocity) 506 // The following makes IsColliding() and IsCollidingGround() work
507 _collidingStep = _scene.SimulationStep;
508 if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID)
643 { 509 {
644 // Changes in the velocity are suppressed in avatars. 510 _collidingGroundStep = _scene.SimulationStep;
645 // That's just the way they are defined.
646 OMV.Vector3 avVel = new OMV.Vector3(_appliedVelocity.X, _appliedVelocity.Y, entprop.Velocity.Z);
647 _velocity = avVel;
648 BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, avVel);
649 } 511 }
512 // DetailLog("{0},BSCharacter.Collison,call,with={1}", LocalID, collidingWith);
650 513
651 // Tell the linkset about value changes 514 // throttle collisions to the rate specified in the subscription
652 Linkset.UpdateProperties(this); 515 if (_subscribedEventsMs != 0) {
516 int nowTime = _scene.SimulationNowTime;
517 if (nowTime >= _nextCollisionOkTime) {
518 _nextCollisionOkTime = nowTime + _subscribedEventsMs;
653 519
654 // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. 520 if (collisionCollection == null)
655 // base.RequestPhysicsterseUpdate(); 521 collisionCollection = new CollisionEventUpdate();
522 collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
523 }
524 }
525 }
656 526
657 DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", 527 public void SendCollisions()
658 LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); 528 {
529 /*
530 if (collisionCollection != null && collisionCollection.Count > 0)
531 {
532 base.SendCollisionUpdate(collisionCollection);
533 collisionCollection = null;
534 }
535 */
536 // Kludge to make a collision call even if there are no collisions.
537 // This causes the avatar animation to get updated.
538 if (collisionCollection == null)
539 collisionCollection = new CollisionEventUpdate();
540 base.SendCollisionUpdate(collisionCollection);
541 // If there were any collisions in the collection, make sure we don't use the
542 // same instance next time.
543 if (collisionCollection.Count > 0)
544 collisionCollection = null;
545 // End kludge
546 }
547
548 // Invoke the detailed logger and output something if it's enabled.
549 private void DetailLog(string msg, params Object[] args)
550 {
551 Scene.PhysicsLogging.Write(msg, args);
659 } 552 }
660} 553}
661} 554}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
index 65fac00..25084d8 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
@@ -34,20 +34,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
34 34
35public abstract class BSConstraint : IDisposable 35public abstract class BSConstraint : IDisposable
36{ 36{
37 private static string LogHeader = "[BULLETSIM CONSTRAINT]";
38
39 protected BulletSim m_world; 37 protected BulletSim m_world;
40 protected BulletBody m_body1; 38 protected BulletBody m_body1;
41 protected BulletBody m_body2; 39 protected BulletBody m_body2;
42 protected BulletConstraint m_constraint; 40 protected BulletConstraint m_constraint;
43 protected bool m_enabled = false; 41 protected bool m_enabled = false;
44 42
45 public BulletBody Body1 { get { return m_body1; } }
46 public BulletBody Body2 { get { return m_body2; } }
47 public BulletConstraint Constraint { get { return m_constraint; } }
48 public abstract ConstraintType Type { get; }
49 public bool IsEnabled { get { return m_enabled; } }
50
51 public BSConstraint() 43 public BSConstraint()
52 { 44 {
53 } 45 }
@@ -56,25 +48,22 @@ public abstract class BSConstraint : IDisposable
56 { 48 {
57 if (m_enabled) 49 if (m_enabled)
58 { 50 {
51 // BulletSimAPI.RemoveConstraint(m_world.ID, m_body1.ID, m_body2.ID);
52 bool success = BulletSimAPI.DestroyConstraint2(m_world.Ptr, m_constraint.Ptr);
53 m_world.scene.DetailLog("{0},BSConstraint.Dispose,taint,body1={1},body2={2},success={3}", BSScene.DetailLogZero, m_body1.ID, m_body2.ID, success);
54 m_constraint.Ptr = System.IntPtr.Zero;
59 m_enabled = false; 55 m_enabled = false;
60 if (m_constraint.ptr != IntPtr.Zero)
61 {
62 bool success = BulletSimAPI.DestroyConstraint2(m_world.ptr, m_constraint.ptr);
63 m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,id1={1},body1={2},id2={3},body2={4},success={5}",
64 BSScene.DetailLogZero,
65 m_body1.ID, m_body1.ptr.ToString("X"),
66 m_body2.ID, m_body2.ptr.ToString("X"),
67 success);
68 m_constraint.ptr = System.IntPtr.Zero;
69 }
70 } 56 }
71 } 57 }
72 58
59 public BulletBody Body1 { get { return m_body1; } }
60 public BulletBody Body2 { get { return m_body2; } }
61
73 public virtual bool SetLinearLimits(Vector3 low, Vector3 high) 62 public virtual bool SetLinearLimits(Vector3 low, Vector3 high)
74 { 63 {
75 bool ret = false; 64 bool ret = false;
76 if (m_enabled) 65 if (m_enabled)
77 ret = BulletSimAPI.SetLinearLimits2(m_constraint.ptr, low, high); 66 ret = BulletSimAPI.SetLinearLimits2(m_constraint.Ptr, low, high);
78 return ret; 67 return ret;
79 } 68 }
80 69
@@ -82,18 +71,7 @@ public abstract class BSConstraint : IDisposable
82 { 71 {
83 bool ret = false; 72 bool ret = false;
84 if (m_enabled) 73 if (m_enabled)
85 ret = BulletSimAPI.SetAngularLimits2(m_constraint.ptr, low, high); 74 ret = BulletSimAPI.SetAngularLimits2(m_constraint.Ptr, low, high);
86 return ret;
87 }
88
89 public virtual bool SetSolverIterations(float cnt)
90 {
91 bool ret = false;
92 if (m_enabled)
93 {
94 BulletSimAPI.SetConstraintNumSolverIterations2(m_constraint.ptr, cnt);
95 ret = true;
96 }
97 return ret; 75 return ret;
98 } 76 }
99 77
@@ -103,7 +81,7 @@ public abstract class BSConstraint : IDisposable
103 if (m_enabled) 81 if (m_enabled)
104 { 82 {
105 // Recompute the internal transforms 83 // Recompute the internal transforms
106 BulletSimAPI.CalculateTransforms2(m_constraint.ptr); 84 BulletSimAPI.CalculateTransforms2(m_constraint.Ptr);
107 ret = true; 85 ret = true;
108 } 86 }
109 return ret; 87 return ret;
@@ -119,14 +97,13 @@ public abstract class BSConstraint : IDisposable
119 ret = CalculateTransforms(); 97 ret = CalculateTransforms();
120 if (ret) 98 if (ret)
121 { 99 {
122 // Setting an object's mass to zero (making it static like when it's selected) 100 // m_world.scene.PhysicsLogging.Write("{0},BSConstraint.RecomputeConstraintVariables,taint,enabling,A={1},B={2}",
123 // automatically disables the constraints. 101 // BSScene.DetailLogZero, Body1.ID, Body2.ID);
124 // If the link is enabled, be sure to set the constraint itself to enabled. 102 BulletSimAPI.SetConstraintEnable2(m_constraint.Ptr, m_world.scene.NumericBool(true));
125 BulletSimAPI.SetConstraintEnable2(m_constraint.ptr, m_world.physicsScene.NumericBool(true));
126 } 103 }
127 else 104 else
128 { 105 {
129 m_world.physicsScene.Logger.ErrorFormat("{0} CalculateTransforms failed. A={1}, B={2}", LogHeader, Body1.ID, Body2.ID); 106 m_world.scene.Logger.ErrorFormat("[BULLETSIM CONSTRAINT] CalculateTransforms failed. A={0}, B={1}", Body1.ID, Body2.ID);
130 } 107 }
131 } 108 }
132 return ret; 109 return ret;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs
index a9fd826..22ea367 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs
@@ -33,7 +33,7 @@ using OpenMetaverse;
33namespace OpenSim.Region.Physics.BulletSPlugin 33namespace OpenSim.Region.Physics.BulletSPlugin
34{ 34{
35 35
36public sealed class BSConstraintCollection : IDisposable 36public class BSConstraintCollection : IDisposable
37{ 37{
38 // private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 38 // private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
39 // private static readonly string LogHeader = "[CONSTRAINT COLLECTION]"; 39 // private static readonly string LogHeader = "[CONSTRAINT COLLECTION]";
@@ -143,6 +143,8 @@ public sealed class BSConstraintCollection : IDisposable
143 // Return 'true' if any constraints were destroyed. 143 // Return 'true' if any constraints were destroyed.
144 public bool RemoveAndDestroyConstraint(BulletBody body1) 144 public bool RemoveAndDestroyConstraint(BulletBody body1)
145 { 145 {
146 // return BulletSimAPI.RemoveConstraintByID(m_world.ID, obj.ID);
147
146 List<BSConstraint> toRemove = new List<BSConstraint>(); 148 List<BSConstraint> toRemove = new List<BSConstraint>();
147 uint lookingID = body1.ID; 149 uint lookingID = body1.ID;
148 lock (m_constraints) 150 lock (m_constraints)
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index 819635a..5a9f135 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -23,7 +23,7 @@
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 * 26 */
27 27
28/* RA: June 14, 2011. Copied from ODEDynamics.cs and converted to 28/* RA: June 14, 2011. Copied from ODEDynamics.cs and converted to
29 * call the BulletSim system. 29 * call the BulletSim system.
@@ -52,15 +52,19 @@ using OpenSim.Region.Physics.Manager;
52 52
53namespace OpenSim.Region.Physics.BulletSPlugin 53namespace OpenSim.Region.Physics.BulletSPlugin
54{ 54{
55 public sealed class BSDynamics 55 public class BSDynamics
56 { 56 {
57 private BSScene PhysicsScene { get; set; } 57 private int frcount = 0; // Used to limit dynamics debug output to
58 // the prim this dynamic controller belongs to 58 // every 100th frame
59 private BSPrim Prim { get; set; }
60 59
61 // Vehicle properties 60 private BSPrim m_prim; // the prim this dynamic controller belongs to
62 public Vehicle Type { get; set; }
63 61
62 // Vehicle properties
63 private Vehicle m_type = Vehicle.TYPE_NONE; // If a 'VEHICLE', and what kind
64 public Vehicle Type
65 {
66 get { return m_type; }
67 }
64 // private Quaternion m_referenceFrame = Quaternion.Identity; // Axis modifier 68 // private Quaternion m_referenceFrame = Quaternion.Identity; // Axis modifier
65 private VehicleFlag m_flags = (VehicleFlag) 0; // Boolean settings: 69 private VehicleFlag m_flags = (VehicleFlag) 0; // Boolean settings:
66 // HOVER_TERRAIN_ONLY 70 // HOVER_TERRAIN_ONLY
@@ -70,15 +74,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
70 // HOVER_UP_ONLY 74 // HOVER_UP_ONLY
71 // LIMIT_MOTOR_UP 75 // LIMIT_MOTOR_UP
72 // LIMIT_ROLL_ONLY 76 // LIMIT_ROLL_ONLY
77 private VehicleFlag m_Hoverflags = (VehicleFlag)0;
73 private Vector3 m_BlockingEndPoint = Vector3.Zero; 78 private Vector3 m_BlockingEndPoint = Vector3.Zero;
74 private Quaternion m_RollreferenceFrame = Quaternion.Identity; 79 private Quaternion m_RollreferenceFrame = Quaternion.Identity;
75 private Quaternion m_referenceFrame = Quaternion.Identity;
76
77 // Linear properties 80 // Linear properties
78 private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time 81 private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time
79 private Vector3 m_linearMotorOffset = Vector3.Zero; // the point of force can be offset from the center
80 private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL 82 private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL
81 private Vector3 m_newVelocity = Vector3.Zero; // velocity computed to be applied to body 83 private Vector3 m_dir = Vector3.Zero; // velocity applied to body
82 private Vector3 m_linearFrictionTimescale = Vector3.Zero; 84 private Vector3 m_linearFrictionTimescale = Vector3.Zero;
83 private float m_linearMotorDecayTimescale = 0; 85 private float m_linearMotorDecayTimescale = 0;
84 private float m_linearMotorTimescale = 0; 86 private float m_linearMotorTimescale = 0;
@@ -89,28 +91,28 @@ namespace OpenSim.Region.Physics.BulletSPlugin
89 91
90 //Angular properties 92 //Angular properties
91 private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor 93 private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor
92 // private int m_angularMotorApply = 0; // application frame counter 94 private int m_angularMotorApply = 0; // application frame counter
93 private Vector3 m_angularMotorVelocity = Vector3.Zero; // current angular motor velocity 95 private Vector3 m_angularMotorVelocity = Vector3.Zero; // current angular motor velocity
94 private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate 96 private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate
95 private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate 97 private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate
96 private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate 98 private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate
97 private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body 99 private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body
98 private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body 100 // private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body
99 101
100 //Deflection properties 102 //Deflection properties
101 private float m_angularDeflectionEfficiency = 0; 103 // private float m_angularDeflectionEfficiency = 0;
102 private float m_angularDeflectionTimescale = 0; 104 // private float m_angularDeflectionTimescale = 0;
103 private float m_linearDeflectionEfficiency = 0; 105 // private float m_linearDeflectionEfficiency = 0;
104 private float m_linearDeflectionTimescale = 0; 106 // private float m_linearDeflectionTimescale = 0;
105 107
106 //Banking properties 108 //Banking properties
107 private float m_bankingEfficiency = 0; 109 // private float m_bankingEfficiency = 0;
108 private float m_bankingMix = 0; 110 // private float m_bankingMix = 0;
109 private float m_bankingTimescale = 0; 111 // private float m_bankingTimescale = 0;
110 112
111 //Hover and Buoyancy properties 113 //Hover and Buoyancy properties
112 private float m_VhoverHeight = 0f; 114 private float m_VhoverHeight = 0f;
113 private float m_VhoverEfficiency = 0f; 115// private float m_VhoverEfficiency = 0f;
114 private float m_VhoverTimescale = 0f; 116 private float m_VhoverTimescale = 0f;
115 private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height 117 private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height
116 private float m_VehicleBuoyancy = 0f; //KF: m_VehicleBuoyancy is set by VEHICLE_BUOYANCY for a vehicle. 118 private float m_VehicleBuoyancy = 0f; //KF: m_VehicleBuoyancy is set by VEHICLE_BUOYANCY for a vehicle.
@@ -122,74 +124,86 @@ namespace OpenSim.Region.Physics.BulletSPlugin
122 private float m_verticalAttractionEfficiency = 1.0f; // damped 124 private float m_verticalAttractionEfficiency = 1.0f; // damped
123 private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor. 125 private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor.
124 126
125 public BSDynamics(BSScene myScene, BSPrim myPrim) 127 public BSDynamics(BSPrim myPrim)
126 {
127 PhysicsScene = myScene;
128 Prim = myPrim;
129 Type = Vehicle.TYPE_NONE;
130 }
131
132 // Return 'true' if this vehicle is doing vehicle things
133 public bool IsActive
134 { 128 {
135 get { return Type != Vehicle.TYPE_NONE; } 129 m_prim = myPrim;
130 m_type = Vehicle.TYPE_NONE;
136 } 131 }
137 132
138 internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue) 133 internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue, float timestep)
139 { 134 {
140 VDetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue); 135 DetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue);
141 switch (pParam) 136 switch (pParam)
142 { 137 {
143 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: 138 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
144 m_angularDeflectionEfficiency = Math.Max(pValue, 0.01f); 139 if (pValue < 0.01f) pValue = 0.01f;
140 // m_angularDeflectionEfficiency = pValue;
145 break; 141 break;
146 case Vehicle.ANGULAR_DEFLECTION_TIMESCALE: 142 case Vehicle.ANGULAR_DEFLECTION_TIMESCALE:
147 m_angularDeflectionTimescale = Math.Max(pValue, 0.01f); 143 if (pValue < 0.01f) pValue = 0.01f;
144 // m_angularDeflectionTimescale = pValue;
148 break; 145 break;
149 case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE: 146 case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE:
150 m_angularMotorDecayTimescale = Math.Max(pValue, 0.01f); 147 if (pValue < 0.01f) pValue = 0.01f;
148 m_angularMotorDecayTimescale = pValue;
151 break; 149 break;
152 case Vehicle.ANGULAR_MOTOR_TIMESCALE: 150 case Vehicle.ANGULAR_MOTOR_TIMESCALE:
153 m_angularMotorTimescale = Math.Max(pValue, 0.01f); 151 if (pValue < 0.01f) pValue = 0.01f;
152 m_angularMotorTimescale = pValue;
154 break; 153 break;
155 case Vehicle.BANKING_EFFICIENCY: 154 case Vehicle.BANKING_EFFICIENCY:
156 m_bankingEfficiency = Math.Max(-1f, Math.Min(pValue, 1f)); 155 if (pValue < 0.01f) pValue = 0.01f;
156 // m_bankingEfficiency = pValue;
157 break; 157 break;
158 case Vehicle.BANKING_MIX: 158 case Vehicle.BANKING_MIX:
159 m_bankingMix = Math.Max(pValue, 0.01f); 159 if (pValue < 0.01f) pValue = 0.01f;
160 // m_bankingMix = pValue;
160 break; 161 break;
161 case Vehicle.BANKING_TIMESCALE: 162 case Vehicle.BANKING_TIMESCALE:
162 m_bankingTimescale = Math.Max(pValue, 0.01f); 163 if (pValue < 0.01f) pValue = 0.01f;
164 // m_bankingTimescale = pValue;
163 break; 165 break;
164 case Vehicle.BUOYANCY: 166 case Vehicle.BUOYANCY:
165 m_VehicleBuoyancy = Math.Max(-1f, Math.Min(pValue, 1f)); 167 if (pValue < -1f) pValue = -1f;
166 break; 168 if (pValue > 1f) pValue = 1f;
167 case Vehicle.HOVER_EFFICIENCY: 169 m_VehicleBuoyancy = pValue;
168 m_VhoverEfficiency = Math.Max(0f, Math.Min(pValue, 1f)); 170 break;
169 break; 171// case Vehicle.HOVER_EFFICIENCY:
172// if (pValue < 0f) pValue = 0f;
173// if (pValue > 1f) pValue = 1f;
174// m_VhoverEfficiency = pValue;
175// break;
170 case Vehicle.HOVER_HEIGHT: 176 case Vehicle.HOVER_HEIGHT:
171 m_VhoverHeight = pValue; 177 m_VhoverHeight = pValue;
172 break; 178 break;
173 case Vehicle.HOVER_TIMESCALE: 179 case Vehicle.HOVER_TIMESCALE:
174 m_VhoverTimescale = Math.Max(pValue, 0.01f); 180 if (pValue < 0.01f) pValue = 0.01f;
181 m_VhoverTimescale = pValue;
175 break; 182 break;
176 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY: 183 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
177 m_linearDeflectionEfficiency = Math.Max(pValue, 0.01f); 184 if (pValue < 0.01f) pValue = 0.01f;
185 // m_linearDeflectionEfficiency = pValue;
178 break; 186 break;
179 case Vehicle.LINEAR_DEFLECTION_TIMESCALE: 187 case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
180 m_linearDeflectionTimescale = Math.Max(pValue, 0.01f); 188 if (pValue < 0.01f) pValue = 0.01f;
189 // m_linearDeflectionTimescale = pValue;
181 break; 190 break;
182 case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE: 191 case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE:
183 m_linearMotorDecayTimescale = Math.Max(pValue, 0.01f); 192 if (pValue < 0.01f) pValue = 0.01f;
193 m_linearMotorDecayTimescale = pValue;
184 break; 194 break;
185 case Vehicle.LINEAR_MOTOR_TIMESCALE: 195 case Vehicle.LINEAR_MOTOR_TIMESCALE:
186 m_linearMotorTimescale = Math.Max(pValue, 0.01f); 196 if (pValue < 0.01f) pValue = 0.01f;
197 m_linearMotorTimescale = pValue;
187 break; 198 break;
188 case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY: 199 case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
189 m_verticalAttractionEfficiency = Math.Max(0.1f, Math.Min(pValue, 1f)); 200 if (pValue < 0.1f) pValue = 0.1f; // Less goes unstable
201 if (pValue > 1.0f) pValue = 1.0f;
202 m_verticalAttractionEfficiency = pValue;
190 break; 203 break;
191 case Vehicle.VERTICAL_ATTRACTION_TIMESCALE: 204 case Vehicle.VERTICAL_ATTRACTION_TIMESCALE:
192 m_verticalAttractionTimescale = Math.Max(pValue, 0.01f); 205 if (pValue < 0.01f) pValue = 0.01f;
206 m_verticalAttractionTimescale = pValue;
193 break; 207 break;
194 208
195 // These are vector properties but the engine lets you use a single float value to 209 // These are vector properties but the engine lets you use a single float value to
@@ -199,7 +213,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
199 break; 213 break;
200 case Vehicle.ANGULAR_MOTOR_DIRECTION: 214 case Vehicle.ANGULAR_MOTOR_DIRECTION:
201 m_angularMotorDirection = new Vector3(pValue, pValue, pValue); 215 m_angularMotorDirection = new Vector3(pValue, pValue, pValue);
202 // m_angularMotorApply = 100; 216 m_angularMotorApply = 10;
203 break; 217 break;
204 case Vehicle.LINEAR_FRICTION_TIMESCALE: 218 case Vehicle.LINEAR_FRICTION_TIMESCALE:
205 m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue); 219 m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue);
@@ -209,27 +223,30 @@ namespace OpenSim.Region.Physics.BulletSPlugin
209 m_linearMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue); 223 m_linearMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue);
210 break; 224 break;
211 case Vehicle.LINEAR_MOTOR_OFFSET: 225 case Vehicle.LINEAR_MOTOR_OFFSET:
212 m_linearMotorOffset = new Vector3(pValue, pValue, pValue); 226 // m_linearMotorOffset = new Vector3(pValue, pValue, pValue);
213 break; 227 break;
214 228
215 } 229 }
216 }//end ProcessFloatVehicleParam 230 }//end ProcessFloatVehicleParam
217 231
218 internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue) 232 internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue, float timestep)
219 { 233 {
220 VDetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue); 234 DetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue);
221 switch (pParam) 235 switch (pParam)
222 { 236 {
223 case Vehicle.ANGULAR_FRICTION_TIMESCALE: 237 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
224 m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); 238 m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
225 break; 239 break;
226 case Vehicle.ANGULAR_MOTOR_DIRECTION: 240 case Vehicle.ANGULAR_MOTOR_DIRECTION:
227 // Limit requested angular speed to 2 rps= 4 pi rads/sec
228 pValue.X = Math.Max(-12.56f, Math.Min(pValue.X, 12.56f));
229 pValue.Y = Math.Max(-12.56f, Math.Min(pValue.Y, 12.56f));
230 pValue.Z = Math.Max(-12.56f, Math.Min(pValue.Z, 12.56f));
231 m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); 241 m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
232 // m_angularMotorApply = 100; 242 // Limit requested angular speed to 2 rps= 4 pi rads/sec
243 if (m_angularMotorDirection.X > 12.56f) m_angularMotorDirection.X = 12.56f;
244 if (m_angularMotorDirection.X < - 12.56f) m_angularMotorDirection.X = - 12.56f;
245 if (m_angularMotorDirection.Y > 12.56f) m_angularMotorDirection.Y = 12.56f;
246 if (m_angularMotorDirection.Y < - 12.56f) m_angularMotorDirection.Y = - 12.56f;
247 if (m_angularMotorDirection.Z > 12.56f) m_angularMotorDirection.Z = 12.56f;
248 if (m_angularMotorDirection.Z < - 12.56f) m_angularMotorDirection.Z = - 12.56f;
249 m_angularMotorApply = 10;
233 break; 250 break;
234 case Vehicle.LINEAR_FRICTION_TIMESCALE: 251 case Vehicle.LINEAR_FRICTION_TIMESCALE:
235 m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); 252 m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
@@ -239,7 +256,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
239 m_linearMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z); 256 m_linearMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z);
240 break; 257 break;
241 case Vehicle.LINEAR_MOTOR_OFFSET: 258 case Vehicle.LINEAR_MOTOR_OFFSET:
242 m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z); 259 // m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z);
243 break; 260 break;
244 case Vehicle.BLOCK_EXIT: 261 case Vehicle.BLOCK_EXIT:
245 m_BlockingEndPoint = new Vector3(pValue.X, pValue.Y, pValue.Z); 262 m_BlockingEndPoint = new Vector3(pValue.X, pValue.Y, pValue.Z);
@@ -249,11 +266,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
249 266
250 internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) 267 internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue)
251 { 268 {
252 VDetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue); 269 DetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue);
253 switch (pParam) 270 switch (pParam)
254 { 271 {
255 case Vehicle.REFERENCE_FRAME: 272 case Vehicle.REFERENCE_FRAME:
256 m_referenceFrame = pValue; 273 // m_referenceFrame = pValue;
257 break; 274 break;
258 case Vehicle.ROLL_FRAME: 275 case Vehicle.ROLL_FRAME:
259 m_RollreferenceFrame = pValue; 276 m_RollreferenceFrame = pValue;
@@ -263,492 +280,575 @@ namespace OpenSim.Region.Physics.BulletSPlugin
263 280
264 internal void ProcessVehicleFlags(int pParam, bool remove) 281 internal void ProcessVehicleFlags(int pParam, bool remove)
265 { 282 {
266 VDetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", Prim.LocalID, pParam, remove); 283 DetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", m_prim.LocalID, pParam, remove);
267 VehicleFlag parm = (VehicleFlag)pParam; 284 if (remove)
268 if (pParam == -1) 285 {
269 m_flags = (VehicleFlag)0; 286 if (pParam == -1)
287 {
288 m_flags = (VehicleFlag)0;
289 m_Hoverflags = (VehicleFlag)0;
290 return;
291 }
292 if ((pParam & (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) == (int)VehicleFlag.HOVER_GLOBAL_HEIGHT)
293 {
294 if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != (VehicleFlag)0)
295 m_Hoverflags &= ~(VehicleFlag.HOVER_GLOBAL_HEIGHT);
296 }
297 if ((pParam & (int)VehicleFlag.HOVER_TERRAIN_ONLY) == (int)VehicleFlag.HOVER_TERRAIN_ONLY)
298 {
299 if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != (VehicleFlag)0)
300 m_Hoverflags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY);
301 }
302 if ((pParam & (int)VehicleFlag.HOVER_UP_ONLY) == (int)VehicleFlag.HOVER_UP_ONLY)
303 {
304 if ((m_Hoverflags & VehicleFlag.HOVER_UP_ONLY) != (VehicleFlag)0)
305 m_Hoverflags &= ~(VehicleFlag.HOVER_UP_ONLY);
306 }
307 if ((pParam & (int)VehicleFlag.HOVER_WATER_ONLY) == (int)VehicleFlag.HOVER_WATER_ONLY)
308 {
309 if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != (VehicleFlag)0)
310 m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY);
311 }
312 if ((pParam & (int)VehicleFlag.LIMIT_MOTOR_UP) == (int)VehicleFlag.LIMIT_MOTOR_UP)
313 {
314 if ((m_flags & VehicleFlag.LIMIT_MOTOR_UP) != (VehicleFlag)0)
315 m_flags &= ~(VehicleFlag.LIMIT_MOTOR_UP);
316 }
317 if ((pParam & (int)VehicleFlag.LIMIT_ROLL_ONLY) == (int)VehicleFlag.LIMIT_ROLL_ONLY)
318 {
319 if ((m_flags & VehicleFlag.LIMIT_ROLL_ONLY) != (VehicleFlag)0)
320 m_flags &= ~(VehicleFlag.LIMIT_ROLL_ONLY);
321 }
322 if ((pParam & (int)VehicleFlag.MOUSELOOK_BANK) == (int)VehicleFlag.MOUSELOOK_BANK)
323 {
324 if ((m_flags & VehicleFlag.MOUSELOOK_BANK) != (VehicleFlag)0)
325 m_flags &= ~(VehicleFlag.MOUSELOOK_BANK);
326 }
327 if ((pParam & (int)VehicleFlag.MOUSELOOK_STEER) == (int)VehicleFlag.MOUSELOOK_STEER)
328 {
329 if ((m_flags & VehicleFlag.MOUSELOOK_STEER) != (VehicleFlag)0)
330 m_flags &= ~(VehicleFlag.MOUSELOOK_STEER);
331 }
332 if ((pParam & (int)VehicleFlag.NO_DEFLECTION_UP) == (int)VehicleFlag.NO_DEFLECTION_UP)
333 {
334 if ((m_flags & VehicleFlag.NO_DEFLECTION_UP) != (VehicleFlag)0)
335 m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP);
336 }
337 if ((pParam & (int)VehicleFlag.CAMERA_DECOUPLED) == (int)VehicleFlag.CAMERA_DECOUPLED)
338 {
339 if ((m_flags & VehicleFlag.CAMERA_DECOUPLED) != (VehicleFlag)0)
340 m_flags &= ~(VehicleFlag.CAMERA_DECOUPLED);
341 }
342 if ((pParam & (int)VehicleFlag.NO_X) == (int)VehicleFlag.NO_X)
343 {
344 if ((m_flags & VehicleFlag.NO_X) != (VehicleFlag)0)
345 m_flags &= ~(VehicleFlag.NO_X);
346 }
347 if ((pParam & (int)VehicleFlag.NO_Y) == (int)VehicleFlag.NO_Y)
348 {
349 if ((m_flags & VehicleFlag.NO_Y) != (VehicleFlag)0)
350 m_flags &= ~(VehicleFlag.NO_Y);
351 }
352 if ((pParam & (int)VehicleFlag.NO_Z) == (int)VehicleFlag.NO_Z)
353 {
354 if ((m_flags & VehicleFlag.NO_Z) != (VehicleFlag)0)
355 m_flags &= ~(VehicleFlag.NO_Z);
356 }
357 if ((pParam & (int)VehicleFlag.LOCK_HOVER_HEIGHT) == (int)VehicleFlag.LOCK_HOVER_HEIGHT)
358 {
359 if ((m_Hoverflags & VehicleFlag.LOCK_HOVER_HEIGHT) != (VehicleFlag)0)
360 m_Hoverflags &= ~(VehicleFlag.LOCK_HOVER_HEIGHT);
361 }
362 if ((pParam & (int)VehicleFlag.NO_DEFLECTION) == (int)VehicleFlag.NO_DEFLECTION)
363 {
364 if ((m_flags & VehicleFlag.NO_DEFLECTION) != (VehicleFlag)0)
365 m_flags &= ~(VehicleFlag.NO_DEFLECTION);
366 }
367 if ((pParam & (int)VehicleFlag.LOCK_ROTATION) == (int)VehicleFlag.LOCK_ROTATION)
368 {
369 if ((m_flags & VehicleFlag.LOCK_ROTATION) != (VehicleFlag)0)
370 m_flags &= ~(VehicleFlag.LOCK_ROTATION);
371 }
372 }
270 else 373 else
271 { 374 {
272 if (remove) 375 if ((pParam & (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) == (int)VehicleFlag.HOVER_GLOBAL_HEIGHT)
273 m_flags &= ~parm; 376 {
274 else 377 m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT | m_flags);
275 m_flags |= parm; 378 }
379 if ((pParam & (int)VehicleFlag.HOVER_TERRAIN_ONLY) == (int)VehicleFlag.HOVER_TERRAIN_ONLY)
380 {
381 m_Hoverflags |= (VehicleFlag.HOVER_TERRAIN_ONLY | m_flags);
382 }
383 if ((pParam & (int)VehicleFlag.HOVER_UP_ONLY) == (int)VehicleFlag.HOVER_UP_ONLY)
384 {
385 m_Hoverflags |= (VehicleFlag.HOVER_UP_ONLY | m_flags);
386 }
387 if ((pParam & (int)VehicleFlag.HOVER_WATER_ONLY) == (int)VehicleFlag.HOVER_WATER_ONLY)
388 {
389 m_Hoverflags |= (VehicleFlag.HOVER_WATER_ONLY | m_flags);
390 }
391 if ((pParam & (int)VehicleFlag.LIMIT_MOTOR_UP) == (int)VehicleFlag.LIMIT_MOTOR_UP)
392 {
393 m_flags |= (VehicleFlag.LIMIT_MOTOR_UP | m_flags);
394 }
395 if ((pParam & (int)VehicleFlag.MOUSELOOK_BANK) == (int)VehicleFlag.MOUSELOOK_BANK)
396 {
397 m_flags |= (VehicleFlag.MOUSELOOK_BANK | m_flags);
398 }
399 if ((pParam & (int)VehicleFlag.MOUSELOOK_STEER) == (int)VehicleFlag.MOUSELOOK_STEER)
400 {
401 m_flags |= (VehicleFlag.MOUSELOOK_STEER | m_flags);
402 }
403 if ((pParam & (int)VehicleFlag.NO_DEFLECTION_UP) == (int)VehicleFlag.NO_DEFLECTION_UP)
404 {
405 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | m_flags);
406 }
407 if ((pParam & (int)VehicleFlag.CAMERA_DECOUPLED) == (int)VehicleFlag.CAMERA_DECOUPLED)
408 {
409 m_flags |= (VehicleFlag.CAMERA_DECOUPLED | m_flags);
410 }
411 if ((pParam & (int)VehicleFlag.NO_X) == (int)VehicleFlag.NO_X)
412 {
413 m_flags |= (VehicleFlag.NO_X);
414 }
415 if ((pParam & (int)VehicleFlag.NO_Y) == (int)VehicleFlag.NO_Y)
416 {
417 m_flags |= (VehicleFlag.NO_Y);
418 }
419 if ((pParam & (int)VehicleFlag.NO_Z) == (int)VehicleFlag.NO_Z)
420 {
421 m_flags |= (VehicleFlag.NO_Z);
422 }
423 if ((pParam & (int)VehicleFlag.LOCK_HOVER_HEIGHT) == (int)VehicleFlag.LOCK_HOVER_HEIGHT)
424 {
425 m_Hoverflags |= (VehicleFlag.LOCK_HOVER_HEIGHT);
426 }
427 if ((pParam & (int)VehicleFlag.NO_DEFLECTION) == (int)VehicleFlag.NO_DEFLECTION)
428 {
429 m_flags |= (VehicleFlag.NO_DEFLECTION);
430 }
431 if ((pParam & (int)VehicleFlag.LOCK_ROTATION) == (int)VehicleFlag.LOCK_ROTATION)
432 {
433 m_flags |= (VehicleFlag.LOCK_ROTATION);
434 }
276 } 435 }
277 } 436 }//end ProcessVehicleFlags
278 437
279 internal void ProcessTypeChange(Vehicle pType) 438 internal void ProcessTypeChange(Vehicle pType)
280 { 439 {
281 VDetailLog("{0},ProcessTypeChange,type={1}", Prim.LocalID, pType); 440 DetailLog("{0},ProcessTypeChange,type={1}", m_prim.LocalID, pType);
282 // Set Defaults For Type 441 // Set Defaults For Type
283 Type = pType; 442 m_type = pType;
284 switch (pType) 443 switch (pType)
285 { 444 {
286 case Vehicle.TYPE_NONE: 445 case Vehicle.TYPE_NONE:
446 m_linearFrictionTimescale = new Vector3(0, 0, 0);
447 m_angularFrictionTimescale = new Vector3(0, 0, 0);
287 m_linearMotorDirection = Vector3.Zero; 448 m_linearMotorDirection = Vector3.Zero;
288 m_linearMotorTimescale = 0; 449 m_linearMotorTimescale = 0;
289 m_linearMotorDecayTimescale = 0; 450 m_linearMotorDecayTimescale = 0;
290 m_linearFrictionTimescale = new Vector3(0, 0, 0);
291
292 m_angularMotorDirection = Vector3.Zero; 451 m_angularMotorDirection = Vector3.Zero;
293 m_angularMotorDecayTimescale = 0;
294 m_angularMotorTimescale = 0; 452 m_angularMotorTimescale = 0;
295 m_angularFrictionTimescale = new Vector3(0, 0, 0); 453 m_angularMotorDecayTimescale = 0;
296
297 m_VhoverHeight = 0; 454 m_VhoverHeight = 0;
298 m_VhoverEfficiency = 0;
299 m_VhoverTimescale = 0; 455 m_VhoverTimescale = 0;
300 m_VehicleBuoyancy = 0; 456 m_VehicleBuoyancy = 0;
301
302 m_linearDeflectionEfficiency = 1;
303 m_linearDeflectionTimescale = 1;
304
305 m_angularDeflectionEfficiency = 0;
306 m_angularDeflectionTimescale = 1000;
307
308 m_verticalAttractionEfficiency = 0;
309 m_verticalAttractionTimescale = 0;
310
311 m_bankingEfficiency = 0;
312 m_bankingTimescale = 1000;
313 m_bankingMix = 1;
314
315 m_referenceFrame = Quaternion.Identity;
316 m_flags = (VehicleFlag)0; 457 m_flags = (VehicleFlag)0;
317 break; 458 break;
318 459
319 case Vehicle.TYPE_SLED: 460 case Vehicle.TYPE_SLED:
461 m_linearFrictionTimescale = new Vector3(30, 1, 1000);
462 m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
320 m_linearMotorDirection = Vector3.Zero; 463 m_linearMotorDirection = Vector3.Zero;
321 m_linearMotorTimescale = 1000; 464 m_linearMotorTimescale = 1000;
322 m_linearMotorDecayTimescale = 120; 465 m_linearMotorDecayTimescale = 120;
323 m_linearFrictionTimescale = new Vector3(30, 1, 1000);
324
325 m_angularMotorDirection = Vector3.Zero; 466 m_angularMotorDirection = Vector3.Zero;
326 m_angularMotorTimescale = 1000; 467 m_angularMotorTimescale = 1000;
327 m_angularMotorDecayTimescale = 120; 468 m_angularMotorDecayTimescale = 120;
328 m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
329
330 m_VhoverHeight = 0; 469 m_VhoverHeight = 0;
331 m_VhoverEfficiency = 10; // TODO: this looks wrong!! 470// m_VhoverEfficiency = 1;
332 m_VhoverTimescale = 10; 471 m_VhoverTimescale = 10;
333 m_VehicleBuoyancy = 0; 472 m_VehicleBuoyancy = 0;
334 473 // m_linearDeflectionEfficiency = 1;
335 m_linearDeflectionEfficiency = 1; 474 // m_linearDeflectionTimescale = 1;
336 m_linearDeflectionTimescale = 1; 475 // m_angularDeflectionEfficiency = 1;
337 476 // m_angularDeflectionTimescale = 1000;
338 m_angularDeflectionEfficiency = 1; 477 // m_bankingEfficiency = 0;
339 m_angularDeflectionTimescale = 1000; 478 // m_bankingMix = 1;
340 479 // m_bankingTimescale = 10;
341 m_verticalAttractionEfficiency = 0; 480 // m_referenceFrame = Quaternion.Identity;
342 m_verticalAttractionTimescale = 0; 481 m_Hoverflags &=
343
344 m_bankingEfficiency = 0;
345 m_bankingTimescale = 10;
346 m_bankingMix = 1;
347
348 m_referenceFrame = Quaternion.Identity;
349 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
350 m_flags &=
351 ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | 482 ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
352 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); 483 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
484 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
353 break; 485 break;
354 case Vehicle.TYPE_CAR: 486 case Vehicle.TYPE_CAR:
487 m_linearFrictionTimescale = new Vector3(100, 2, 1000);
488 m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
355 m_linearMotorDirection = Vector3.Zero; 489 m_linearMotorDirection = Vector3.Zero;
356 m_linearMotorTimescale = 1; 490 m_linearMotorTimescale = 1;
357 m_linearMotorDecayTimescale = 60; 491 m_linearMotorDecayTimescale = 60;
358 m_linearFrictionTimescale = new Vector3(100, 2, 1000);
359
360 m_angularMotorDirection = Vector3.Zero; 492 m_angularMotorDirection = Vector3.Zero;
361 m_angularMotorTimescale = 1; 493 m_angularMotorTimescale = 1;
362 m_angularMotorDecayTimescale = 0.8f; 494 m_angularMotorDecayTimescale = 0.8f;
363 m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
364
365 m_VhoverHeight = 0; 495 m_VhoverHeight = 0;
366 m_VhoverEfficiency = 0; 496// m_VhoverEfficiency = 0;
367 m_VhoverTimescale = 1000; 497 m_VhoverTimescale = 1000;
368 m_VehicleBuoyancy = 0; 498 m_VehicleBuoyancy = 0;
369 499 // // m_linearDeflectionEfficiency = 1;
370 m_linearDeflectionEfficiency = 1; 500 // // m_linearDeflectionTimescale = 2;
371 m_linearDeflectionTimescale = 2; 501 // // m_angularDeflectionEfficiency = 0;
372 502 // m_angularDeflectionTimescale = 10;
373 m_angularDeflectionEfficiency = 0;
374 m_angularDeflectionTimescale = 10;
375
376 m_verticalAttractionEfficiency = 1f; 503 m_verticalAttractionEfficiency = 1f;
377 m_verticalAttractionTimescale = 10f; 504 m_verticalAttractionTimescale = 10f;
378 505 // m_bankingEfficiency = -0.2f;
379 m_bankingEfficiency = -0.2f; 506 // m_bankingMix = 1;
380 m_bankingMix = 1; 507 // m_bankingTimescale = 1;
381 m_bankingTimescale = 1; 508 // m_referenceFrame = Quaternion.Identity;
382 509 m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT);
383 m_referenceFrame = Quaternion.Identity; 510 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY |
384 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY 511 VehicleFlag.LIMIT_MOTOR_UP);
385 | VehicleFlag.HOVER_TERRAIN_ONLY 512 m_Hoverflags |= (VehicleFlag.HOVER_UP_ONLY);
386 | VehicleFlag.HOVER_GLOBAL_HEIGHT);
387 m_flags |= (VehicleFlag.NO_DEFLECTION_UP
388 | VehicleFlag.LIMIT_ROLL_ONLY
389 | VehicleFlag.LIMIT_MOTOR_UP
390 | VehicleFlag.HOVER_UP_ONLY);
391 break; 513 break;
392 case Vehicle.TYPE_BOAT: 514 case Vehicle.TYPE_BOAT:
515 m_linearFrictionTimescale = new Vector3(10, 3, 2);
516 m_angularFrictionTimescale = new Vector3(10,10,10);
393 m_linearMotorDirection = Vector3.Zero; 517 m_linearMotorDirection = Vector3.Zero;
394 m_linearMotorTimescale = 5; 518 m_linearMotorTimescale = 5;
395 m_linearMotorDecayTimescale = 60; 519 m_linearMotorDecayTimescale = 60;
396 m_linearFrictionTimescale = new Vector3(10, 3, 2);
397
398 m_angularMotorDirection = Vector3.Zero; 520 m_angularMotorDirection = Vector3.Zero;
399 m_angularMotorTimescale = 4; 521 m_angularMotorTimescale = 4;
400 m_angularMotorDecayTimescale = 4; 522 m_angularMotorDecayTimescale = 4;
401 m_angularFrictionTimescale = new Vector3(10,10,10);
402
403 m_VhoverHeight = 0; 523 m_VhoverHeight = 0;
404 m_VhoverEfficiency = 0.5f; 524// m_VhoverEfficiency = 0.5f;
405 m_VhoverTimescale = 2; 525 m_VhoverTimescale = 2;
406 m_VehicleBuoyancy = 1; 526 m_VehicleBuoyancy = 1;
407 527 // m_linearDeflectionEfficiency = 0.5f;
408 m_linearDeflectionEfficiency = 0.5f; 528 // m_linearDeflectionTimescale = 3;
409 m_linearDeflectionTimescale = 3; 529 // m_angularDeflectionEfficiency = 0.5f;
410 530 // m_angularDeflectionTimescale = 5;
411 m_angularDeflectionEfficiency = 0.5f;
412 m_angularDeflectionTimescale = 5;
413
414 m_verticalAttractionEfficiency = 0.5f; 531 m_verticalAttractionEfficiency = 0.5f;
415 m_verticalAttractionTimescale = 5f; 532 m_verticalAttractionTimescale = 5f;
416 533 // m_bankingEfficiency = -0.3f;
417 m_bankingEfficiency = -0.3f; 534 // m_bankingMix = 0.8f;
418 m_bankingMix = 0.8f; 535 // m_bankingTimescale = 1;
419 m_bankingTimescale = 1; 536 // m_referenceFrame = Quaternion.Identity;
420 537 m_Hoverflags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY |
421 m_referenceFrame = Quaternion.Identity; 538 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
422 m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY 539 m_flags &= ~(VehicleFlag.LIMIT_ROLL_ONLY);
423 | VehicleFlag.HOVER_GLOBAL_HEIGHT 540 m_flags |= (VehicleFlag.NO_DEFLECTION_UP |
424 | VehicleFlag.LIMIT_ROLL_ONLY 541 VehicleFlag.LIMIT_MOTOR_UP);
425 | VehicleFlag.HOVER_UP_ONLY); 542 m_Hoverflags |= (VehicleFlag.HOVER_WATER_ONLY);
426 m_flags |= (VehicleFlag.NO_DEFLECTION_UP
427 | VehicleFlag.LIMIT_MOTOR_UP
428 | VehicleFlag.HOVER_WATER_ONLY);
429 break; 543 break;
430 case Vehicle.TYPE_AIRPLANE: 544 case Vehicle.TYPE_AIRPLANE:
545 m_linearFrictionTimescale = new Vector3(200, 10, 5);
546 m_angularFrictionTimescale = new Vector3(20, 20, 20);
431 m_linearMotorDirection = Vector3.Zero; 547 m_linearMotorDirection = Vector3.Zero;
432 m_linearMotorTimescale = 2; 548 m_linearMotorTimescale = 2;
433 m_linearMotorDecayTimescale = 60; 549 m_linearMotorDecayTimescale = 60;
434 m_linearFrictionTimescale = new Vector3(200, 10, 5);
435
436 m_angularMotorDirection = Vector3.Zero; 550 m_angularMotorDirection = Vector3.Zero;
437 m_angularMotorTimescale = 4; 551 m_angularMotorTimescale = 4;
438 m_angularMotorDecayTimescale = 4; 552 m_angularMotorDecayTimescale = 4;
439 m_angularFrictionTimescale = new Vector3(20, 20, 20);
440
441 m_VhoverHeight = 0; 553 m_VhoverHeight = 0;
442 m_VhoverEfficiency = 0.5f; 554// m_VhoverEfficiency = 0.5f;
443 m_VhoverTimescale = 1000; 555 m_VhoverTimescale = 1000;
444 m_VehicleBuoyancy = 0; 556 m_VehicleBuoyancy = 0;
445 557 // m_linearDeflectionEfficiency = 0.5f;
446 m_linearDeflectionEfficiency = 0.5f; 558 // m_linearDeflectionTimescale = 3;
447 m_linearDeflectionTimescale = 3; 559 // m_angularDeflectionEfficiency = 1;
448 560 // m_angularDeflectionTimescale = 2;
449 m_angularDeflectionEfficiency = 1;
450 m_angularDeflectionTimescale = 2;
451
452 m_verticalAttractionEfficiency = 0.9f; 561 m_verticalAttractionEfficiency = 0.9f;
453 m_verticalAttractionTimescale = 2f; 562 m_verticalAttractionTimescale = 2f;
454 563 // m_bankingEfficiency = 1;
455 m_bankingEfficiency = 1; 564 // m_bankingMix = 0.7f;
456 m_bankingMix = 0.7f; 565 // m_bankingTimescale = 2;
457 m_bankingTimescale = 2; 566 // m_referenceFrame = Quaternion.Identity;
458 567 m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
459 m_referenceFrame = Quaternion.Identity; 568 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
460 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY 569 m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP);
461 | VehicleFlag.HOVER_TERRAIN_ONLY
462 | VehicleFlag.HOVER_GLOBAL_HEIGHT
463 | VehicleFlag.HOVER_UP_ONLY
464 | VehicleFlag.NO_DEFLECTION_UP
465 | VehicleFlag.LIMIT_MOTOR_UP);
466 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); 570 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
467 break; 571 break;
468 case Vehicle.TYPE_BALLOON: 572 case Vehicle.TYPE_BALLOON:
573 m_linearFrictionTimescale = new Vector3(5, 5, 5);
574 m_angularFrictionTimescale = new Vector3(10, 10, 10);
469 m_linearMotorDirection = Vector3.Zero; 575 m_linearMotorDirection = Vector3.Zero;
470 m_linearMotorTimescale = 5; 576 m_linearMotorTimescale = 5;
471 m_linearFrictionTimescale = new Vector3(5, 5, 5);
472 m_linearMotorDecayTimescale = 60; 577 m_linearMotorDecayTimescale = 60;
473
474 m_angularMotorDirection = Vector3.Zero; 578 m_angularMotorDirection = Vector3.Zero;
475 m_angularMotorTimescale = 6; 579 m_angularMotorTimescale = 6;
476 m_angularFrictionTimescale = new Vector3(10, 10, 10);
477 m_angularMotorDecayTimescale = 10; 580 m_angularMotorDecayTimescale = 10;
478
479 m_VhoverHeight = 5; 581 m_VhoverHeight = 5;
480 m_VhoverEfficiency = 0.8f; 582// m_VhoverEfficiency = 0.8f;
481 m_VhoverTimescale = 10; 583 m_VhoverTimescale = 10;
482 m_VehicleBuoyancy = 1; 584 m_VehicleBuoyancy = 1;
483 585 // m_linearDeflectionEfficiency = 0;
484 m_linearDeflectionEfficiency = 0; 586 // m_linearDeflectionTimescale = 5;
485 m_linearDeflectionTimescale = 5; 587 // m_angularDeflectionEfficiency = 0;
486 588 // m_angularDeflectionTimescale = 5;
487 m_angularDeflectionEfficiency = 0;
488 m_angularDeflectionTimescale = 5;
489
490 m_verticalAttractionEfficiency = 1f; 589 m_verticalAttractionEfficiency = 1f;
491 m_verticalAttractionTimescale = 100f; 590 m_verticalAttractionTimescale = 100f;
492 591 // m_bankingEfficiency = 0;
493 m_bankingEfficiency = 0; 592 // m_bankingMix = 0.7f;
494 m_bankingMix = 0.7f; 593 // m_bankingTimescale = 5;
495 m_bankingTimescale = 5; 594 // m_referenceFrame = Quaternion.Identity;
496 m_referenceFrame = Quaternion.Identity; 595 m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
497 596 VehicleFlag.HOVER_UP_ONLY);
498 m_referenceFrame = Quaternion.Identity; 597 m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP);
499 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY 598 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
500 | VehicleFlag.HOVER_TERRAIN_ONLY 599 m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT);
501 | VehicleFlag.HOVER_UP_ONLY
502 | VehicleFlag.NO_DEFLECTION_UP
503 | VehicleFlag.LIMIT_MOTOR_UP);
504 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY
505 | VehicleFlag.HOVER_GLOBAL_HEIGHT);
506 break; 600 break;
507 } 601 }
508 } 602 }//end SetDefaultsForType
509 603
510 // Some of the properties of this prim may have changed.
511 // Do any updating needed for a vehicle
512 public void Refresh()
513 {
514 if (IsActive)
515 {
516 // Friction effects are handled by this vehicle code
517 BulletSimAPI.SetFriction2(Prim.PhysBody.ptr, 0f);
518 BulletSimAPI.SetHitFraction2(Prim.PhysBody.ptr, 0f);
519 }
520 }
521
522 // One step of the vehicle properties for the next 'pTimestep' seconds.
523 internal void Step(float pTimestep) 604 internal void Step(float pTimestep)
524 { 605 {
525 if (!IsActive) return; 606 if (m_type == Vehicle.TYPE_NONE) return;
526 607
527 // DEBUG 608 frcount++; // used to limit debug comment output
528 // Because Bullet does apply forces to the vehicle, our last computed 609 if (frcount > 100)
529 // linear and angular velocities are not what is happening now. 610 frcount = 0;
530 // Vector3 externalAngularVelocity = Prim.ForceRotationalVelocity - m_lastAngularVelocity;
531 // m_lastAngularVelocity += (externalAngularVelocity * 0.5f) * pTimestep;
532 // m_lastAngularVelocity = Prim.ForceRotationalVelocity; // DEBUG: account for what Bullet did last time
533 // m_lastLinearVelocityVector = Prim.ForceVelocity * Quaternion.Inverse(Prim.ForceOrientation); // DEBUG:
534 // END DEBUG
535 611
536 MoveLinear(pTimestep); 612 MoveLinear(pTimestep);
537 MoveAngular(pTimestep); 613 MoveAngular(pTimestep);
538 LimitRotation(pTimestep); 614 LimitRotation(pTimestep);
539 615
540 // DEBUG: Trying to figure out why Bullet goes crazy when the root prim is moved. 616 DetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}",
541 // BulletSimAPI.SetInterpolationVelocity2(Prim.BSBody.ptr, m_newVelocity, m_lastAngularVelocity); // DEBUG DEBUG DEBUG 617 m_prim.LocalID, m_prim.Position, m_prim.Force, m_prim.Velocity, m_prim.RotationalVelocity);
542
543 // remember the position so next step we can limit absolute movement effects
544 m_lastPositionVector = Prim.ForcePosition;
545
546 VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}",
547 Prim.LocalID, Prim.ForcePosition, Prim.Force, Prim.ForceVelocity, Prim.RotationalVelocity);
548 }// end Step 618 }// end Step
549 619
550 // Apply the effect of the linear motor.
551 // Also does hover and float.
552 private void MoveLinear(float pTimestep) 620 private void MoveLinear(float pTimestep)
553 { 621 {
554 // m_linearMotorDirection is the target direction we are moving relative to the vehicle coordinates 622 // requested m_linearMotorDirection is significant
555 // m_lastLinearVelocityVector is the current speed we are moving in that direction 623 // if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f))
556 if (m_linearMotorDirection.LengthSquared() > 0.001f) 624 if (m_linearMotorDirection.LengthSquared() > 0.0001f)
557 { 625 {
558 Vector3 origDir = m_linearMotorDirection; 626 Vector3 origDir = m_linearMotorDirection;
559 Vector3 origVel = m_lastLinearVelocityVector; 627 Vector3 origVel = m_lastLinearVelocityVector;
560 Vector3 vehicleVelocity = Prim.ForceVelocity * Quaternion.Inverse(Prim.ForceOrientation); // DEBUG
561 628
562 // add drive to body 629 // add drive to body
563 Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/(m_linearMotorTimescale) * pTimestep; 630 // Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep);
564 // lastLinearVelocityVector is the current body velocity vector 631 Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale);
632 // lastLinearVelocityVector is the current body velocity vector?
633 // RA: Not sure what the *10 is for. A correction for pTimestep?
634 // m_lastLinearVelocityVector += (addAmount*10);
635 m_lastLinearVelocityVector += addAmount;
636
637 // This will work temporarily, but we really need to compare speed on an axis
638 // KF: Limit body velocity to applied velocity?
639 // Limit the velocity vector to less than the last set linear motor direction
640 if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X))
641 m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X;
642 if (Math.Abs(m_lastLinearVelocityVector.Y) > Math.Abs(m_linearMotorDirectionLASTSET.Y))
643 m_lastLinearVelocityVector.Y = m_linearMotorDirectionLASTSET.Y;
644 if (Math.Abs(m_lastLinearVelocityVector.Z) > Math.Abs(m_linearMotorDirectionLASTSET.Z))
645 m_lastLinearVelocityVector.Z = m_linearMotorDirectionLASTSET.Z;
646
647 // decay applied velocity
648 Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep)));
649 m_linearMotorDirection -= m_linearMotorDirection * decayfraction * 0.5f;
650
651 /*
652 Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/m_linearMotorTimescale;
565 m_lastLinearVelocityVector += addAmount; 653 m_lastLinearVelocityVector += addAmount;
566 654
567 float decayFactor = (1.0f / m_linearMotorDecayTimescale) * pTimestep; 655 float decayfraction = (1.0f - 1.0f / m_linearMotorDecayTimescale);
568 m_linearMotorDirection *= (1f - decayFactor); 656 m_linearMotorDirection *= decayfraction;
569 657
570 Vector3 frictionFactor = (Vector3.One / m_linearFrictionTimescale) * pTimestep; 658 */
571 m_lastLinearVelocityVector *= (Vector3.One - frictionFactor);
572 659
573 // Rotate new object velocity from vehicle relative to world coordinates 660 DetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},add={3},decay={4},dir={5},vel={6}",
574 m_newVelocity = m_lastLinearVelocityVector * Prim.ForceOrientation; 661 m_prim.LocalID, origDir, origVel, addAmount, decayfraction, m_linearMotorDirection, m_lastLinearVelocityVector);
575
576 VDetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},vehVel={3},add={4},decay={5},frict={6},lmDir={7},lmVel={8},newVel={9}",
577 Prim.LocalID, origDir, origVel, vehicleVelocity, addAmount, decayFactor, frictionFactor,
578 m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity);
579 } 662 }
580 else 663 else
581 { 664 {
582 // if what remains of direction is very small, zero it. 665 // if what remains of applied is small, zero it.
666 // if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f))
667 // m_lastLinearVelocityVector = Vector3.Zero;
583 m_linearMotorDirection = Vector3.Zero; 668 m_linearMotorDirection = Vector3.Zero;
584 m_lastLinearVelocityVector = Vector3.Zero; 669 m_lastLinearVelocityVector = Vector3.Zero;
585 m_newVelocity = Vector3.Zero;
586
587 VDetailLog("{0},MoveLinear,zeroed", Prim.LocalID);
588 } 670 }
589 671
590 // m_newVelocity is velocity computed from linear motor in world coordinates 672 // convert requested object velocity to world-referenced vector
673 Quaternion rotq = m_prim.Orientation;
674 m_dir = m_lastLinearVelocityVector * rotq;
591 675
592 // Gravity and Buoyancy 676 // Add the various forces into m_dir which will be our new direction vector (velocity)
677
678 // add Gravity and Buoyancy
679 // KF: So far I have found no good method to combine a script-requested
680 // .Z velocity and gravity. Therefore only 0g will used script-requested
681 // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only.
682 Vector3 grav = Vector3.Zero;
593 // There is some gravity, make a gravity force vector that is applied after object velocity. 683 // There is some gravity, make a gravity force vector that is applied after object velocity.
594 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; 684 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
595 Vector3 grav = Prim.PhysicsScene.DefaultGravity * (1f - m_VehicleBuoyancy); 685 grav.Z = m_prim.Scene.DefaultGravity.Z * m_prim.Mass * (1f - m_VehicleBuoyancy);
596
597 /*
598 * RA: Not sure why one would do this unless we are hoping external forces are doing gravity, ...
599 // Preserve the current Z velocity 686 // Preserve the current Z velocity
600 Vector3 vel_now = m_prim.Velocity; 687 Vector3 vel_now = m_prim.Velocity;
601 m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity 688 m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity
602 */
603 689
604 Vector3 pos = Prim.ForcePosition; 690 Vector3 pos = m_prim.Position;
691 Vector3 posChange = pos;
605// Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f); 692// Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f);
693 double Zchange = Math.Abs(posChange.Z);
694 if (m_BlockingEndPoint != Vector3.Zero)
695 {
696 bool changed = false;
697 if (pos.X >= (m_BlockingEndPoint.X - (float)1))
698 {
699 pos.X -= posChange.X + 1;
700 changed = true;
701 }
702 if (pos.Y >= (m_BlockingEndPoint.Y - (float)1))
703 {
704 pos.Y -= posChange.Y + 1;
705 changed = true;
706 }
707 if (pos.Z >= (m_BlockingEndPoint.Z - (float)1))
708 {
709 pos.Z -= posChange.Z + 1;
710 changed = true;
711 }
712 if (pos.X <= 0)
713 {
714 pos.X += posChange.X + 1;
715 changed = true;
716 }
717 if (pos.Y <= 0)
718 {
719 pos.Y += posChange.Y + 1;
720 changed = true;
721 }
722 if (changed)
723 {
724 m_prim.Position = pos;
725 DetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}",
726 m_prim.LocalID, m_BlockingEndPoint, posChange, pos);
727 }
728 }
606 729
607 // If below the terrain, move us above the ground a little. 730 // If below the terrain, move us above the ground a little.
608 float terrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos); 731 if (pos.Z < m_prim.Scene.GetTerrainHeightAtXYZ(pos))
609 // Taking the rotated size doesn't work here because m_prim.Size is the size of the root prim and not the linkset.
610 // Need to add a m_prim.LinkSet.Size similar to m_prim.LinkSet.Mass.
611 // Vector3 rotatedSize = m_prim.Size * m_prim.ForceOrientation;
612 // if (rotatedSize.Z < terrainHeight)
613 if (pos.Z < terrainHeight)
614 { 732 {
615 pos.Z = terrainHeight + 2; 733 pos.Z = m_prim.Scene.GetTerrainHeightAtXYZ(pos) + 2;
616 Prim.ForcePosition = pos; 734 m_prim.Position = pos;
617 VDetailLog("{0},MoveLinear,terrainHeight,terrainHeight={1},pos={2}", Prim.LocalID, terrainHeight, pos); 735 DetailLog("{0},MoveLinear,terrainHeight,pos={1}", m_prim.LocalID, pos);
618 } 736 }
619 737
620 // Check if hovering 738 // Check if hovering
621 // m_VhoverEfficiency: 0=bouncy, 1=totally damped 739 if ((m_Hoverflags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0)
622 // m_VhoverTimescale: time to achieve height
623 if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0)
624 { 740 {
625 // We should hover, get the target height 741 // We should hover, get the target height
626 if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0) 742 if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != 0)
627 { 743 {
628 m_VhoverTargetHeight = Prim.PhysicsScene.GetWaterLevelAtXYZ(pos) + m_VhoverHeight; 744 m_VhoverTargetHeight = m_prim.Scene.GetWaterLevel() + m_VhoverHeight;
629 } 745 }
630 if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0) 746 if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
631 { 747 {
632 m_VhoverTargetHeight = terrainHeight + m_VhoverHeight; 748 m_VhoverTargetHeight = m_prim.Scene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight;
633 } 749 }
634 if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0) 750 if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0)
635 { 751 {
636 m_VhoverTargetHeight = m_VhoverHeight; 752 m_VhoverTargetHeight = m_VhoverHeight;
637 } 753 }
638 754
639 if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0) 755 if ((m_Hoverflags & VehicleFlag.HOVER_UP_ONLY) != 0)
640 { 756 {
641 // If body is aready heigher, use its height as target height 757 // If body is aready heigher, use its height as target height
642 if (pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z; 758 if (pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z;
643 } 759 }
644 if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) 760 if ((m_Hoverflags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0)
645 { 761 {
646 if ((pos.Z - m_VhoverTargetHeight) > .2 || (pos.Z - m_VhoverTargetHeight) < -.2) 762 if ((pos.Z - m_VhoverTargetHeight) > .2 || (pos.Z - m_VhoverTargetHeight) < -.2)
647 { 763 {
648 Prim.ForcePosition = pos; 764 m_prim.Position = pos;
649 } 765 }
650 } 766 }
651 else 767 else
652 { 768 {
653 float verticalError = pos.Z - m_VhoverTargetHeight; 769 float herr0 = pos.Z - m_VhoverTargetHeight;
654 // RA: where does the 50 come from?
655 float verticalCorrectionVelocity = pTimestep * ((verticalError * 50.0f) / m_VhoverTimescale);
656 // Replace Vertical speed with correction figure if significant 770 // Replace Vertical speed with correction figure if significant
657 if (Math.Abs(verticalError) > 0.01f) 771 if (Math.Abs(herr0) > 0.01f)
658 { 772 {
659 m_newVelocity.Z += verticalCorrectionVelocity; 773 m_dir.Z = -((herr0 * pTimestep * 50.0f) / m_VhoverTimescale);
660 //KF: m_VhoverEfficiency is not yet implemented 774 //KF: m_VhoverEfficiency is not yet implemented
661 } 775 }
662 else if (verticalError < -0.01)
663 {
664 m_newVelocity.Z -= verticalCorrectionVelocity;
665 }
666 else 776 else
667 { 777 {
668 m_newVelocity.Z = 0f; 778 m_dir.Z = 0f;
669 } 779 }
670 } 780 }
671 781
672 VDetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", Prim.LocalID, pos, m_newVelocity, m_VhoverHeight, m_VhoverTargetHeight); 782 DetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", m_prim.LocalID, pos, m_dir, m_VhoverHeight, m_VhoverTargetHeight);
673 }
674 783
675 Vector3 posChange = pos - m_lastPositionVector; 784// m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped
676 if (m_BlockingEndPoint != Vector3.Zero) 785// m_VhoverTimescale = 0f; // time to acheive height
677 { 786// pTimestep is time since last frame,in secs
678 bool changed = false;
679 if (pos.X >= (m_BlockingEndPoint.X - (float)1))
680 {
681 pos.X -= posChange.X + 1;
682 changed = true;
683 }
684 if (pos.Y >= (m_BlockingEndPoint.Y - (float)1))
685 {
686 pos.Y -= posChange.Y + 1;
687 changed = true;
688 }
689 if (pos.Z >= (m_BlockingEndPoint.Z - (float)1))
690 {
691 pos.Z -= posChange.Z + 1;
692 changed = true;
693 }
694 if (pos.X <= 0)
695 {
696 pos.X += posChange.X + 1;
697 changed = true;
698 }
699 if (pos.Y <= 0)
700 {
701 pos.Y += posChange.Y + 1;
702 changed = true;
703 }
704 if (changed)
705 {
706 Prim.ForcePosition = pos;
707 VDetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}",
708 Prim.LocalID, m_BlockingEndPoint, posChange, pos);
709 }
710 } 787 }
711 788
712 // Limit absolute vertical change
713 float Zchange = Math.Abs(posChange.Z);
714 if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) 789 if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0)
715 { 790 {
791 //Start Experimental Values
716 if (Zchange > .3) 792 if (Zchange > .3)
793 {
717 grav.Z = (float)(grav.Z * 3); 794 grav.Z = (float)(grav.Z * 3);
795 }
718 if (Zchange > .15) 796 if (Zchange > .15)
797 {
719 grav.Z = (float)(grav.Z * 2); 798 grav.Z = (float)(grav.Z * 2);
799 }
720 if (Zchange > .75) 800 if (Zchange > .75)
801 {
721 grav.Z = (float)(grav.Z * 1.5); 802 grav.Z = (float)(grav.Z * 1.5);
803 }
722 if (Zchange > .05) 804 if (Zchange > .05)
805 {
723 grav.Z = (float)(grav.Z * 1.25); 806 grav.Z = (float)(grav.Z * 1.25);
807 }
724 if (Zchange > .025) 808 if (Zchange > .025)
809 {
725 grav.Z = (float)(grav.Z * 1.125); 810 grav.Z = (float)(grav.Z * 1.125);
726 float postemp = (pos.Z - terrainHeight); 811 }
812 float terraintemp = m_prim.Scene.GetTerrainHeightAtXYZ(pos);
813 float postemp = (pos.Z - terraintemp);
727 if (postemp > 2.5f) 814 if (postemp > 2.5f)
815 {
728 grav.Z = (float)(grav.Z * 1.037125); 816 grav.Z = (float)(grav.Z * 1.037125);
729 VDetailLog("{0},MoveLinear,limitMotorUp,grav={1}", Prim.LocalID, grav); 817 }
818 DetailLog("{0},MoveLinear,limitMotorUp,grav={1}", m_prim.LocalID, grav);
819 //End Experimental Values
730 } 820 }
731
732 // If not changing some axis, reduce out velocity
733 if ((m_flags & (VehicleFlag.NO_X)) != 0) 821 if ((m_flags & (VehicleFlag.NO_X)) != 0)
734 m_newVelocity.X = 0; 822 {
823 m_dir.X = 0;
824 }
735 if ((m_flags & (VehicleFlag.NO_Y)) != 0) 825 if ((m_flags & (VehicleFlag.NO_Y)) != 0)
736 m_newVelocity.Y = 0; 826 {
827 m_dir.Y = 0;
828 }
737 if ((m_flags & (VehicleFlag.NO_Z)) != 0) 829 if ((m_flags & (VehicleFlag.NO_Z)) != 0)
738 m_newVelocity.Z = 0; 830 {
831 m_dir.Z = 0;
832 }
833
834 m_lastPositionVector = m_prim.Position;
739 835
740 // Apply velocity 836 // Apply velocity
741 Prim.ForceVelocity = m_newVelocity; 837 m_prim.Velocity = m_dir;
742 // Prim.AddForce(m_newVelocity * Prim.Linkset.LinksetMass, false); 838 // apply gravity force
743 Prim.AddForce(grav * Prim.Linkset.LinksetMass, false); 839 // Why is this set here? The physics engine already does gravity.
840 // m_prim.AddForce(grav, false);
841 // m_prim.Force = grav;
744 842
745 VDetailLog("{0},MoveLinear,done,lmDir={1},lmVel={2},newVel={3},grav={4}", 843 // Apply friction
746 Prim.LocalID, m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity, grav); 844 Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep);
845 m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount;
846
847 DetailLog("{0},MoveLinear,done,pos={1},vel={2},force={3},decay={4}",
848 m_prim.LocalID, m_lastPositionVector, m_dir, grav, decayamount);
747 849
748 } // end MoveLinear() 850 } // end MoveLinear()
749 851
750 // =======================================================================
751 // Apply the effect of the angular motor.
752 private void MoveAngular(float pTimestep) 852 private void MoveAngular(float pTimestep)
753 { 853 {
754 // m_angularMotorDirection // angular velocity requested by LSL motor 854 // m_angularMotorDirection // angular velocity requested by LSL motor
@@ -759,223 +859,160 @@ namespace OpenSim.Region.Physics.BulletSPlugin
759 // m_angularFrictionTimescale // body angular velocity decay rate 859 // m_angularFrictionTimescale // body angular velocity decay rate
760 // m_lastAngularVelocity // what was last applied to body 860 // m_lastAngularVelocity // what was last applied to body
761 861
762 if (m_angularMotorDirection.LengthSquared() > 0.0001) 862 // Get what the body is doing, this includes 'external' influences
763 { 863 Vector3 angularVelocity = m_prim.RotationalVelocity;
764 Vector3 origVel = m_angularMotorVelocity;
765 Vector3 origDir = m_angularMotorDirection;
766
767 // new velocity += error / ( time to get there / step interval)
768 // requested speed - last motor speed
769 m_angularMotorVelocity += (m_angularMotorDirection - m_angularMotorVelocity) / (m_angularMotorTimescale / pTimestep);
770 // decay requested direction
771 m_angularMotorDirection *= (1.0f - (pTimestep * 1.0f/m_angularMotorDecayTimescale));
772 864
773 VDetailLog("{0},MoveAngular,angularMotorApply,angTScale={1},timeStep={2},origvel={3},origDir={4},vel={5}", 865 if (m_angularMotorApply > 0)
774 Prim.LocalID, m_angularMotorTimescale, pTimestep, origVel, origDir, m_angularMotorVelocity); 866 {
867 // Rather than snapping the angular motor velocity from the old value to
868 // a newly set velocity, this routine steps the value from the previous
869 // value (m_angularMotorVelocity) to the requested value (m_angularMotorDirection).
870 // There are m_angularMotorApply steps.
871 Vector3 origAngularVelocity = m_angularMotorVelocity;
872 // ramp up to new value
873 // current velocity += error / (time to get there / step interval)
874 // requested speed - last motor speed
875 m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / pTimestep);
876 m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep);
877 m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep);
878
879 DetailLog("{0},MoveAngular,angularMotorApply,apply={1},origvel={2},dir={3},vel={4}",
880 m_prim.LocalID,m_angularMotorApply,origAngularVelocity, m_angularMotorDirection, m_angularMotorVelocity);
881
882 m_angularMotorApply--; // This is done so that if script request rate is less than phys frame rate the expected
883 // velocity may still be acheived.
775 } 884 }
776 else 885 else
777 { 886 {
778 m_angularMotorVelocity = Vector3.Zero; 887 // No motor recently applied, keep the body velocity
779 } 888 // and decay the velocity
780 889 m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep);
781 #region Vertical attactor 890 } // end motor section
782 891
892 // Vertical attractor section
783 Vector3 vertattr = Vector3.Zero; 893 Vector3 vertattr = Vector3.Zero;
784 Vector3 deflection = Vector3.Zero; 894 if (m_verticalAttractionTimescale < 300)
785 Vector3 banking = Vector3.Zero;
786
787 if (m_verticalAttractionTimescale < 300 && m_lastAngularVelocity != Vector3.Zero)
788 { 895 {
789 float VAservo = pTimestep * 0.2f / m_verticalAttractionTimescale; 896 float VAservo = 0.2f / (m_verticalAttractionTimescale * pTimestep);
790 if (Prim.Linkset.LinksetIsColliding) 897 // get present body rotation
791 VAservo = pTimestep * 0.05f / (m_verticalAttractionTimescale); 898 Quaternion rotq = m_prim.Orientation;
792 899 // make a vector pointing up
793 VAservo *= (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency); 900 Vector3 verterr = Vector3.Zero;
794 901 verterr.Z = 1.0f;
795 // Create a vector of the vehicle "up" in world coordinates 902 // rotate it to Body Angle
796 Vector3 verticalError = Vector3.UnitZ * Prim.ForceOrientation; 903 verterr = verterr * rotq;
797 // verticalError.X and .Y are the World error amounts. They are 0 when there is no 904 // verterr.X and .Y are the World error ammounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1.
798 // error (Vehicle Body is 'vertical'), and .Z will be 1. As the body leans to its 905 // As the body leans to its side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall and .Z will go
799 // side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall 906 // negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body.
800 // and .Z will go // negative. Similar for tilt and |.Y|. .X and .Y must be 907 if (verterr.Z < 0.0f)
801 // modulated to prevent a stable inverted body.
802
803 // Error is 0 (no error) to +/- 2 (max error)
804 if (verticalError.Z < 0.0f)
805 { 908 {
806 verticalError.X = 2.0f - verticalError.X; 909 verterr.X = 2.0f - verterr.X;
807 verticalError.Y = 2.0f - verticalError.Y; 910 verterr.Y = 2.0f - verterr.Y;
808 } 911 }
912 // Error is 0 (no error) to +/- 2 (max error)
809 // scale it by VAservo 913 // scale it by VAservo
810 verticalError = verticalError * VAservo; 914 verterr = verterr * VAservo;
811 915
812 // As the body rotates around the X axis, then verticalError.Y increases; Rotated around Y 916 // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so
813 // then .X increases, so change Body angular velocity X based on Y, and Y based on X. 917 // Change Body angular velocity X based on Y, and Y based on X. Z is not changed.
814 // Z is not changed. 918 vertattr.X = verterr.Y;
815 vertattr.X = verticalError.Y; 919 vertattr.Y = - verterr.X;
816 vertattr.Y = - verticalError.X;
817 vertattr.Z = 0f; 920 vertattr.Z = 0f;
818 921
819 // scaling appears better usingsquare-law 922 // scaling appears better usingsquare-law
820 Vector3 angularVelocity = Prim.ForceRotationalVelocity;
821 float bounce = 1.0f - (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency); 923 float bounce = 1.0f - (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency);
822 vertattr.X += bounce * angularVelocity.X; 924 vertattr.X += bounce * angularVelocity.X;
823 vertattr.Y += bounce * angularVelocity.Y; 925 vertattr.Y += bounce * angularVelocity.Y;
824 926
825 VDetailLog("{0},MoveAngular,verticalAttraction,verticalError={1},bounce={2},vertattr={3}", 927 DetailLog("{0},MoveAngular,verticalAttraction,verterr={1},bounce={2},vertattr={3}",
826 Prim.LocalID, verticalError, bounce, vertattr); 928 m_prim.LocalID, verterr, bounce, vertattr);
827
828 }
829 #endregion // Vertical attactor
830
831 #region Deflection
832
833 //Forward is the prefered direction, but if the reference frame has changed, we need to take this into account as well
834 if (m_angularDeflectionEfficiency != 0)
835 {
836 Vector3 preferredAxisOfMotion =
837 new Vector3((pTimestep * 10 * (m_angularDeflectionEfficiency / m_angularDeflectionTimescale)), 0, 0);
838 preferredAxisOfMotion *= Quaternion.Add(Prim.ForceOrientation, m_referenceFrame);
839
840 deflection = (preferredAxisOfMotion * (m_angularDeflectionEfficiency) / m_angularDeflectionTimescale) * pTimestep;
841
842 VDetailLog("{0},MoveAngular,Deflection,perfAxis={1},deflection={2}",
843 Prim.LocalID, preferredAxisOfMotion, deflection);
844 }
845
846 #endregion
847
848 #region Banking
849 929
850 if (m_bankingEfficiency != 0) 930 } // else vertical attractor is off
851 {
852 Vector3 dir = Vector3.One * Prim.ForceOrientation;
853 float mult = (m_bankingMix*m_bankingMix)*-1*(m_bankingMix < 0 ? -1 : 1);
854 //Changes which way it banks in and out of turns
855 931
856 //Use the square of the efficiency, as it looks much more how SL banking works 932 // m_lastVertAttractor = vertattr;
857 float effSquared = (m_bankingEfficiency*m_bankingEfficiency);
858 if (m_bankingEfficiency < 0)
859 effSquared *= -1; //Keep the negative!
860 933
861 float mix = Math.Abs(m_bankingMix); 934 // Bank section tba
862 if (m_angularMotorVelocity.X == 0)
863 {
864 /*if (!parent.Orientation.ApproxEquals(this.m_referenceFrame, 0.25f))
865 {
866 Vector3 axisAngle;
867 float angle;
868 parent.Orientation.GetAxisAngle(out axisAngle, out angle);
869 Vector3 rotatedVel = parent.Velocity * parent.Orientation;
870 if ((rotatedVel.X < 0 && axisAngle.Y > 0) || (rotatedVel.X > 0 && axisAngle.Y < 0))
871 m_angularMotorVelocity.X += (effSquared * (mult * mix)) * (1f) * 10;
872 else
873 m_angularMotorVelocity.X += (effSquared * (mult * mix)) * (-1f) * 10;
874 }*/
875 }
876 else
877 banking.Z += (effSquared*(mult*mix))*(m_angularMotorVelocity.X) * 4;
878 if (!Prim.Linkset.LinksetIsColliding && Math.Abs(m_angularMotorVelocity.X) > mix)
879 //If they are colliding, we probably shouldn't shove the prim around... probably
880 {
881 float angVelZ = m_angularMotorVelocity.X*-1;
882 /*if(angVelZ > mix)
883 angVelZ = mix;
884 else if(angVelZ < -mix)
885 angVelZ = -mix;*/
886 //This controls how fast and how far the banking occurs
887 Vector3 bankingRot = new Vector3(angVelZ*(effSquared*mult), 0, 0);
888 if (bankingRot.X > 3)
889 bankingRot.X = 3;
890 else if (bankingRot.X < -3)
891 bankingRot.X = -3;
892 bankingRot *= Prim.ForceOrientation;
893 banking += bankingRot;
894 }
895 m_angularMotorVelocity.X *= m_bankingEfficiency == 1 ? 0.0f : 1 - m_bankingEfficiency;
896 VDetailLog("{0},MoveAngular,Banking,bEff={1},angMotVel={2},banking={3}",
897 Prim.LocalID, m_bankingEfficiency, m_angularMotorVelocity, banking);
898 }
899
900 #endregion
901 935
902 m_lastVertAttractor = vertattr; 936 // Deflection section tba
903 937
904 // Sum velocities 938 // Sum velocities
905 m_lastAngularVelocity = m_angularMotorVelocity + vertattr + banking + deflection; 939 m_lastAngularVelocity = m_angularMotorVelocity + vertattr; // + bank + deflection
906 940
907 if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) 941 if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0)
908 { 942 {
909 m_lastAngularVelocity.X = 0; 943 m_lastAngularVelocity.X = 0;
910 m_lastAngularVelocity.Y = 0; 944 m_lastAngularVelocity.Y = 0;
911 VDetailLog("{0},MoveAngular,noDeflectionUp,lastAngular={1}", Prim.LocalID, m_lastAngularVelocity); 945 DetailLog("{0},MoveAngular,noDeflectionUp,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity);
912 } 946 }
913 947
914 if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f)) 948 if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f))
915 { 949 {
916 m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero. 950 m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero.
917 VDetailLog("{0},MoveAngular,zeroSmallValues,lastAngular={1}", Prim.LocalID, m_lastAngularVelocity); 951 DetailLog("{0},MoveAngular,zeroSmallValues,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity);
918 } 952 }
919 953
920 // Apply to the body 954 // apply friction
921 // The above calculates the absolute angular velocity needed 955 Vector3 decayamount = Vector3.One / (m_angularFrictionTimescale / pTimestep);
922 // Prim.ForceRotationalVelocity = m_lastAngularVelocity; 956 m_lastAngularVelocity -= m_lastAngularVelocity * decayamount;
923
924 // Apply a force to overcome current angular velocity
925 Vector3 applyAngularForce = (m_lastAngularVelocity - Prim.ForceRotationalVelocity) * Prim.Linkset.LinksetMass;
926 // Vector3 applyAngularForce = (m_lastAngularVelocity - Prim.ForceRotationalVelocity);
927 // Prim.AddAngularForce(applyAngularForce, false);
928 Prim.ApplyTorqueImpulse(applyAngularForce, false);
929 957
930 // Apply friction for next time 958 // Apply to the body
931 Vector3 decayamount = (Vector3.One / m_angularFrictionTimescale) * pTimestep; 959 m_prim.RotationalVelocity = m_lastAngularVelocity;
932 m_lastAngularVelocity *= Vector3.One - decayamount;
933 960
934 VDetailLog("{0},MoveAngular,done,applyAForce={1},decay={2},lastAngular={3}", 961 DetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", m_prim.LocalID, decayamount, m_lastAngularVelocity);
935 Prim.LocalID, applyAngularForce, decayamount, m_lastAngularVelocity);
936 } //end MoveAngular 962 } //end MoveAngular
937 963
938 internal void LimitRotation(float timestep) 964 internal void LimitRotation(float timestep)
939 { 965 {
940 Quaternion rotq = Prim.ForceOrientation; 966 Quaternion rotq = m_prim.Orientation;
941 Quaternion m_rot = rotq; 967 Quaternion m_rot = rotq;
968 bool changed = false;
942 if (m_RollreferenceFrame != Quaternion.Identity) 969 if (m_RollreferenceFrame != Quaternion.Identity)
943 { 970 {
944 if (rotq.X >= m_RollreferenceFrame.X) 971 if (rotq.X >= m_RollreferenceFrame.X)
945 { 972 {
946 m_rot.X = rotq.X - (m_RollreferenceFrame.X / 2); 973 m_rot.X = rotq.X - (m_RollreferenceFrame.X / 2);
974 changed = true;
947 } 975 }
948 if (rotq.Y >= m_RollreferenceFrame.Y) 976 if (rotq.Y >= m_RollreferenceFrame.Y)
949 { 977 {
950 m_rot.Y = rotq.Y - (m_RollreferenceFrame.Y / 2); 978 m_rot.Y = rotq.Y - (m_RollreferenceFrame.Y / 2);
979 changed = true;
951 } 980 }
952 if (rotq.X <= -m_RollreferenceFrame.X) 981 if (rotq.X <= -m_RollreferenceFrame.X)
953 { 982 {
954 m_rot.X = rotq.X + (m_RollreferenceFrame.X / 2); 983 m_rot.X = rotq.X + (m_RollreferenceFrame.X / 2);
984 changed = true;
955 } 985 }
956 if (rotq.Y <= -m_RollreferenceFrame.Y) 986 if (rotq.Y <= -m_RollreferenceFrame.Y)
957 { 987 {
958 m_rot.Y = rotq.Y + (m_RollreferenceFrame.Y / 2); 988 m_rot.Y = rotq.Y + (m_RollreferenceFrame.Y / 2);
989 changed = true;
959 } 990 }
991 changed = true;
960 } 992 }
961 if ((m_flags & VehicleFlag.LOCK_ROTATION) != 0) 993 if ((m_flags & VehicleFlag.LOCK_ROTATION) != 0)
962 { 994 {
963 m_rot.X = 0; 995 m_rot.X = 0;
964 m_rot.Y = 0; 996 m_rot.Y = 0;
997 changed = true;
965 } 998 }
966 if (rotq != m_rot) 999 if ((m_flags & VehicleFlag.LOCK_ROTATION) != 0)
967 { 1000 {
968 Prim.ForceOrientation = m_rot; 1001 m_rot.X = 0;
969 VDetailLog("{0},LimitRotation,done,orig={1},new={2}", Prim.LocalID, rotq, m_rot); 1002 m_rot.Y = 0;
1003 changed = true;
970 } 1004 }
1005 if (changed)
1006 m_prim.Orientation = m_rot;
971 1007
1008 DetailLog("{0},LimitRotation,done,changed={1},orig={2},new={3}", m_prim.LocalID, changed, rotq, m_rot);
972 } 1009 }
973 1010
974 // Invoke the detailed logger and output something if it's enabled. 1011 // Invoke the detailed logger and output something if it's enabled.
975 private void VDetailLog(string msg, params Object[] args) 1012 private void DetailLog(string msg, params Object[] args)
976 { 1013 {
977 if (Prim.PhysicsScene.VehicleLoggingEnabled) 1014 if (m_prim.Scene.VehicleLoggingEnabled)
978 Prim.PhysicsScene.DetailLog(msg, args); 1015 m_prim.Scene.PhysicsLogging.Write(msg, args);
979 } 1016 }
980 } 1017 }
981} 1018}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs b/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs
index ed3ffa7..d68048b 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs
@@ -1,57 +1,55 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright 7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD 9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the 12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products 13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission. 14 * derived from this software without specific prior written permission.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY 16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY 19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27using System; 27using System;
28using System.Collections.Generic; 28using System.Collections.Generic;
29using System.Text; 29using System.Text;
30using OpenMetaverse; 30using OpenMetaverse;
31 31
32namespace OpenSim.Region.Physics.BulletSPlugin 32namespace OpenSim.Region.Physics.BulletSPlugin
33{ 33{
34 34
35public sealed class BSConstraintHinge : BSConstraint 35class BSHingeConstraint : BSConstraint
36{ 36{
37 public override ConstraintType Type { get { return ConstraintType.HINGE_CONSTRAINT_TYPE; } } 37 public BSHingeConstraint(BulletSim world, BulletBody obj1, BulletBody obj2,
38 38 Vector3 pivotInA, Vector3 pivotInB,
39 public BSConstraintHinge(BulletSim world, BulletBody obj1, BulletBody obj2, 39 Vector3 axisInA, Vector3 axisInB,
40 Vector3 pivotInA, Vector3 pivotInB, 40 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
41 Vector3 axisInA, Vector3 axisInB, 41 {
42 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) 42 m_world = world;
43 { 43 m_body1 = obj1;
44 m_world = world; 44 m_body2 = obj2;
45 m_body1 = obj1; 45 m_constraint = new BulletConstraint(
46 m_body2 = obj2; 46 BulletSimAPI.CreateHingeConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr,
47 m_constraint = new BulletConstraint( 47 pivotInA, pivotInB,
48 BulletSimAPI.CreateHingeConstraint2(m_world.ptr, m_body1.ptr, m_body2.ptr, 48 axisInA, axisInB,
49 pivotInA, pivotInB, 49 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
50 axisInA, axisInB, 50 m_enabled = true;
51 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); 51 }
52 m_enabled = true; 52
53 } 53}
54 54
55} 55}
56
57}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
index 3a92f93..087b9bb 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -32,78 +32,35 @@ using OMV = OpenMetaverse;
32 32
33namespace OpenSim.Region.Physics.BulletSPlugin 33namespace OpenSim.Region.Physics.BulletSPlugin
34{ 34{
35public abstract class BSLinkset 35public class BSLinkset
36{ 36{
37 // private static string LogHeader = "[BULLETSIM LINKSET]"; 37 private static string LogHeader = "[BULLETSIM LINKSET]";
38 38
39 public enum LinksetImplementation 39 private BSPrim m_linksetRoot;
40 { 40 public BSPrim LinksetRoot { get { return m_linksetRoot; } }
41 Constraint = 0, // linkset tied together with constraints
42 Compound = 1, // linkset tied together as a compound object
43 Manual = 2 // linkset tied together manually (code moves all the pieces)
44 }
45 // Create the correct type of linkset for this child
46 public static BSLinkset Factory(BSScene physScene, BSPhysObject parent)
47 {
48 BSLinkset ret = null;
49
50 switch ((int)physScene.Params.linksetImplementation)
51 {
52 case (int)LinksetImplementation.Compound:
53 ret = new BSLinksetCompound(physScene, parent);
54 break;
55 case (int)LinksetImplementation.Manual:
56 // ret = new BSLinksetManual(physScene, parent);
57 break;
58 default:
59 ret = new BSLinksetConstraints(physScene, parent);
60 break;
61 }
62 return ret;
63 }
64
65 public BSPhysObject LinksetRoot { get; protected set; }
66 41
67 public BSScene PhysicsScene { get; private set; } 42 private BSScene m_physicsScene;
43 public BSScene PhysicsScene { get { return m_physicsScene; } }
68 44
69 static int m_nextLinksetID = 1; 45 // The children under the root in this linkset
70 public int LinksetID { get; private set; } 46 private List<BSPrim> m_children;
71
72 // The children under the root in this linkset.
73 protected HashSet<BSPhysObject> m_children;
74 47
75 // We lock the diddling of linkset classes to prevent any badness. 48 // We lock the diddling of linkset classes to prevent any badness.
76 // This locks the modification of the instances of this class. Changes 49 // This locks the modification of the instances of this class. Changes
77 // to the physical representation is done via the tainting mechenism. 50 // to the physical representation is done via the tainting mechenism.
78 protected object m_linksetActivityLock = new Object(); 51 private object m_linksetActivityLock = new Object();
79
80 // Some linksets have a preferred physical shape.
81 // Returns SHAPE_UNKNOWN if there is no preference. Causes the correct shape to be selected.
82 public virtual ShapeData.PhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor)
83 {
84 return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN;
85 }
86 52
87 // Linksets move around the children so the linkset might need to compute the child position
88 public virtual OMV.Vector3 Position(BSPhysObject member)
89 { return member.RawPosition; }
90 public virtual OMV.Quaternion Orientation(BSPhysObject member)
91 { return member.RawOrientation; }
92 // TODO: does this need to be done for Velocity and RotationalVelocityy?
93
94 // We keep the prim's mass in the linkset structure since it could be dependent on other prims 53 // We keep the prim's mass in the linkset structure since it could be dependent on other prims
95 protected float m_mass; 54 private float m_mass;
96 public float LinksetMass 55 public float LinksetMass
97 { 56 {
98 get 57 get
99 { 58 {
100 m_mass = ComputeLinksetMass(); 59 m_mass = ComputeLinksetMass();
101 return m_mass; 60 return m_mass;
102 } 61 }
103 } 62 }
104 63
105 public virtual bool LinksetIsColliding { get { return false; } }
106
107 public OMV.Vector3 CenterOfMass 64 public OMV.Vector3 CenterOfMass
108 { 65 {
109 get { return ComputeLinksetCenterOfMass(); } 66 get { return ComputeLinksetCenterOfMass(); }
@@ -114,30 +71,23 @@ public abstract class BSLinkset
114 get { return ComputeLinksetGeometricCenter(); } 71 get { return ComputeLinksetGeometricCenter(); }
115 } 72 }
116 73
117 protected void Initialize(BSScene scene, BSPhysObject parent) 74 public BSLinkset(BSScene scene, BSPrim parent)
118 { 75 {
119 // A simple linkset of one (no children) 76 // A simple linkset of one (no children)
120 LinksetID = m_nextLinksetID++; 77 m_physicsScene = scene;
121 // We create LOTS of linksets. 78 m_linksetRoot = parent;
122 if (m_nextLinksetID <= 0) 79 m_children = new List<BSPrim>();
123 m_nextLinksetID = 1; 80 m_mass = parent.MassRaw;
124 PhysicsScene = scene;
125 LinksetRoot = parent;
126 m_children = new HashSet<BSPhysObject>();
127 m_mass = parent.RawMass;
128 } 81 }
129 82
130 // Link to a linkset where the child knows the parent. 83 // Link to a linkset where the child knows the parent.
131 // Parent changing should not happen so do some sanity checking. 84 // Parent changing should not happen so do some sanity checking.
132 // We return the parent's linkset so the child can track its membership. 85 // We return the parent's linkset so the child can track its membership.
133 // Called at runtime. 86 public BSLinkset AddMeToLinkset(BSPrim child)
134 public BSLinkset AddMeToLinkset(BSPhysObject child)
135 { 87 {
136 lock (m_linksetActivityLock) 88 lock (m_linksetActivityLock)
137 { 89 {
138 // Don't add the root to its own linkset 90 AddChildToLinkset(child);
139 if (!IsRoot(child))
140 AddChildToLinkset(child);
141 } 91 }
142 return this; 92 return this;
143 } 93 }
@@ -145,27 +95,36 @@ public abstract class BSLinkset
145 // Remove a child from a linkset. 95 // Remove a child from a linkset.
146 // Returns a new linkset for the child which is a linkset of one (just the 96 // Returns a new linkset for the child which is a linkset of one (just the
147 // orphened child). 97 // orphened child).
148 // Called at runtime. 98 public BSLinkset RemoveMeFromLinkset(BSPrim child)
149 public BSLinkset RemoveMeFromLinkset(BSPhysObject child)
150 { 99 {
151 lock (m_linksetActivityLock) 100 lock (m_linksetActivityLock)
152 { 101 {
153 if (IsRoot(child)) 102 if (IsRoot(child))
154 { 103 {
155 // Cannot remove the root from a linkset. 104 // if root of linkset, take the linkset apart
156 return this; 105 while (m_children.Count > 0)
106 {
107 // Note that we don't do a foreach because the remove routine
108 // takes it out of the list.
109 RemoveChildFromOtherLinkset(m_children[0]);
110 }
111 m_children.Clear(); // just to make sure
112 }
113 else
114 {
115 // Just removing a child from an existing linkset
116 RemoveChildFromLinkset(child);
157 } 117 }
158 RemoveChildFromLinkset(child);
159 } 118 }
160 119
161 // The child is down to a linkset of just itself 120 // The child is down to a linkset of just itself
162 return BSLinkset.Factory(PhysicsScene, child); 121 return new BSLinkset(PhysicsScene, child);
163 } 122 }
164 123
165 // Return 'true' if the passed object is the root object of this linkset 124 // Return 'true' if the passed object is the root object of this linkset
166 public bool IsRoot(BSPhysObject requestor) 125 public bool IsRoot(BSPrim requestor)
167 { 126 {
168 return (requestor.LocalID == LinksetRoot.LocalID); 127 return (requestor.LocalID == m_linksetRoot.LocalID);
169 } 128 }
170 129
171 public int NumberOfChildren { get { return m_children.Count; } } 130 public int NumberOfChildren { get { return m_children.Count; } }
@@ -174,14 +133,12 @@ public abstract class BSLinkset
174 public bool HasAnyChildren { get { return (m_children.Count > 0); } } 133 public bool HasAnyChildren { get { return (m_children.Count > 0); } }
175 134
176 // Return 'true' if this child is in this linkset 135 // Return 'true' if this child is in this linkset
177 public bool HasChild(BSPhysObject child) 136 public bool HasChild(BSPrim child)
178 { 137 {
179 bool ret = false; 138 bool ret = false;
180 lock (m_linksetActivityLock) 139 lock (m_linksetActivityLock)
181 { 140 {
182 ret = m_children.Contains(child); 141 foreach (BSPrim bp in m_children)
183 /* Safer version but the above should work
184 foreach (BSPhysObject bp in m_children)
185 { 142 {
186 if (child.LocalID == bp.LocalID) 143 if (child.LocalID == bp.LocalID)
187 { 144 {
@@ -189,132 +146,274 @@ public abstract class BSLinkset
189 break; 146 break;
190 } 147 }
191 } 148 }
192 */
193 } 149 }
194 return ret; 150 return ret;
195 } 151 }
196 152
197 // Perform an action on each member of the linkset including root prim. 153 private float ComputeLinksetMass()
198 // Depends on the action on whether this should be done at taint time.
199 public delegate bool ForEachMemberAction(BSPhysObject obj);
200 public virtual bool ForEachMember(ForEachMemberAction action)
201 { 154 {
202 bool ret = false; 155 float mass = m_linksetRoot.MassRaw;
156 foreach (BSPrim bp in m_children)
157 {
158 mass += bp.MassRaw;
159 }
160 return mass;
161 }
162
163 private OMV.Vector3 ComputeLinksetCenterOfMass()
164 {
165 OMV.Vector3 com = m_linksetRoot.Position * m_linksetRoot.MassRaw;
166 float totalMass = m_linksetRoot.MassRaw;
167
203 lock (m_linksetActivityLock) 168 lock (m_linksetActivityLock)
204 { 169 {
205 action(LinksetRoot); 170 foreach (BSPrim bp in m_children)
206 foreach (BSPhysObject po in m_children)
207 { 171 {
208 if (action(po)) 172 com += bp.Position * bp.MassRaw;
209 break; 173 totalMass += bp.MassRaw;
210 } 174 }
175 if (totalMass != 0f)
176 com /= totalMass;
211 } 177 }
212 return ret; 178
179 return com;
213 } 180 }
214 181
215 // I am the root of a linkset and a new child is being added 182 private OMV.Vector3 ComputeLinksetGeometricCenter()
216 // Called while LinkActivity is locked. 183 {
217 protected abstract void AddChildToLinkset(BSPhysObject child); 184 OMV.Vector3 com = m_linksetRoot.Position;
218 185
219 // I am the root of a linkset and one of my children is being removed. 186 lock (m_linksetActivityLock)
220 // Safe to call even if the child is not really in my linkset. 187 {
221 protected abstract void RemoveChildFromLinkset(BSPhysObject child); 188 foreach (BSPrim bp in m_children)
189 {
190 com += bp.Position * bp.MassRaw;
191 }
192 com /= (m_children.Count + 1);
193 }
194
195 return com;
196 }
222 197
223 // When physical properties are changed the linkset needs to recalculate 198 // When physical properties are changed the linkset needs to recalculate
224 // its internal properties. 199 // its internal properties.
225 // May be called at runtime or taint-time. 200 public void Refresh(BSPrim requestor)
226 public abstract void Refresh(BSPhysObject requestor);
227
228 // The object is going dynamic (physical). Do any setup necessary
229 // for a dynamic linkset.
230 // Only the state of the passed object can be modified. The rest of the linkset
231 // has not yet been fully constructed.
232 // Return 'true' if any properties updated on the passed object.
233 // Called at taint-time!
234 public abstract bool MakeDynamic(BSPhysObject child);
235
236 // The object is going static (non-physical). Do any setup necessary
237 // for a static linkset.
238 // Return 'true' if any properties updated on the passed object.
239 // Called at taint-time!
240 public abstract bool MakeStatic(BSPhysObject child);
241
242 // Called when a parameter update comes from the physics engine for any object
243 // of the linkset is received.
244 // Called at taint-time!!
245 public abstract void UpdateProperties(BSPhysObject physObject);
246
247 // Routine used when rebuilding the body of the root of the linkset
248 // Destroy all the constraints have have been made to root.
249 // This is called when the root body is changing.
250 // Returns 'true' of something was actually removed and would need restoring
251 // Called at taint-time!!
252 public abstract bool RemoveBodyDependencies(BSPrim child);
253
254 // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true',
255 // this routine will restore the removed constraints.
256 // Called at taint-time!!
257 public abstract void RestoreBodyDependencies(BSPrim child);
258
259 // ================================================================
260 protected virtual float ComputeLinksetMass()
261 { 201 {
262 float mass = LinksetRoot.RawMass; 202 // If there are no children, there aren't any constraints to recompute
263 if (HasAnyChildren) 203 if (!HasAnyChildren)
204 return;
205
206 // Only the root does the recomputation
207 if (IsRoot(requestor))
208 {
209 PhysicsScene.TaintedObject("BSLinkSet.Refresh", delegate()
210 {
211 RecomputeLinksetConstraintVariables();
212 });
213 }
214 }
215
216 // Call each of the constraints that make up this linkset and recompute the
217 // various transforms and variables. Used when objects are added or removed
218 // from a linkset to make sure the constraints know about the new mass and
219 // geometry.
220 // Must only be called at taint time!!
221 private bool RecomputeLinksetConstraintVariables()
222 {
223 float linksetMass = LinksetMass;
224 lock (m_linksetActivityLock)
264 { 225 {
265 lock (m_linksetActivityLock) 226 foreach (BSPrim child in m_children)
266 { 227 {
267 foreach (BSPhysObject bp in m_children) 228 BSConstraint constrain;
229 if (m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.Body, child.Body, out constrain))
230 {
231 // DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}",
232 // LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID);
233 constrain.RecomputeConstraintVariables(linksetMass);
234 }
235 else
268 { 236 {
269 mass += bp.RawMass; 237 // Non-fatal error that can happen when children are being added to the linkset but
238 // their constraints have not been created yet.
239 // Caused by the fact that m_children is built at run time but building constraints
240 // happens at taint time.
241 // m_physicsScene.Logger.ErrorFormat("[BULLETSIM LINKSET] RecomputeLinksetConstraintVariables: constraint not found for root={0}, child={1}",
242 // m_linksetRoot.Body.ID, child.Body.ID);
270 } 243 }
271 } 244 }
272 } 245 }
273 return mass; 246 return false;
274 } 247 }
275 248
276 protected virtual OMV.Vector3 ComputeLinksetCenterOfMass() 249 // I am the root of a linkset and a new child is being added
250 // Called while LinkActivity is locked.
251 private void AddChildToLinkset(BSPrim child)
277 { 252 {
278 OMV.Vector3 com; 253 if (!HasChild(child))
279 lock (m_linksetActivityLock)
280 { 254 {
281 com = LinksetRoot.Position * LinksetRoot.RawMass; 255 m_children.Add(child);
282 float totalMass = LinksetRoot.RawMass;
283 256
284 foreach (BSPhysObject bp in m_children) 257 BSPrim rootx = LinksetRoot; // capture the root as of now
258 BSPrim childx = child;
259 m_physicsScene.TaintedObject("AddChildToLinkset", delegate()
285 { 260 {
286 com += bp.Position * bp.RawMass; 261 // DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, m_linksetRoot.LocalID);
287 totalMass += bp.RawMass; 262 // DetailLog("{0},AddChildToLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
288 } 263 PhysicallyLinkAChildToRoot(rootx, childx); // build the physical binding between me and the child
289 if (totalMass != 0f) 264 });
290 com /= totalMass;
291 } 265 }
266 return;
267 }
292 268
293 return com; 269 // Forcefully removing a child from a linkset.
270 // This is not being called by the child so we have to make sure the child doesn't think
271 // it's still connected to the linkset.
272 // Normal OpenSimulator operation will never do this because other SceneObjectPart information
273 // has to be updated also (like pointer to prim's parent).
274 private void RemoveChildFromOtherLinkset(BSPrim pchild)
275 {
276 pchild.Linkset = new BSLinkset(m_physicsScene, pchild);
277 RemoveChildFromLinkset(pchild);
294 } 278 }
295 279
296 protected virtual OMV.Vector3 ComputeLinksetGeometricCenter() 280 // I am the root of a linkset and one of my children is being removed.
281 // Safe to call even if the child is not really in my linkset.
282 private void RemoveChildFromLinkset(BSPrim child)
297 { 283 {
298 OMV.Vector3 com; 284 if (m_children.Remove(child))
299 lock (m_linksetActivityLock)
300 { 285 {
301 com = LinksetRoot.Position; 286 BSPrim rootx = LinksetRoot; // capture the root as of now
302 287 BSPrim childx = child;
303 foreach (BSPhysObject bp in m_children) 288 m_physicsScene.TaintedObject("RemoveChildFromLinkset", delegate()
304 { 289 {
305 com += bp.Position * bp.RawMass; 290 // DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID);
306 } 291 // DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
307 com /= (m_children.Count + 1); 292
293 PhysicallyUnlinkAChildFromRoot(rootx, childx);
294 });
295
296 RecomputeLinksetConstraintVariables();
297 }
298 else
299 {
300 // This will happen if we remove the root of the linkset first. Non-fatal occurance.
301 // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader);
308 } 302 }
303 return;
304 }
309 305
310 return com; 306 // Create a constraint between me (root of linkset) and the passed prim (the child).
307 // Called at taint time!
308 private void PhysicallyLinkAChildToRoot(BSPrim rootPrim, BSPrim childPrim)
309 {
310 // Zero motion for children so they don't interpolate
311 childPrim.ZeroMotion();
312
313 // Relative position normalized to the root prim
314 // Essentually a vector pointing from center of rootPrim to center of childPrim
315 OMV.Vector3 childRelativePosition = childPrim.Position - rootPrim.Position;
316
317 // real world coordinate of midpoint between the two objects
318 OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2);
319
320 // create a constraint that allows no freedom of movement between the two objects
321 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
322 // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID);
323 DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2},rLoc={3},cLoc={4},midLoc={5}",
324 rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID, rootPrim.Position, childPrim.Position, midPoint);
325 BS6DofConstraint constrain = new BS6DofConstraint(
326 m_physicsScene.World, rootPrim.Body, childPrim.Body,
327 midPoint,
328 true,
329 true
330 );
331 /* NOTE: attempt to build constraint with full frame computation, etc.
332 * Using the midpoint is easier since it lets the Bullet code use the transforms
333 * of the objects.
334 * Code left here as an example.
335 // ==================================================================================
336 // relative position normalized to the root prim
337 OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation);
338 OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation;
339
340 // relative rotation of the child to the parent
341 OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation;
342 OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation);
343
344 // create a constraint that allows no freedom of movement between the two objects
345 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
346 // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID);
347 DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
348 BS6DofConstraint constrain = new BS6DofConstraint(
349 PhysicsScene.World, rootPrim.Body, childPrim.Body,
350 OMV.Vector3.Zero,
351 OMV.Quaternion.Inverse(rootPrim.Orientation),
352 OMV.Vector3.Zero,
353 OMV.Quaternion.Inverse(childPrim.Orientation),
354 // A point half way between the parent and child
355 // childRelativePosition/2,
356 // childRelativeRotation,
357 // childRelativePosition/2,
358 // inverseChildRelativeRotation,
359 true,
360 true
361 );
362 // ==================================================================================
363 */
364
365 m_physicsScene.Constraints.AddConstraint(constrain);
366
367 // zero linear and angular limits makes the objects unable to move in relation to each other
368 constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
369 constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
370
371 // tweek the constraint to increase stability
372 constrain.UseFrameOffset(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintUseFrameOffset));
373 constrain.TranslationalLimitMotor(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintEnableTransMotor),
374 PhysicsScene.Params.linkConstraintTransMotorMaxVel,
375 PhysicsScene.Params.linkConstraintTransMotorMaxForce);
376 constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP);
377
378 RecomputeLinksetConstraintVariables();
379 }
380
381 // Remove linkage between myself and a particular child
382 // Called at taint time!
383 private void PhysicallyUnlinkAChildFromRoot(BSPrim rootPrim, BSPrim childPrim)
384 {
385 // DebugLog("{0}: PhysicallyUnlinkAChildFromRoot: RemoveConstraint between root prim {1} and child prim {2}",
386 // LogHeader, rootPrim.LocalID, childPrim.LocalID);
387 DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
388
389 // Find the constraint for this link and get rid of it from the overall collection and from my list
390 m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body, childPrim.Body);
391
392 // Make the child refresh its location
393 BulletSimAPI.PushUpdate2(childPrim.Body.Ptr);
394 }
395
396 // Remove linkage between myself and any possible children I might have
397 // Called at taint time!
398 private void PhysicallyUnlinkAllChildrenFromRoot(BSPrim rootPrim)
399 {
400 // DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader);
401 DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID);
402
403 m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body);
404 }
405
406 // Invoke the detailed logger and output something if it's enabled.
407 private void DebugLog(string msg, params Object[] args)
408 {
409 if (m_physicsScene.ShouldDebugLog)
410 m_physicsScene.Logger.DebugFormat(msg, args);
311 } 411 }
312 412
313 // Invoke the detailed logger and output something if it's enabled. 413 // Invoke the detailed logger and output something if it's enabled.
314 protected void DetailLog(string msg, params Object[] args) 414 private void DetailLog(string msg, params Object[] args)
315 { 415 {
316 if (PhysicsScene.PhysicsLogging.Enabled) 416 m_physicsScene.PhysicsLogging.Write(msg, args);
317 PhysicsScene.DetailLog(msg, args);
318 } 417 }
319 418
320} 419}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
deleted file mode 100755
index 12c6d7a..0000000
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
+++ /dev/null
@@ -1,273 +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 copyrightD
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 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30
31using OMV = OpenMetaverse;
32
33namespace OpenSim.Region.Physics.BulletSPlugin
34{
35public sealed class BSLinksetCompound : BSLinkset
36{
37 private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]";
38
39 public BSLinksetCompound(BSScene scene, BSPhysObject parent)
40 {
41 base.Initialize(scene, parent);
42 }
43
44 // For compound implimented linksets, if there are children, use compound shape for the root.
45 public override ShapeData.PhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor)
46 {
47 ShapeData.PhysicsShapeType ret = ShapeData.PhysicsShapeType.SHAPE_UNKNOWN;
48 if (IsRoot(requestor) && HasAnyChildren)
49 {
50 ret = ShapeData.PhysicsShapeType.SHAPE_COMPOUND;
51 }
52 // DetailLog("{0},BSLinksetCompound.PreferredPhysicalShape,call,shape={1}", LinksetRoot.LocalID, ret);
53 return ret;
54 }
55
56 // When physical properties are changed the linkset needs to recalculate
57 // its internal properties.
58 // This is queued in the 'post taint' queue so the
59 // refresh will happen once after all the other taints are applied.
60 public override void Refresh(BSPhysObject requestor)
61 {
62 // External request for Refresh (from BSPrim) is not necessary
63 // InternalRefresh(requestor);
64 }
65
66 private void InternalRefresh(BSPhysObject requestor)
67 {
68 DetailLog("{0},BSLinksetCompound.Refresh,schedulingRefresh,requestor={1}", LinksetRoot.LocalID, requestor.LocalID);
69 // Queue to happen after all the other taint processing
70 PhysicsScene.PostTaintObject("BSLinksetCompound.Refresh", requestor.LocalID, delegate()
71 {
72 if (IsRoot(requestor) && HasAnyChildren)
73 RecomputeLinksetCompound();
74 });
75 }
76
77 // The object is going dynamic (physical). Do any setup necessary
78 // for a dynamic linkset.
79 // Only the state of the passed object can be modified. The rest of the linkset
80 // has not yet been fully constructed.
81 // Return 'true' if any properties updated on the passed object.
82 // Called at taint-time!
83 public override bool MakeDynamic(BSPhysObject child)
84 {
85 bool ret = false;
86 DetailLog("{0},BSLinksetCompound.MakeDynamic,call,IsRoot={1}", child.LocalID, IsRoot(child));
87 if (!IsRoot(child))
88 {
89 // Physical children are removed from the world as the shape ofthe root compound
90 // shape takes over.
91 BulletSimAPI.AddToCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
92 BulletSimAPI.ForceActivationState2(child.PhysBody.ptr, ActivationState.DISABLE_SIMULATION);
93 ret = true;
94 }
95 return ret;
96 }
97
98 // The object is going static (non-physical). Do any setup necessary for a static linkset.
99 // Return 'true' if any properties updated on the passed object.
100 // This doesn't normally happen -- OpenSim removes the objects from the physical
101 // world if it is a static linkset.
102 // Called at taint-time!
103 public override bool MakeStatic(BSPhysObject child)
104 {
105 bool ret = false;
106 DetailLog("{0},BSLinksetCompound.MakeStatic,call,IsRoot={1}", child.LocalID, IsRoot(child));
107 if (!IsRoot(child))
108 {
109 // The non-physical children can come back to life.
110 BulletSimAPI.RemoveFromCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
111 // Don't force activation so setting of DISABLE_SIMULATION can stay.
112 BulletSimAPI.Activate2(child.PhysBody.ptr, false);
113 ret = true;
114 }
115 return ret;
116 }
117
118 // Called at taint-time!!
119 public override void UpdateProperties(BSPhysObject updated)
120 {
121 // Nothing to do for constraints on property updates
122 }
123
124 // The children move around in relationship to the root.
125 // Just grab the current values of wherever it is right now.
126 public override OMV.Vector3 Position(BSPhysObject member)
127 {
128 return BulletSimAPI.GetPosition2(member.PhysBody.ptr);
129 }
130
131 public override OMV.Quaternion Orientation(BSPhysObject member)
132 {
133 return BulletSimAPI.GetOrientation2(member.PhysBody.ptr);
134 }
135
136 // Routine called when rebuilding the body of some member of the linkset.
137 // Since we don't keep in world relationships, do nothing unless it's a child changing.
138 // Returns 'true' of something was actually removed and would need restoring
139 // Called at taint-time!!
140 public override bool RemoveBodyDependencies(BSPrim child)
141 {
142 bool ret = false;
143
144 DetailLog("{0},BSLinksetCompound.RemoveBodyDependencies,refreshIfChild,rID={1},rBody={2},isRoot={3}",
145 child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), IsRoot(child));
146
147 if (!IsRoot(child))
148 {
149 // Cause the current shape to be freed and the new one to be built.
150 InternalRefresh(LinksetRoot);
151 ret = true;
152 }
153
154 return ret;
155 }
156
157 // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true',
158 // this routine will restore the removed constraints.
159 // Called at taint-time!!
160 public override void RestoreBodyDependencies(BSPrim child)
161 {
162 // The Refresh operation queued by RemoveBodyDependencies() will build any missing constraints.
163 }
164
165 // ================================================================
166
167 // Add a new child to the linkset.
168 // Called while LinkActivity is locked.
169 protected override void AddChildToLinkset(BSPhysObject child)
170 {
171 if (!HasChild(child))
172 {
173 m_children.Add(child);
174
175 DetailLog("{0},BSLinksetCompound.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID);
176
177 // Cause constraints and assorted properties to be recomputed before the next simulation step.
178 InternalRefresh(LinksetRoot);
179 }
180 return;
181 }
182
183 // Remove the specified child from the linkset.
184 // Safe to call even if the child is not really in my linkset.
185 protected override void RemoveChildFromLinkset(BSPhysObject child)
186 {
187 if (m_children.Remove(child))
188 {
189 DetailLog("{0},BSLinksetCompound.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}",
190 child.LocalID,
191 LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"),
192 child.LocalID, child.PhysBody.ptr.ToString("X"));
193
194 // Cause the child's body to be rebuilt and thus restored to normal operation
195 child.ForceBodyShapeRebuild(false);
196
197 if (!HasAnyChildren)
198 {
199 // The linkset is now empty. The root needs rebuilding.
200 LinksetRoot.ForceBodyShapeRebuild(false);
201 }
202 else
203 {
204 // Schedule a rebuild of the linkset before the next simulation tick.
205 InternalRefresh(LinksetRoot);
206 }
207 }
208 return;
209 }
210
211 // Called before the simulation step to make sure the compound based linkset
212 // is all initialized.
213 // Constraint linksets are rebuilt every time.
214 // Note that this works for rebuilding just the root after a linkset is taken apart.
215 // Called at taint time!!
216 private void RecomputeLinksetCompound()
217 {
218 // Cause the root shape to be rebuilt as a compound object with just the root in it
219 LinksetRoot.ForceBodyShapeRebuild(true);
220
221 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}",
222 LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren);
223
224 // Add a shape for each of the other children in the linkset
225 ForEachMember(delegate(BSPhysObject cPrim)
226 {
227 if (!IsRoot(cPrim))
228 {
229 // Each child position and rotation is given relative to the root.
230 OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation);
231 OMV.Vector3 displacementPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation;
232 OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation;
233
234 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},dispPos={3},dispRot={4}",
235 LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, displacementPos, displacementRot);
236
237 if (cPrim.PhysShape.isNativeShape)
238 {
239 // Native shapes are not shared so we need to create a new one.
240 // A mesh or hull is created because scale is not available on a native shape.
241 // (TODO: Bullet does have a btScaledCollisionShape. Can that be used?)
242 BulletShape saveShape = cPrim.PhysShape;
243 cPrim.PhysShape.ptr = IntPtr.Zero; // Don't let the create free the child's shape
244 PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null);
245 BulletShape newShape = cPrim.PhysShape;
246 cPrim.PhysShape = saveShape;
247 BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, newShape.ptr, displacementPos, displacementRot);
248 }
249 else
250 {
251 // For the shared shapes (meshes and hulls), just use the shape in the child.
252 if (PhysicsScene.Shapes.ReferenceShape(cPrim.PhysShape))
253 {
254 PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}",
255 LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape);
256 }
257 BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, cPrim.PhysShape.ptr, displacementPos, displacementRot);
258 }
259 }
260 return false; // 'false' says to move onto the next child in the list
261 });
262
263 // With all of the linkset packed into the root prim, it has the mass of everyone.
264 float linksetMass = LinksetMass;
265 LinksetRoot.UpdatePhysicalMassProperties(linksetMass);
266
267 // DEBUG: see of inter-linkset collisions are causing problems for constraint linksets.
268 // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr,
269 // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask);
270
271 }
272}
273} \ No newline at end of file
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
deleted file mode 100755
index d2387fb..0000000
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
+++ /dev/null
@@ -1,327 +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 copyrightD
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 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30
31using OMV = OpenMetaverse;
32
33namespace OpenSim.Region.Physics.BulletSPlugin
34{
35public sealed class BSLinksetConstraints : BSLinkset
36{
37 // private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]";
38
39 public BSLinksetConstraints(BSScene scene, BSPhysObject parent)
40 {
41 base.Initialize(scene, parent);
42 }
43
44 // When physical properties are changed the linkset needs to recalculate
45 // its internal properties.
46 // This is queued in the 'post taint' queue so the
47 // refresh will happen once after all the other taints are applied.
48 public override void Refresh(BSPhysObject requestor)
49 {
50 // Queue to happen after all the other taint processing
51 PhysicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate()
52 {
53 if (HasAnyChildren && IsRoot(requestor))
54 RecomputeLinksetConstraints();
55 });
56 }
57
58 // The object is going dynamic (physical). Do any setup necessary
59 // for a dynamic linkset.
60 // Only the state of the passed object can be modified. The rest of the linkset
61 // has not yet been fully constructed.
62 // Return 'true' if any properties updated on the passed object.
63 // Called at taint-time!
64 public override bool MakeDynamic(BSPhysObject child)
65 {
66 // What is done for each object in BSPrim is what we want.
67 return false;
68 }
69
70 // The object is going static (non-physical). Do any setup necessary for a static linkset.
71 // Return 'true' if any properties updated on the passed object.
72 // This doesn't normally happen -- OpenSim removes the objects from the physical
73 // world if it is a static linkset.
74 // Called at taint-time!
75 public override bool MakeStatic(BSPhysObject child)
76 {
77 // What is done for each object in BSPrim is what we want.
78 return false;
79 }
80
81 // Called at taint-time!!
82 public override void UpdateProperties(BSPhysObject updated)
83 {
84 // Nothing to do for constraints on property updates
85 }
86
87 // The children of the linkset are moved around by the constraints.
88 // Just grab the current values of wherever it is right now.
89 public override OMV.Vector3 Position(BSPhysObject member)
90 {
91 return BulletSimAPI.GetPosition2(member.PhysBody.ptr);
92 }
93
94 public override OMV.Quaternion Orientation(BSPhysObject member)
95 {
96 return BulletSimAPI.GetOrientation2(member.PhysBody.ptr);
97 }
98
99 // Routine called when rebuilding the body of some member of the linkset.
100 // Destroy all the constraints have have been made to root and set
101 // up to rebuild the constraints before the next simulation step.
102 // Returns 'true' of something was actually removed and would need restoring
103 // Called at taint-time!!
104 public override bool RemoveBodyDependencies(BSPrim child)
105 {
106 bool ret = false;
107
108 DetailLog("{0},BSLinksetConstraint.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}",
109 child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"));
110
111 lock (m_linksetActivityLock)
112 {
113 // Just undo all the constraints for this linkset. Rebuild at the end of the step.
114 ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot);
115 // Cause the constraints, et al to be rebuilt before the next simulation step.
116 Refresh(LinksetRoot);
117 }
118 return ret;
119 }
120
121 // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true',
122 // this routine will restore the removed constraints.
123 // Called at taint-time!!
124 public override void RestoreBodyDependencies(BSPrim child)
125 {
126 // The Refresh operation queued by RemoveBodyDependencies() will build any missing constraints.
127 }
128
129 // ================================================================
130
131 // Add a new child to the linkset.
132 // Called while LinkActivity is locked.
133 protected override void AddChildToLinkset(BSPhysObject child)
134 {
135 if (!HasChild(child))
136 {
137 m_children.Add(child);
138
139 DetailLog("{0},BSLinksetConstraints.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID);
140
141 // Cause constraints and assorted properties to be recomputed before the next simulation step.
142 Refresh(LinksetRoot);
143 }
144 return;
145 }
146
147 // Remove the specified child from the linkset.
148 // Safe to call even if the child is not really in my linkset.
149 protected override void RemoveChildFromLinkset(BSPhysObject child)
150 {
151 if (m_children.Remove(child))
152 {
153 BSPhysObject rootx = LinksetRoot; // capture the root and body as of now
154 BSPhysObject childx = child;
155
156 DetailLog("{0},BSLinksetConstraints.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}",
157 childx.LocalID,
158 rootx.LocalID, rootx.PhysBody.ptr.ToString("X"),
159 childx.LocalID, childx.PhysBody.ptr.ToString("X"));
160
161 PhysicsScene.TaintedObject("BSLinksetConstraints.RemoveChildFromLinkset", delegate()
162 {
163 PhysicallyUnlinkAChildFromRoot(rootx, childx);
164 });
165 // See that the linkset parameters are recomputed at the end of the taint time.
166 Refresh(LinksetRoot);
167 }
168 else
169 {
170 // Non-fatal occurance.
171 // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader);
172 }
173 return;
174 }
175
176 // Create a constraint between me (root of linkset) and the passed prim (the child).
177 // Called at taint time!
178 private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BSPhysObject childPrim)
179 {
180 // Don't build the constraint when asked. Put it off until just before the simulation step.
181 Refresh(rootPrim);
182 }
183
184 private BSConstraint BuildConstraint(BSPhysObject rootPrim, BSPhysObject childPrim)
185 {
186 // Zero motion for children so they don't interpolate
187 childPrim.ZeroMotion();
188
189 // Relative position normalized to the root prim
190 // Essentually a vector pointing from center of rootPrim to center of childPrim
191 OMV.Vector3 childRelativePosition = childPrim.Position - rootPrim.Position;
192
193 // real world coordinate of midpoint between the two objects
194 OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2);
195
196 DetailLog("{0},BSLinksetConstraint.BuildConstraint,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}",
197 rootPrim.LocalID,
198 rootPrim.LocalID, rootPrim.PhysBody.ptr.ToString("X"),
199 childPrim.LocalID, childPrim.PhysBody.ptr.ToString("X"),
200 rootPrim.Position, childPrim.Position, midPoint);
201
202 // create a constraint that allows no freedom of movement between the two objects
203 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
204
205 BSConstraint6Dof constrain = new BSConstraint6Dof(
206 PhysicsScene.World, rootPrim.PhysBody, childPrim.PhysBody, midPoint, true, true );
207 // PhysicsScene.World, childPrim.BSBody, rootPrim.BSBody, midPoint, true, true );
208
209 /* NOTE: below is an attempt to build constraint with full frame computation, etc.
210 * Using the midpoint is easier since it lets the Bullet code manipulate the transforms
211 * of the objects.
212 * Code left for future programmers.
213 // ==================================================================================
214 // relative position normalized to the root prim
215 OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation);
216 OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation;
217
218 // relative rotation of the child to the parent
219 OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation;
220 OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation);
221
222 DetailLog("{0},BSLinksetConstraint.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
223 BS6DofConstraint constrain = new BS6DofConstraint(
224 PhysicsScene.World, rootPrim.Body, childPrim.Body,
225 OMV.Vector3.Zero,
226 OMV.Quaternion.Inverse(rootPrim.Orientation),
227 OMV.Vector3.Zero,
228 OMV.Quaternion.Inverse(childPrim.Orientation),
229 true,
230 true
231 );
232 // ==================================================================================
233 */
234
235 PhysicsScene.Constraints.AddConstraint(constrain);
236
237 // zero linear and angular limits makes the objects unable to move in relation to each other
238 constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
239 constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
240
241 // tweek the constraint to increase stability
242 constrain.UseFrameOffset(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintUseFrameOffset));
243 constrain.TranslationalLimitMotor(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintEnableTransMotor),
244 PhysicsScene.Params.linkConstraintTransMotorMaxVel,
245 PhysicsScene.Params.linkConstraintTransMotorMaxForce);
246 constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP);
247 if (PhysicsScene.Params.linkConstraintSolverIterations != 0f)
248 {
249 constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations);
250 }
251 return constrain;
252 }
253
254 // Remove linkage between the linkset root and a particular child
255 // The root and child bodies are passed in because we need to remove the constraint between
256 // the bodies that were present at unlink time.
257 // Called at taint time!
258 private bool PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BSPhysObject childPrim)
259 {
260 bool ret = false;
261 DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}",
262 rootPrim.LocalID,
263 rootPrim.LocalID, rootPrim.PhysBody.ptr.ToString("X"),
264 childPrim.LocalID, childPrim.PhysBody.ptr.ToString("X"));
265
266 // Find the constraint for this link and get rid of it from the overall collection and from my list
267 if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody, childPrim.PhysBody))
268 {
269 // Make the child refresh its location
270 BulletSimAPI.PushUpdate2(childPrim.PhysBody.ptr);
271 ret = true;
272 }
273
274 return ret;
275 }
276
277 // Remove linkage between myself and any possible children I might have.
278 // Returns 'true' of any constraints were destroyed.
279 // Called at taint time!
280 private bool PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim)
281 {
282 DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID);
283
284 return PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody);
285 }
286
287 // Call each of the constraints that make up this linkset and recompute the
288 // various transforms and variables. Create constraints of not created yet.
289 // Called before the simulation step to make sure the constraint based linkset
290 // is all initialized.
291 // Called at taint time!!
292 private void RecomputeLinksetConstraints()
293 {
294 float linksetMass = LinksetMass;
295 LinksetRoot.UpdatePhysicalMassProperties(linksetMass);
296
297 // DEBUG: see of inter-linkset collisions are causing problems
298 // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr,
299 // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask);
300 DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraints,set,rBody={1},linksetMass={2}",
301 LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), linksetMass);
302
303 foreach (BSPhysObject child in m_children)
304 {
305 // A child in the linkset physically shows the mass of the whole linkset.
306 // This allows Bullet to apply enough force on the child to move the whole linkset.
307 // (Also do the mass stuff before recomputing the constraint so mass is not zero.)
308 child.UpdatePhysicalMassProperties(linksetMass);
309
310 BSConstraint constrain;
311 if (!PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.PhysBody, child.PhysBody, out constrain))
312 {
313 // If constraint doesn't exist yet, create it.
314 constrain = BuildConstraint(LinksetRoot, child);
315 }
316 constrain.RecomputeConstraintVariables(linksetMass);
317
318 // DEBUG: see of inter-linkset collisions are causing problems
319 // BulletSimAPI.SetCollisionFilterMask2(child.BSBody.ptr,
320 // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask);
321
322 // BulletSimAPI.DumpConstraint2(PhysicsScene.World.ptr, constrain.Constraint.ptr); // DEBUG DEBUG
323 }
324
325 }
326}
327}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
deleted file mode 100755
index 7127aaf..0000000
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
+++ /dev/null
@@ -1,248 +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 copyrightD
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 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30
31using OMV = OpenMetaverse;
32using OpenSim.Framework;
33using OpenSim.Region.Physics.Manager;
34
35namespace OpenSim.Region.Physics.BulletSPlugin
36{
37// Class to wrap all objects.
38// The rest of BulletSim doesn't need to keep checking for avatars or prims
39// unless the difference is significant.
40public abstract class BSPhysObject : PhysicsActor
41{
42 protected void BaseInitialize(BSScene parentScene, uint localID, string name, string typeName)
43 {
44 PhysicsScene = parentScene;
45 LocalID = localID;
46 PhysObjectName = name;
47 TypeName = typeName;
48
49 Linkset = BSLinkset.Factory(PhysicsScene, this);
50 LastAssetBuildFailed = false;
51
52 CollisionCollection = new CollisionEventUpdate();
53 SubscribedEventsMs = 0;
54 CollidingStep = 0;
55 CollidingGroundStep = 0;
56 }
57
58 public BSScene PhysicsScene { get; protected set; }
59 // public override uint LocalID { get; set; } // Use the LocalID definition in PhysicsActor
60 public string PhysObjectName { get; protected set; }
61 public string TypeName { get; protected set; }
62
63 public BSLinkset Linkset { get; set; }
64
65 // Return the object mass without calculating it or having side effects
66 public abstract float RawMass { get; }
67 // Set the raw mass but also update physical mass properties (inertia, ...)
68 public abstract void UpdatePhysicalMassProperties(float mass);
69
70 // Reference to the physical body (btCollisionObject) of this object
71 public BulletBody PhysBody;
72 // Reference to the physical shape (btCollisionShape) of this object
73 public BulletShape PhysShape;
74
75 // 'true' if the mesh's underlying asset failed to build.
76 // This will keep us from looping after the first time the build failed.
77 public bool LastAssetBuildFailed { get; set; }
78
79 // The objects base shape information. Null if not a prim type shape.
80 public PrimitiveBaseShape BaseShape { get; protected set; }
81 // Some types of objects have preferred physical representations.
82 // Returns SHAPE_UNKNOWN if there is no preference.
83 public virtual ShapeData.PhysicsShapeType PreferredPhysicalShape
84 {
85 get { return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; }
86 }
87
88 // When the physical properties are updated, an EntityProperty holds the update values.
89 // Keep the current and last EntityProperties to enable computation of differences
90 // between the current update and the previous values.
91 public EntityProperties CurrentEntityProperties { get; set; }
92 public EntityProperties LastEntityProperties { get; set; }
93
94 public abstract OMV.Vector3 Scale { get; set; }
95 public abstract bool IsSolid { get; }
96 public abstract bool IsStatic { get; }
97
98 // Stop all physical motion.
99 public abstract void ZeroMotion();
100
101 // Step the vehicle simulation for this object. A NOOP if the vehicle was not configured.
102 public virtual void StepVehicle(float timeStep) { }
103
104 // Update the physical location and motion of the object. Called with data from Bullet.
105 public abstract void UpdateProperties(EntityProperties entprop);
106
107 // Tell the object to clean up.
108 public abstract void Destroy();
109
110 public abstract OMV.Vector3 RawPosition { get; set; }
111 public abstract OMV.Vector3 ForcePosition { get; set; }
112
113 public abstract OMV.Quaternion RawOrientation { get; set; }
114 public abstract OMV.Quaternion ForceOrientation { get; set; }
115
116 public abstract OMV.Vector3 ForceVelocity { get; set; }
117
118 public abstract OMV.Vector3 ForceRotationalVelocity { get; set; }
119
120 public abstract float ForceBuoyancy { get; set; }
121
122 public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; }
123
124 #region Collisions
125
126 // Requested number of milliseconds between collision events. Zero means disabled.
127 protected int SubscribedEventsMs { get; set; }
128 // Given subscription, the time that a collision may be passed up
129 protected int NextCollisionOkTime { get; set; }
130 // The simulation step that last had a collision
131 protected long CollidingStep { get; set; }
132 // The simulation step that last had a collision with the ground
133 protected long CollidingGroundStep { get; set; }
134 // The collision flags we think are set in Bullet
135 protected CollisionFlags CurrentCollisionFlags { get; set; }
136
137 // The collisions that have been collected this tick
138 protected CollisionEventUpdate CollisionCollection;
139
140 // The simulation step is telling this object about a collision.
141 // Return 'true' if a collision was processed and should be sent up.
142 // Called at taint time from within the Step() function
143 public virtual bool Collide(uint collidingWith, BSPhysObject collidee,
144 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
145 {
146 bool ret = false;
147
148 // The following lines make IsColliding() and IsCollidingGround() work
149 CollidingStep = PhysicsScene.SimulationStep;
150 if (collidingWith <= PhysicsScene.TerrainManager.HighestTerrainID)
151 {
152 CollidingGroundStep = PhysicsScene.SimulationStep;
153 }
154
155 // prims in the same linkset cannot collide with each other
156 if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID))
157 {
158 return ret;
159 }
160
161 // if someone has subscribed for collision events....
162 if (SubscribedEvents()) {
163 CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
164 DetailLog("{0},{1}.Collison.AddCollider,call,with={2},point={3},normal={4},depth={5}",
165 LocalID, TypeName, collidingWith, contactPoint, contactNormal, pentrationDepth);
166
167 ret = true;
168 }
169 return ret;
170 }
171
172 // Send the collected collisions into the simulator.
173 // Called at taint time from within the Step() function thus no locking problems
174 // with CollisionCollection and ObjectsWithNoMoreCollisions.
175 // Return 'true' if there were some actual collisions passed up
176 public virtual bool SendCollisions()
177 {
178 bool ret = true;
179 // If the 'no collision' call, force it to happen right now so quick collision_end
180 bool force = CollisionCollection.Count == 0;
181
182 // throttle the collisions to the number of milliseconds specified in the subscription
183 if (force || (PhysicsScene.SimulationNowTime >= NextCollisionOkTime))
184 {
185 NextCollisionOkTime = PhysicsScene.SimulationNowTime + SubscribedEventsMs;
186
187 // We are called if we previously had collisions. If there are no collisions
188 // this time, send up one last empty event so OpenSim can sense collision end.
189 if (CollisionCollection.Count == 0)
190 {
191 // If I have no collisions this time, remove me from the list of objects with collisions.
192 ret = false;
193 }
194
195 // DetailLog("{0},{1}.SendCollisionUpdate,call,numCollisions={2}", LocalID, TypeName, CollisionCollection.Count);
196 base.SendCollisionUpdate(CollisionCollection);
197
198 // The collisionCollection structure is passed around in the simulator.
199 // Make sure we don't have a handle to that one and that a new one is used for next time.
200 CollisionCollection = new CollisionEventUpdate();
201 }
202 return ret;
203 }
204
205 // Subscribe for collision events.
206 // Parameter is the millisecond rate the caller wishes collision events to occur.
207 public override void SubscribeEvents(int ms) {
208 // DetailLog("{0},{1}.SubscribeEvents,subscribing,ms={2}", LocalID, TypeName, ms);
209 SubscribedEventsMs = ms;
210 if (ms > 0)
211 {
212 // make sure first collision happens
213 NextCollisionOkTime = Util.EnvironmentTickCountSubtract(SubscribedEventsMs);
214
215 PhysicsScene.TaintedObject(TypeName+".SubscribeEvents", delegate()
216 {
217 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
218 });
219 }
220 else
221 {
222 // Subscribing for zero or less is the same as unsubscribing
223 UnSubscribeEvents();
224 }
225 }
226 public override void UnSubscribeEvents() {
227 // DetailLog("{0},{1}.UnSubscribeEvents,unsubscribing", LocalID, TypeName);
228 SubscribedEventsMs = 0;
229 PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate()
230 {
231 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
232 });
233 }
234 // Return 'true' if the simulator wants collision events
235 public override bool SubscribedEvents() {
236 return (SubscribedEventsMs > 0);
237 }
238
239 #endregion // Collisions
240
241 // High performance detailed logging routine used by the physical objects.
242 protected void DetailLog(string msg, params Object[] args)
243 {
244 if (PhysicsScene.PhysicsLogging.Enabled)
245 PhysicsScene.DetailLog(msg, args);
246 }
247}
248}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs
index 20f5180..0f027b8 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs
@@ -33,7 +33,7 @@ using OpenMetaverse;
33namespace OpenSim.Region.Physics.BulletSPlugin 33namespace OpenSim.Region.Physics.BulletSPlugin
34{ 34{
35 /// <summary> 35 /// <summary>
36 /// Entry for a port of Bullet (http://bulletphysics.org/) to OpenSim. 36 /// Entry for a port of Bullet (http://bulletphysics.org/) to OpenSim.
37 /// This module interfaces to an unmanaged C++ library which makes the 37 /// This module interfaces to an unmanaged C++ library which makes the
38 /// actual calls into the Bullet physics engine. 38 /// actual calls into the Bullet physics engine.
39 /// The unmanaged library is found in opensim-libs::trunk/unmanaged/BulletSim/. 39 /// The unmanaged library is found in opensim-libs::trunk/unmanaged/BulletSim/.
@@ -62,7 +62,7 @@ public class BSPlugin : IPhysicsPlugin
62 if (Util.IsWindows()) 62 if (Util.IsWindows())
63 Util.LoadArchSpecificWindowsDll("BulletSim.dll"); 63 Util.LoadArchSpecificWindowsDll("BulletSim.dll");
64 // If not Windows, loading is performed by the 64 // If not Windows, loading is performed by the
65 // Mono loader as specified in 65 // Mono loader as specified in
66 // "bin/Physics/OpenSim.Region.Physics.BulletSPlugin.dll.config". 66 // "bin/Physics/OpenSim.Region.Physics.BulletSPlugin.dll.config".
67 67
68 _mScene = new BSScene(sceneIdentifier); 68 _mScene = new BSScene(sceneIdentifier);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index aaa0d93..9c20004 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -24,9 +24,6 @@
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27
28// Uncomment this it enable code to do all shape an body memory management
29// in the C# code.
30using System; 27using System;
31using System.Reflection; 28using System.Reflection;
32using System.Collections.Generic; 29using System.Collections.Generic;
@@ -39,18 +36,32 @@ using OpenSim.Region.Physics.ConvexDecompositionDotNet;
39 36
40namespace OpenSim.Region.Physics.BulletSPlugin 37namespace OpenSim.Region.Physics.BulletSPlugin
41{ 38{
42
43 [Serializable] 39 [Serializable]
44public sealed class BSPrim : BSPhysObject 40public sealed class BSPrim : PhysicsActor
45{ 41{
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 private static readonly string LogHeader = "[BULLETS PRIM]"; 43 private static readonly string LogHeader = "[BULLETS PRIM]";
48 44
49 // _size is what the user passed. Scale is what we pass to the physics engine with the mesh. 45 private void DebugLog(string mm, params Object[] xx) { if (_scene.ShouldDebugLog) m_log.DebugFormat(mm, xx); }
50 // Often Scale is unity because the meshmerizer will apply _size when creating the mesh. 46
47 private IMesh _mesh;
48 private PrimitiveBaseShape _pbs;
49 private ShapeData.PhysicsShapeType _shapeType;
50 private ulong _meshKey;
51 private ulong _hullKey;
52 private List<ConvexResult> _hulls;
53
54 private BSScene _scene;
55 public BSScene Scene { get { return _scene; } }
56 private String _avName;
57 private uint _localID = 0;
58
59 // _size is what the user passed. _scale is what we pass to the physics engine with the mesh.
60 // Often _scale is unity because the meshmerizer will apply _size when creating the mesh.
51 private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user 61 private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user
52 // private OMV.Vector3 _scale; // the multiplier for each mesh dimension for the mesh as created by the meshmerizer 62 private OMV.Vector3 _scale; // the multiplier for each mesh dimension for the mesh as created by the meshmerizer
53 63
64 private bool _stopped;
54 private bool _grabbed; 65 private bool _grabbed;
55 private bool _isSelected; 66 private bool _isSelected;
56 private bool _isVolumeDetect; 67 private bool _isVolumeDetect;
@@ -78,6 +89,25 @@ public sealed class BSPrim : BSPhysObject
78 private bool _kinematic; 89 private bool _kinematic;
79 private float _buoyancy; 90 private float _buoyancy;
80 91
92 // Membership in a linkset is controlled by this class.
93 private BSLinkset _linkset;
94 public BSLinkset Linkset
95 {
96 get { return _linkset; }
97 set { _linkset = value; }
98 }
99
100 private int _subscribedEventsMs = 0;
101 private int _nextCollisionOkTime = 0;
102 long _collidingStep;
103 long _collidingGroundStep;
104
105 private BulletBody m_body;
106 public BulletBody Body {
107 get { return m_body; }
108 set { m_body = value; }
109 }
110
81 private BSDynamics _vehicle; 111 private BSDynamics _vehicle;
82 112
83 private OMV.Vector3 _PIDTarget; 113 private OMV.Vector3 _PIDTarget;
@@ -92,112 +122,108 @@ public sealed class BSPrim : BSPhysObject
92 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) 122 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical)
93 { 123 {
94 // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID); 124 // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID);
95 base.BaseInitialize(parent_scene, localID, primName, "BSPrim"); 125 _localID = localID;
96 _physicsActorType = (int)ActorTypes.Prim; 126 _avName = primName;
127 _scene = parent_scene;
97 _position = pos; 128 _position = pos;
98 _size = size; 129 _size = size;
99 Scale = new OMV.Vector3(1f, 1f, 1f); // the scale will be set by CreateGeom depending on object type 130 _scale = new OMV.Vector3(1f, 1f, 1f); // the scale will be set by CreateGeom depending on object type
100 _orientation = rotation; 131 _orientation = rotation;
101 _buoyancy = 1f; 132 _buoyancy = 1f;
102 _velocity = OMV.Vector3.Zero; 133 _velocity = OMV.Vector3.Zero;
103 _rotationalVelocity = OMV.Vector3.Zero; 134 _rotationalVelocity = OMV.Vector3.Zero;
104 BaseShape = pbs; 135 _hullKey = 0;
136 _meshKey = 0;
137 _pbs = pbs;
105 _isPhysical = pisPhysical; 138 _isPhysical = pisPhysical;
106 _isVolumeDetect = false; 139 _isVolumeDetect = false;
107 _friction = PhysicsScene.Params.defaultFriction; // TODO: compute based on object material 140 _subscribedEventsMs = 0;
108 _density = PhysicsScene.Params.defaultDensity; // TODO: compute based on object material 141 _friction = _scene.Params.defaultFriction; // TODO: compute based on object material
109 _restitution = PhysicsScene.Params.defaultRestitution; 142 _density = _scene.Params.defaultDensity; // TODO: compute based on object material
110 _vehicle = new BSDynamics(PhysicsScene, this); // add vehicleness 143 _restitution = _scene.Params.defaultRestitution;
144 _linkset = new BSLinkset(_scene, this); // a linkset of one
145 _vehicle = new BSDynamics(this); // add vehicleness
111 _mass = CalculateMass(); 146 _mass = CalculateMass();
112
113 // No body or shape yet
114 PhysBody = new BulletBody(LocalID, IntPtr.Zero);
115 PhysShape = new BulletShape(IntPtr.Zero);
116
117 DetailLog("{0},BSPrim.constructor,call", LocalID);
118 // do the actual object creation at taint time 147 // do the actual object creation at taint time
119 PhysicsScene.TaintedObject("BSPrim.create", delegate() 148 DetailLog("{0},BSPrim.constructor,call", LocalID);
149 _scene.TaintedObject("BSPrim.create", delegate()
120 { 150 {
121 CreateGeomAndObject(true); 151 RecreateGeomAndObject();
122 152
123 CurrentCollisionFlags = BulletSimAPI.GetCollisionFlags2(PhysBody.ptr); 153 // Get the pointer to the physical body for this object.
154 // At the moment, we're still letting BulletSim manage the creation and destruction
155 // of the object. Someday we'll move that into the C# code.
156 m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
124 }); 157 });
125 } 158 }
126 159
127 // called when this prim is being destroyed and we should free all the resources 160 // called when this prim is being destroyed and we should free all the resources
128 public override void Destroy() 161 public void Destroy()
129 { 162 {
130 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); 163 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID);
131 164
132 // Undo any links between me and any other object 165 // Undo any links between me and any other object
133 BSPhysObject parentBefore = Linkset.LinksetRoot; 166 BSPrim parentBefore = _linkset.LinksetRoot;
134 int childrenBefore = Linkset.NumberOfChildren; 167 int childrenBefore = _linkset.NumberOfChildren;
135 168
136 Linkset = Linkset.RemoveMeFromLinkset(this); 169 _linkset = _linkset.RemoveMeFromLinkset(this);
137 170
138 DetailLog("{0},BSPrim.Destroy,call,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}", 171 DetailLog("{0},BSPrim.Destroy,call,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}",
139 LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); 172 LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren);
140 173
141 // Undo any vehicle properties 174 // Undo any vehicle properties
142 this.VehicleType = (int)Vehicle.TYPE_NONE; 175 this.VehicleType = (int)Vehicle.TYPE_NONE;
143 176
144 PhysicsScene.TaintedObject("BSPrim.destroy", delegate() 177 _scene.TaintedObject("BSPrim.destroy", delegate()
145 { 178 {
146 DetailLog("{0},BSPrim.Destroy,taint,", LocalID); 179 DetailLog("{0},BSPrim.Destroy,taint,", LocalID);
147 // If there are physical body and shape, release my use of same. 180 // everything in the C# world will get garbage collected. Tell the C++ world to free stuff.
148 PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null); 181 BulletSimAPI.DestroyObject(_scene.WorldID, LocalID);
149 PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null);
150 }); 182 });
151 } 183 }
152 184
153 // No one uses this property. 185 public override bool Stopped {
154 public override bool Stopped { 186 get { return _stopped; }
155 get { return false; }
156 } 187 }
157 public override OMV.Vector3 Size { 188 public override OMV.Vector3 Size {
158 get { return _size; } 189 get { return _size; }
159 set { 190 set {
160 _size = value; 191 _size = value;
161 ForceBodyShapeRebuild(false); 192 _scene.TaintedObject("BSPrim.setSize", delegate()
162 } 193 {
194 _mass = CalculateMass(); // changing size changes the mass
195 BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, (IsPhysical ? _mass : 0f), IsPhysical);
196 // DetailLog("{0}: BSPrim.setSize: size={1}, mass={2}, physical={3}", LocalID, _size, _mass, IsPhysical);
197 RecreateGeomAndObject();
198 });
199 }
163 } 200 }
164 // Scale is what we set in the physics engine. It is different than 'size' in that 201 public override PrimitiveBaseShape Shape {
165 // 'size' can be encorporated into the mesh. In that case, the scale is <1,1,1>.
166 public override OMV.Vector3 Scale { get; set; }
167
168 public override PrimitiveBaseShape Shape {
169 set { 202 set {
170 BaseShape = value; 203 _pbs = value;
171 ForceBodyShapeRebuild(false); 204 _scene.TaintedObject("BSPrim.setShape", delegate()
172 } 205 {
206 _mass = CalculateMass(); // changing the shape changes the mass
207 RecreateGeomAndObject();
208 });
209 }
173 } 210 }
174 // Whatever the linkset wants is what I want. 211 public override uint LocalID {
175 public override ShapeData.PhysicsShapeType PreferredPhysicalShape 212 set { _localID = value; }
176 { get { return Linkset.PreferredPhysicalShape(this); } } 213 get { return _localID; }
177
178 public override bool ForceBodyShapeRebuild(bool inTaintTime)
179 {
180 LastAssetBuildFailed = false;
181 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ForceBodyShapeRebuild", delegate()
182 {
183 _mass = CalculateMass(); // changing the shape changes the mass
184 CreateGeomAndObject(true);
185 });
186 return true;
187 } 214 }
188 public override bool Grabbed { 215 public override bool Grabbed {
189 set { _grabbed = value; 216 set { _grabbed = value;
190 } 217 }
191 } 218 }
192 public override bool Selected { 219 public override bool Selected {
193 set { 220 set {
194 _isSelected = value; 221 _isSelected = value;
195 PhysicsScene.TaintedObject("BSPrim.setSelected", delegate() 222 _scene.TaintedObject("BSPrim.setSelected", delegate()
196 { 223 {
197 DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected); 224 SetObjectDynamic();
198 SetObjectDynamic(false);
199 }); 225 });
200 } 226 }
201 } 227 }
202 public override void CrossingFailure() { return; } 228 public override void CrossingFailure() { return; }
203 229
@@ -206,255 +232,158 @@ public sealed class BSPrim : BSPhysObject
206 BSPrim parent = obj as BSPrim; 232 BSPrim parent = obj as BSPrim;
207 if (parent != null) 233 if (parent != null)
208 { 234 {
209 BSPhysObject parentBefore = Linkset.LinksetRoot; 235 DebugLog("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, parent.LocalID);
210 int childrenBefore = Linkset.NumberOfChildren; 236 BSPrim parentBefore = _linkset.LinksetRoot;
237 int childrenBefore = _linkset.NumberOfChildren;
211 238
212 Linkset = parent.Linkset.AddMeToLinkset(this); 239 _linkset = parent.Linkset.AddMeToLinkset(this);
213 240
214 DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}", 241 DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}",
215 LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); 242 LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren);
216 } 243 }
217 return; 244 return;
218 } 245 }
219 246
220 // delink me from my linkset 247 // delink me from my linkset
221 public override void delink() { 248 public override void delink() {
222 // TODO: decide if this parent checking needs to happen at taint time 249 // TODO: decide if this parent checking needs to happen at taint time
223 // Race condition here: if link() and delink() in same simulation tick, the delink will not happen 250 // Race condition here: if link() and delink() in same simulation tick, the delink will not happen
251 DebugLog("{0}: delink {1}/{2}. Parent={3}", LogHeader, _avName, _localID,
252 _linkset.LinksetRoot._avName+"/"+_linkset.LinksetRoot.LocalID.ToString());
224 253
225 BSPhysObject parentBefore = Linkset.LinksetRoot; 254 BSPrim parentBefore = _linkset.LinksetRoot;
226 int childrenBefore = Linkset.NumberOfChildren; 255 int childrenBefore = _linkset.NumberOfChildren;
256
257 _linkset = _linkset.RemoveMeFromLinkset(this);
227 258
228 Linkset = Linkset.RemoveMeFromLinkset(this); 259 DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ",
229 260 LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren);
230 DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ", 261 return;
231 LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
232 return;
233 } 262 }
234 263
235 // Set motion values to zero. 264 // Set motion values to zero.
236 // Do it to the properties so the values get set in the physics engine. 265 // Do it to the properties so the values get set in the physics engine.
237 // Push the setting of the values to the viewer. 266 // Push the setting of the values to the viewer.
238 // Called at taint time! 267 // Called at taint time!
239 public override void ZeroMotion() 268 public void ZeroMotion()
240 { 269 {
241 _velocity = OMV.Vector3.Zero; 270 _velocity = OMV.Vector3.Zero;
242 _acceleration = OMV.Vector3.Zero; 271 _acceleration = OMV.Vector3.Zero;
243 _rotationalVelocity = OMV.Vector3.Zero; 272 _rotationalVelocity = OMV.Vector3.Zero;
244 273
245 // Zero some other properties in the physics engine 274 // Zero some other properties directly into the physics engine
246 BulletSimAPI.ClearAllForces2(PhysBody.ptr); 275 BulletSimAPI.SetVelocity2(Body.Ptr, OMV.Vector3.Zero);
276 BulletSimAPI.SetAngularVelocity2(Body.Ptr, OMV.Vector3.Zero);
277 BulletSimAPI.SetInterpolation2(Body.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero);
278 BulletSimAPI.ClearForces2(Body.Ptr);
247 } 279 }
248 280
249 public override void LockAngularMotion(OMV.Vector3 axis) 281 public override void LockAngularMotion(OMV.Vector3 axis)
250 { 282 {
251 DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis); 283 // DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis);
252 return; 284 return;
253 } 285 }
254 286
255 public override OMV.Vector3 RawPosition 287 public override OMV.Vector3 Position {
256 { 288 get {
257 get { return _position; } 289 if (!_linkset.IsRoot(this))
258 set { _position = value; } 290 // child prims move around based on their parent. Need to get the latest location
259 } 291 _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
260 public override OMV.Vector3 Position {
261 get {
262 // child prims move around based on their parent. Need to get the latest location
263 if (!Linkset.IsRoot(this))
264 _position = Linkset.Position(this);
265 292
266 // don't do the GetObjectPosition for root elements because this function is called a zillion times 293 // don't do the GetObjectPosition for root elements because this function is called a zillion times
267 // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); 294 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
268 return _position; 295 return _position;
269 } 296 }
270 set { 297 set {
271 // If you must push the position into the physics engine, use ForcePosition.
272 if (_position == value)
273 {
274 return;
275 }
276 _position = value; 298 _position = value;
277 // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? 299 // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint?
278 PositionSanityCheck(); 300 _scene.TaintedObject("BSPrim.setPosition", delegate()
279 PhysicsScene.TaintedObject("BSPrim.setPosition", delegate()
280 { 301 {
281 // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 302 // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
282 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); 303 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
283 ActivateIfPhysical(false);
284 });
285 }
286 }
287 public override OMV.Vector3 ForcePosition {
288 get {
289 _position = BulletSimAPI.GetPosition2(PhysBody.ptr);
290 return _position;
291 }
292 set {
293 _position = value;
294 PositionSanityCheck();
295 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
296 ActivateIfPhysical(false);
297 }
298 }
299
300 // Check that the current position is sane and, if not, modify the position to make it so.
301 // Check for being below terrain and being out of bounds.
302 // Returns 'true' of the position was made sane by some action.
303 private bool PositionSanityCheck()
304 {
305 bool ret = false;
306
307 // If totally below the ground, move the prim up
308 // TODO: figure out the right solution for this... only for dynamic objects?
309 /*
310 float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position);
311 if (Position.Z < terrainHeight)
312 {
313 DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight);
314 _position.Z = terrainHeight + 2.0f;
315 ret = true;
316 }
317 */
318 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0)
319 {
320 float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position);
321 // TODO: a floating motor so object will bob in the water
322 if (Position.Z < waterHeight)
323 {
324 _position.Z = waterHeight;
325 ret = true;
326 }
327 }
328
329 // TODO: check for out of bounds
330 return ret;
331 }
332
333 // A version of the sanity check that also makes sure a new position value is
334 // pushed to the physics engine. This routine would be used by anyone
335 // who is not already pushing the value.
336 private bool PositionSanityCheck(bool inTaintTime)
337 {
338 bool ret = false;
339 if (PositionSanityCheck())
340 {
341 // The new position value must be pushed into the physics engine but we can't
342 // just assign to "Position" because of potential call loops.
343 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.PositionSanityCheck", delegate()
344 {
345 DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
346 ForcePosition = _position;
347 }); 304 });
348 ret = true; 305 }
349 }
350 return ret;
351 } 306 }
352 307
353 // Return the effective mass of the object. 308 // Return the effective mass of the object.
354 // If there are multiple items in the linkset, add them together for the root 309 // If there are multiple items in the linkset, add them together for the root
355 public override float Mass 310 public override float Mass
356 { 311 {
357 get 312 get
358 { 313 {
359 return Linkset.LinksetMass; 314 return _linkset.LinksetMass;
360 // return _mass;
361 } 315 }
362 } 316 }
363 317
364 // used when we only want this prim's mass and not the linkset thing 318 // used when we only want this prim's mass and not the linkset thing
365 public override float RawMass { 319 public float MassRaw { get { return _mass; } }
366 get { return _mass; }
367 }
368 // Set the physical mass to the passed mass.
369 // Note that this does not change _mass!
370 public override void UpdatePhysicalMassProperties(float physMass)
371 {
372 if (IsStatic)
373 {
374 BulletSimAPI.SetMassProps2(PhysBody.ptr, 0f, OMV.Vector3.Zero);
375 BulletSimAPI.UpdateInertiaTensor2(PhysBody.ptr);
376 }
377 else
378 {
379 OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass);
380 BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, localInertia);
381 // center of mass is at the zero of the object
382 BulletSimAPI.SetCenterOfMassByPosRot2(PhysBody.ptr, ForcePosition, ForceOrientation);
383 // BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr);
384 DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2}", LocalID, physMass, localInertia);
385 }
386 }
387 320
388 // Is this used? 321 // Is this used?
389 public override OMV.Vector3 CenterOfMass 322 public override OMV.Vector3 CenterOfMass
390 { 323 {
391 get { return Linkset.CenterOfMass; } 324 get { return _linkset.CenterOfMass; }
392 } 325 }
393 326
394 // Is this used? 327 // Is this used?
395 public override OMV.Vector3 GeometricCenter 328 public override OMV.Vector3 GeometricCenter
396 { 329 {
397 get { return Linkset.GeometricCenter; } 330 get { return _linkset.GeometricCenter; }
398 } 331 }
399 332
400 public override OMV.Vector3 Force { 333 public override OMV.Vector3 Force {
401 get { return _force; } 334 get { return _force; }
402 set { 335 set {
403 _force = value; 336 _force = value;
404 PhysicsScene.TaintedObject("BSPrim.setForce", delegate() 337 _scene.TaintedObject("BSPrim.setForce", delegate()
405 { 338 {
406 // DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); 339 // DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force);
407 BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force); 340 // BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force);
341 BulletSimAPI.SetObjectForce2(Body.Ptr, _force);
408 }); 342 });
409 } 343 }
410 } 344 }
411 345
412 public override int VehicleType { 346 public override int VehicleType {
413 get { 347 get {
414 return (int)_vehicle.Type; // if we are a vehicle, return that type 348 return (int)_vehicle.Type; // if we are a vehicle, return that type
415 } 349 }
416 set { 350 set {
417 Vehicle type = (Vehicle)value; 351 Vehicle type = (Vehicle)value;
418 352 BSPrim vehiclePrim = this;
419 // Tell the scene about the vehicle so it will get processing each frame. 353 _scene.TaintedObject("setVehicleType", delegate()
420 PhysicsScene.VehicleInSceneTypeChanged(this, type);
421
422 PhysicsScene.TaintedObject("setVehicleType", delegate()
423 { 354 {
424 // Done at taint time so we're sure the physics engine is not using the variables 355 // Done at taint time so we're sure the physics engine is not using the variables
425 // Vehicle code changes the parameters for this vehicle type. 356 // Vehicle code changes the parameters for this vehicle type.
426 _vehicle.ProcessTypeChange(type); 357 _vehicle.ProcessTypeChange(type);
427 ActivateIfPhysical(false); 358 // Tell the scene about the vehicle so it will get processing each frame.
359 _scene.VehicleInSceneTypeChanged(this, type);
428 }); 360 });
429 } 361 }
430 } 362 }
431 public override void VehicleFloatParam(int param, float value) 363 public override void VehicleFloatParam(int param, float value)
432 { 364 {
433 PhysicsScene.TaintedObject("BSPrim.VehicleFloatParam", delegate() 365 _scene.TaintedObject("BSPrim.VehicleFloatParam", delegate()
434 { 366 {
435 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value); 367 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep);
436 ActivateIfPhysical(false);
437 }); 368 });
438 } 369 }
439 public override void VehicleVectorParam(int param, OMV.Vector3 value) 370 public override void VehicleVectorParam(int param, OMV.Vector3 value)
440 { 371 {
441 PhysicsScene.TaintedObject("BSPrim.VehicleVectorParam", delegate() 372 _scene.TaintedObject("BSPrim.VehicleVectorParam", delegate()
442 { 373 {
443 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value); 374 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep);
444 ActivateIfPhysical(false);
445 }); 375 });
446 } 376 }
447 public override void VehicleRotationParam(int param, OMV.Quaternion rotation) 377 public override void VehicleRotationParam(int param, OMV.Quaternion rotation)
448 { 378 {
449 PhysicsScene.TaintedObject("BSPrim.VehicleRotationParam", delegate() 379 _scene.TaintedObject("BSPrim.VehicleRotationParam", delegate()
450 { 380 {
451 _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation); 381 _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation);
452 ActivateIfPhysical(false);
453 }); 382 });
454 } 383 }
455 public override void VehicleFlags(int param, bool remove) 384 public override void VehicleFlags(int param, bool remove)
456 { 385 {
457 PhysicsScene.TaintedObject("BSPrim.VehicleFlags", delegate() 386 _scene.TaintedObject("BSPrim.VehicleFlags", delegate()
458 { 387 {
459 _vehicle.ProcessVehicleFlags(param, remove); 388 _vehicle.ProcessVehicleFlags(param, remove);
460 }); 389 });
@@ -462,355 +391,143 @@ public sealed class BSPrim : BSPhysObject
462 391
463 // Called each simulation step to advance vehicle characteristics. 392 // Called each simulation step to advance vehicle characteristics.
464 // Called from Scene when doing simulation step so we're in taint processing time. 393 // Called from Scene when doing simulation step so we're in taint processing time.
465 public override void StepVehicle(float timeStep) 394 public void StepVehicle(float timeStep)
466 { 395 {
467 if (IsPhysical && _vehicle.IsActive) 396 if (IsPhysical)
468 {
469 _vehicle.Step(timeStep); 397 _vehicle.Step(timeStep);
470 /* // TEST TEST DEBUG DEBUG -- trying to reduce the extra action of Bullet simulation step
471 PhysicsScene.PostTaintObject("BSPrim.StepVehicles", LocalID, delegate()
472 {
473 // This resets the interpolation values and recomputes the tensor variables
474 BulletSimAPI.SetCenterOfMassByPosRot2(BSBody.ptr, ForcePosition, ForceOrientation);
475 });
476 */
477 }
478 } 398 }
479 399
480 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more 400 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more
481 public override void SetVolumeDetect(int param) { 401 public override void SetVolumeDetect(int param) {
482 bool newValue = (param != 0); 402 bool newValue = (param != 0);
483 if (_isVolumeDetect != newValue) 403 _isVolumeDetect = newValue;
404 _scene.TaintedObject("BSPrim.SetVolumeDetect", delegate()
484 { 405 {
485 _isVolumeDetect = newValue; 406 SetObjectDynamic();
486 PhysicsScene.TaintedObject("BSPrim.SetVolumeDetect", delegate() 407 });
487 { 408 return;
488 // DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect);
489 SetObjectDynamic(true);
490 });
491 }
492 return;
493 } 409 }
494 public override OMV.Vector3 Velocity { 410
495 get { return _velocity; } 411 public override OMV.Vector3 Velocity {
412 get { return _velocity; }
496 set { 413 set {
497 _velocity = value; 414 _velocity = value;
498 PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate() 415 _scene.TaintedObject("BSPrim.setVelocity", delegate()
499 { 416 {
500 // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); 417 // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity);
501 BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity); 418 BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity);
502 }); 419 });
503 } 420 }
504 }
505 public override OMV.Vector3 ForceVelocity {
506 get { return _velocity; }
507 set {
508 _velocity = value;
509 BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity);
510 }
511 } 421 }
512 public override OMV.Vector3 Torque { 422 public override OMV.Vector3 Torque {
513 get { return _torque; } 423 get { return _torque; }
514 set { 424 set { _torque = value;
515 _torque = value;
516 AddAngularForce(_torque, false, false);
517 // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque); 425 // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque);
518 } 426 }
519 } 427 }
520 public override float CollisionScore { 428 public override float CollisionScore {
521 get { return _collisionScore; } 429 get { return _collisionScore; }
522 set { _collisionScore = value; 430 set { _collisionScore = value;
523 } 431 }
524 } 432 }
525 public override OMV.Vector3 Acceleration { 433 public override OMV.Vector3 Acceleration {
526 get { return _acceleration; } 434 get { return _acceleration; }
527 set { _acceleration = value; } 435 set { _acceleration = value; }
528 } 436 }
529 public override OMV.Quaternion RawOrientation 437 public override OMV.Quaternion Orientation {
530 {
531 get { return _orientation; }
532 set { _orientation = value; }
533 }
534 public override OMV.Quaternion Orientation {
535 get { 438 get {
536 // Children move around because tied to parent. Get a fresh value. 439 if (!_linkset.IsRoot(this))
537 if (!Linkset.IsRoot(this))
538 { 440 {
539 _orientation = Linkset.Orientation(this); 441 // Children move around because tied to parent. Get a fresh value.
442 _orientation = BulletSimAPI.GetObjectOrientation(_scene.WorldID, LocalID);
540 } 443 }
541 return _orientation; 444 return _orientation;
542 } 445 }
543 set { 446 set {
544 if (_orientation == value)
545 return;
546 _orientation = value; 447 _orientation = value;
547 // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint? 448 // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint?
548 PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate() 449 _scene.TaintedObject("BSPrim.setOrientation", delegate()
549 { 450 {
550 // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); 451 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
551 // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); 452 // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation);
552 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); 453 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
553 }); 454 });
554 } 455 }
555 } 456 }
556 // Go directly to Bullet to get/set the value. 457 public override int PhysicsActorType {
557 public override OMV.Quaternion ForceOrientation 458 get { return _physicsActorType; }
558 { 459 set { _physicsActorType = value;
559 get 460 }
560 {
561 _orientation = BulletSimAPI.GetOrientation2(PhysBody.ptr);
562 return _orientation;
563 }
564 set
565 {
566 _orientation = value;
567 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
568 }
569 } 461 }
570 public override int PhysicsActorType { 462 public override bool IsPhysical {
571 get { return _physicsActorType; } 463 get { return _isPhysical; }
572 set { _physicsActorType = value; }
573 }
574 public override bool IsPhysical {
575 get { return _isPhysical; }
576 set { 464 set {
577 if (_isPhysical != value) 465 _isPhysical = value;
466 _scene.TaintedObject("BSPrim.setIsPhysical", delegate()
578 { 467 {
579 _isPhysical = value; 468 SetObjectDynamic();
580 PhysicsScene.TaintedObject("BSPrim.setIsPhysical", delegate() 469 });
581 { 470 }
582 // DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical);
583 SetObjectDynamic(true);
584 // whether phys-to-static or static-to-phys, the object is not moving.
585 ZeroMotion();
586 });
587 }
588 }
589 } 471 }
590 472
591 // An object is static (does not move) if selected or not physical 473 // An object is static (does not move) if selected or not physical
592 public override bool IsStatic 474 private bool IsStatic
593 { 475 {
594 get { return _isSelected || !IsPhysical; } 476 get { return _isSelected || !IsPhysical; }
595 } 477 }
596 478
597 // An object is solid if it's not phantom and if it's not doing VolumeDetect 479 // An object is solid if it's not phantom and if it's not doing VolumeDetect
598 public override bool IsSolid 480 private bool IsSolid
599 { 481 {
600 get { return !IsPhantom && !_isVolumeDetect; } 482 get { return !IsPhantom && !_isVolumeDetect; }
601 } 483 }
602 484
603 // Make gravity work if the object is physical and not selected 485 // Make gravity work if the object is physical and not selected
604 // Called at taint-time!! 486 // No locking here because only called when it is safe
605 private void SetObjectDynamic(bool forceRebuild) 487 private void SetObjectDynamic()
606 {
607 // Recreate the physical object if necessary
608 CreateGeomAndObject(forceRebuild);
609 }
610
611 // Convert the simulator's physical properties into settings on BulletSim objects.
612 // There are four flags we're interested in:
613 // IsStatic: Object does not move, otherwise the object has mass and moves
614 // isSolid: other objects bounce off of this object
615 // isVolumeDetect: other objects pass through but can generate collisions
616 // collisionEvents: whether this object returns collision events
617 private void UpdatePhysicalParameters()
618 {
619 // DetailLog("{0},BSPrim.UpdatePhysicalParameters,entry,body={1},shape={2}", LocalID, BSBody, BSShape);
620
621 // Mangling all the physical properties requires the object not be in the physical world.
622 // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found).
623 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, PhysBody.ptr);
624
625 // Set up the object physicalness (does gravity and collisions move this object)
626 MakeDynamic(IsStatic);
627
628 // Update vehicle specific parameters (after MakeDynamic() so can change physical parameters)
629 _vehicle.Refresh();
630
631 // Arrange for collision events if the simulator wants them
632 EnableCollisions(SubscribedEvents());
633
634 // Make solid or not (do things bounce off or pass through this object).
635 MakeSolid(IsSolid);
636
637 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, PhysBody.ptr);
638
639 // Rebuild its shape
640 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr);
641
642 // Collision filter can be set only when the object is in the world
643 if (PhysBody.collisionFilter != 0 || PhysBody.collisionMask != 0)
644 {
645 BulletSimAPI.SetCollisionFilterMask2(PhysBody.ptr, (uint)PhysBody.collisionFilter, (uint)PhysBody.collisionMask);
646 }
647
648 // Recompute any linkset parameters.
649 // When going from non-physical to physical, this re-enables the constraints that
650 // had been automatically disabled when the mass was set to zero.
651 Linkset.Refresh(this);
652
653 DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}",
654 LocalID, IsStatic, IsSolid, _mass, SubscribedEvents(), CurrentCollisionFlags, PhysBody, PhysShape);
655 }
656
657 // "Making dynamic" means changing to and from static.
658 // When static, gravity does not effect the object and it is fixed in space.
659 // When dynamic, the object can fall and be pushed by others.
660 // This is independent of its 'solidness' which controls what passes through
661 // this object and what interacts with it.
662 private void MakeDynamic(bool makeStatic)
663 { 488 {
664 if (makeStatic) 489 // RA: remove this for the moment.
665 { 490 // The problem is that dynamic objects are hulls so if we are becoming physical
666 // Become a Bullet 'static' object type 491 // the shape has to be checked and possibly built.
667 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_STATIC_OBJECT); 492 // Maybe a VerifyCorrectPhysicalShape() routine?
668 // Stop all movement 493 // RecreateGeomAndObject();
669 ZeroMotion();
670 // Center of mass is at the center of the object
671 BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.PhysBody.ptr, _position, _orientation);
672 // Mass is zero which disables a bunch of physics stuff in Bullet
673 UpdatePhysicalMassProperties(0f);
674 // Set collision detection parameters
675 if (PhysicsScene.Params.ccdMotionThreshold > 0f)
676 {
677 BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold);
678 BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius);
679 }
680 // There can be special things needed for implementing linksets
681 Linkset.MakeStatic(this);
682 // The activation state is 'disabled' so Bullet will not try to act on it.
683 BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.DISABLE_SIMULATION);
684 // Start it out sleeping and physical actions could wake it up.
685 // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING);
686
687 PhysBody.collisionFilter = CollisionFilterGroups.StaticObjectFilter;
688 PhysBody.collisionMask = CollisionFilterGroups.StaticObjectMask;
689 }
690 else
691 {
692 // Not a Bullet static object
693 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_STATIC_OBJECT);
694
695 // Set various physical properties so internal dynamic properties will get computed correctly as they are set
696 BulletSimAPI.SetFriction2(PhysBody.ptr, PhysicsScene.Params.defaultFriction);
697 BulletSimAPI.SetRestitution2(PhysBody.ptr, PhysicsScene.Params.defaultRestitution);
698
699 // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382
700 // Since this can be called multiple times, only zero forces when becoming physical
701 // BulletSimAPI.ClearAllForces2(BSBody.ptr);
702 494
703 // For good measure, make sure the transform is set through to the motion state 495 // Bullet wants static objects to have a mass of zero
704 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); 496 float mass = IsStatic ? 0f : _mass;
705 497
706 // Center of mass is at the center of the object 498 BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass);
707 BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.PhysBody.ptr, _position, _orientation);
708
709 // A dynamic object has mass
710 UpdatePhysicalMassProperties(RawMass);
711
712 // Set collision detection parameters
713 if (PhysicsScene.Params.ccdMotionThreshold > 0f)
714 {
715 BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold);
716 BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius);
717 }
718
719 // Various values for simulation limits
720 BulletSimAPI.SetDamping2(PhysBody.ptr, PhysicsScene.Params.linearDamping, PhysicsScene.Params.angularDamping);
721 BulletSimAPI.SetDeactivationTime2(PhysBody.ptr, PhysicsScene.Params.deactivationTime);
722 BulletSimAPI.SetSleepingThresholds2(PhysBody.ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold);
723 BulletSimAPI.SetContactProcessingThreshold2(PhysBody.ptr, PhysicsScene.Params.contactProcessingThreshold);
724
725 // There might be special things needed for implementing linksets.
726 Linkset.MakeDynamic(this);
727
728 // Force activation of the object so Bullet will act on it.
729 // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects.
730 BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.ACTIVE_TAG);
731 // BulletSimAPI.Activate2(BSBody.ptr, true);
732
733 PhysBody.collisionFilter = CollisionFilterGroups.ObjectFilter;
734 PhysBody.collisionMask = CollisionFilterGroups.ObjectMask;
735 }
736 }
737
738 // "Making solid" means that other object will not pass through this object.
739 // To make transparent, we create a Bullet ghost object.
740 // Note: This expects to be called from the UpdatePhysicalParameters() routine as
741 // the functions after this one set up the state of a possibly newly created collision body.
742 private void MakeSolid(bool makeSolid)
743 {
744 CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(PhysBody.ptr);
745 if (makeSolid)
746 {
747 // Verify the previous code created the correct shape for this type of thing.
748 if ((bodyType & CollisionObjectTypes.CO_RIGID_BODY) == 0)
749 {
750 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for solidity. id={1}, type={2}", LogHeader, LocalID, bodyType);
751 }
752 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
753 }
754 else
755 {
756 if ((bodyType & CollisionObjectTypes.CO_GHOST_OBJECT) == 0)
757 {
758 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType);
759 }
760 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
761 PhysBody.collisionFilter = CollisionFilterGroups.VolumeDetectFilter;
762 PhysBody.collisionMask = CollisionFilterGroups.VolumeDetectMask;
763 }
764 }
765 499
766 // Enable physical actions. Bullet will keep sleeping non-moving physical objects so 500 // recompute any linkset parameters
767 // they need waking up when parameters are changed. 501 _linkset.Refresh(this);
768 // Called in taint-time!!
769 private void ActivateIfPhysical(bool forceIt)
770 {
771 if (IsPhysical)
772 BulletSimAPI.Activate2(PhysBody.ptr, forceIt);
773 }
774 502
775 // Turn on or off the flag controlling whether collision events are returned to the simulator. 503 CollisionFlags cf = BulletSimAPI.GetCollisionFlags2(Body.Ptr);
776 private void EnableCollisions(bool wantsCollisionEvents) 504 // DetailLog("{0},BSPrim.SetObjectDynamic,taint,static={1},solid={2},mass={3}, cf={4}", LocalID, IsStatic, IsSolid, mass, cf);
777 {
778 if (wantsCollisionEvents)
779 {
780 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
781 }
782 else
783 {
784 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
785 }
786 } 505 }
787 506
788 // prims don't fly 507 // prims don't fly
789 public override bool Flying { 508 public override bool Flying {
790 get { return _flying; } 509 get { return _flying; }
791 set { 510 set { _flying = value; }
792 _flying = value;
793 }
794 } 511 }
795 public override bool SetAlwaysRun { 512 public override bool SetAlwaysRun {
796 get { return _setAlwaysRun; } 513 get { return _setAlwaysRun; }
797 set { _setAlwaysRun = value; } 514 set { _setAlwaysRun = value; }
798 } 515 }
799 public override bool ThrottleUpdates { 516 public override bool ThrottleUpdates {
800 get { return _throttleUpdates; } 517 get { return _throttleUpdates; }
801 set { _throttleUpdates = value; } 518 set { _throttleUpdates = value; }
802 } 519 }
803 public override bool IsColliding { 520 public override bool IsColliding {
804 get { return (CollidingStep == PhysicsScene.SimulationStep); } 521 get { return (_collidingStep == _scene.SimulationStep); }
805 set { _isColliding = value; } 522 set { _isColliding = value; }
806 } 523 }
807 public override bool CollidingGround { 524 public override bool CollidingGround {
808 get { return (CollidingGroundStep == PhysicsScene.SimulationStep); } 525 get { return (_collidingGroundStep == _scene.SimulationStep); }
809 set { _collidingGround = value; } 526 set { _collidingGround = value; }
810 } 527 }
811 public override bool CollidingObj { 528 public override bool CollidingObj {
812 get { return _collidingObj; } 529 get { return _collidingObj; }
813 set { _collidingObj = value; } 530 set { _collidingObj = value; }
814 } 531 }
815 public bool IsPhantom { 532 public bool IsPhantom {
816 get { 533 get {
@@ -820,19 +537,10 @@ public sealed class BSPrim : BSPhysObject
820 return false; 537 return false;
821 } 538 }
822 } 539 }
823 public override bool FloatOnWater { 540 public override bool FloatOnWater {
824 set { 541 set { _floatOnWater = value; }
825 _floatOnWater = value;
826 PhysicsScene.TaintedObject("BSPrim.setFloatOnWater", delegate()
827 {
828 if (_floatOnWater)
829 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER);
830 else
831 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER);
832 });
833 }
834 } 542 }
835 public override OMV.Vector3 RotationalVelocity { 543 public override OMV.Vector3 RotationalVelocity {
836 get { 544 get {
837 /* 545 /*
838 OMV.Vector3 pv = OMV.Vector3.Zero; 546 OMV.Vector3 pv = OMV.Vector3.Zero;
@@ -844,76 +552,58 @@ public sealed class BSPrim : BSPhysObject
844 */ 552 */
845 553
846 return _rotationalVelocity; 554 return _rotationalVelocity;
847 } 555 }
848 set { 556 set {
849 _rotationalVelocity = value; 557 _rotationalVelocity = value;
850 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); 558 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity);
851 PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate() 559 _scene.TaintedObject("BSPrim.setRotationalVelocity", delegate()
852 { 560 {
853 DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); 561 // DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
854 BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity); 562 BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity);
855 }); 563 });
856 } 564 }
857 }
858 public override OMV.Vector3 ForceRotationalVelocity {
859 get {
860 return _rotationalVelocity;
861 }
862 set {
863 _rotationalVelocity = value;
864 BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity);
865 }
866 } 565 }
867 public override bool Kinematic { 566 public override bool Kinematic {
868 get { return _kinematic; } 567 get { return _kinematic; }
869 set { _kinematic = value; 568 set { _kinematic = value;
870 // m_log.DebugFormat("{0}: Kinematic={1}", LogHeader, _kinematic); 569 // m_log.DebugFormat("{0}: Kinematic={1}", LogHeader, _kinematic);
871 } 570 }
872 } 571 }
873 public override float Buoyancy { 572 public override float Buoyancy {
874 get { return _buoyancy; } 573 get { return _buoyancy; }
875 set { 574 set {
876 _buoyancy = value; 575 _buoyancy = value;
877 PhysicsScene.TaintedObject("BSPrim.setBuoyancy", delegate() 576 _scene.TaintedObject("BSPrim.setBuoyancy", delegate()
878 { 577 {
879 ForceBuoyancy = _buoyancy; 578 // DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
579 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy);
880 }); 580 });
881 } 581 }
882 }
883 public override float ForceBuoyancy {
884 get { return _buoyancy; }
885 set {
886 _buoyancy = value;
887 // DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
888 // Buoyancy is faked by changing the gravity applied to the object
889 float grav = PhysicsScene.Params.gravity * (1f - _buoyancy);
890 BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav));
891 }
892 } 582 }
893 583
894 // Used for MoveTo 584 // Used for MoveTo
895 public override OMV.Vector3 PIDTarget { 585 public override OMV.Vector3 PIDTarget {
896 set { _PIDTarget = value; } 586 set { _PIDTarget = value; }
897 } 587 }
898 public override bool PIDActive { 588 public override bool PIDActive {
899 set { _usePID = value; } 589 set { _usePID = value; }
900 } 590 }
901 public override float PIDTau { 591 public override float PIDTau {
902 set { _PIDTau = value; } 592 set { _PIDTau = value; }
903 } 593 }
904 594
905 // Used for llSetHoverHeight and maybe vehicle height 595 // Used for llSetHoverHeight and maybe vehicle height
906 // Hover Height will override MoveTo target's Z 596 // Hover Height will override MoveTo target's Z
907 public override bool PIDHoverActive { 597 public override bool PIDHoverActive {
908 set { _useHoverPID = value; } 598 set { _useHoverPID = value; }
909 } 599 }
910 public override float PIDHoverHeight { 600 public override float PIDHoverHeight {
911 set { _PIDHoverHeight = value; } 601 set { _PIDHoverHeight = value; }
912 } 602 }
913 public override PIDHoverType PIDHoverType { 603 public override PIDHoverType PIDHoverType {
914 set { _PIDHoverType = value; } 604 set { _PIDHoverType = value; }
915 } 605 }
916 public override float PIDHoverTau { 606 public override float PIDHoverTau {
917 set { _PIDHoverTao = value; } 607 set { _PIDHoverTao = value; }
918 } 608 }
919 609
@@ -925,9 +615,6 @@ public sealed class BSPrim : BSPhysObject
925 615
926 private List<OMV.Vector3> m_accumulatedForces = new List<OMV.Vector3>(); 616 private List<OMV.Vector3> m_accumulatedForces = new List<OMV.Vector3>();
927 public override void AddForce(OMV.Vector3 force, bool pushforce) { 617 public override void AddForce(OMV.Vector3 force, bool pushforce) {
928 AddForce(force, pushforce, false);
929 }
930 public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) {
931 // for an object, doesn't matter if force is a pushforce or not 618 // for an object, doesn't matter if force is a pushforce or not
932 if (force.IsFinite()) 619 if (force.IsFinite())
933 { 620 {
@@ -937,78 +624,56 @@ public sealed class BSPrim : BSPhysObject
937 } 624 }
938 else 625 else
939 { 626 {
940 m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); 627 m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader);
941 return; 628 return;
942 } 629 }
943 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate() 630 _scene.TaintedObject("BSPrim.AddForce", delegate()
944 { 631 {
945 OMV.Vector3 fSum = OMV.Vector3.Zero; 632 OMV.Vector3 fSum = OMV.Vector3.Zero;
946 lock (m_accumulatedForces) 633 lock (m_accumulatedForces)
947 { 634 {
948 // Sum the accumulated additional forces for one big force to apply once.
949 foreach (OMV.Vector3 v in m_accumulatedForces) 635 foreach (OMV.Vector3 v in m_accumulatedForces)
950 { 636 {
951 fSum += v; 637 fSum += v;
952 } 638 }
953 m_accumulatedForces.Clear(); 639 m_accumulatedForces.Clear();
954 } 640 }
955 DetailLog("{0},BSPrim.AddForce,taint,force={1}", LocalID, fSum); 641 // DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, _force);
956 if (fSum != OMV.Vector3.Zero) 642 BulletSimAPI.AddObjectForce2(Body.Ptr, fSum);
957 BulletSimAPI.ApplyCentralForce2(PhysBody.ptr, fSum);
958 }); 643 });
959 } 644 }
960 645
961 private List<OMV.Vector3> m_accumulatedAngularForces = new List<OMV.Vector3>(); 646 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
962 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { 647 // DetailLog("{0},BSPrim.AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce);
963 AddAngularForce(force, pushforce, false); 648 // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce);
964 } 649 }
965 public void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) 650 public override void SetMomentum(OMV.Vector3 momentum) {
966 { 651 // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum);
967 if (force.IsFinite()) 652 }
968 { 653 public override void SubscribeEvents(int ms) {
969 // _force += force; 654 _subscribedEventsMs = ms;
970 lock (m_accumulatedAngularForces) 655 if (ms > 0)
971 m_accumulatedAngularForces.Add(new OMV.Vector3(force));
972 }
973 else
974 {
975 m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID);
976 return;
977 }
978 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddAngularForce", delegate()
979 { 656 {
980 OMV.Vector3 fSum = OMV.Vector3.Zero; 657 // make sure first collision happens
981 lock (m_accumulatedAngularForces) 658 _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs;
982 { 659
983 // Sum the accumulated additional forces for one big force to apply once. 660 Scene.TaintedObject("BSPrim.SubscribeEvents", delegate()
984 foreach (OMV.Vector3 v in m_accumulatedAngularForces)
985 {
986 fSum += v;
987 }
988 m_accumulatedAngularForces.Clear();
989 }
990 DetailLog("{0},BSPrim.AddAngularForce,taint,aForce={1}", LocalID, fSum);
991 if (fSum != OMV.Vector3.Zero)
992 { 661 {
993 BulletSimAPI.ApplyTorque2(PhysBody.ptr, fSum); 662 BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
994 _torque = fSum; 663 });
995 } 664 }
996 });
997 } 665 }
998 // A torque impulse. 666 public override void UnSubscribeEvents() {
999 public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime) 667 _subscribedEventsMs = 0;
1000 { 668 Scene.TaintedObject("BSPrim.UnSubscribeEvents", delegate()
1001 OMV.Vector3 applyImpulse = impulse;
1002 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate()
1003 { 669 {
1004 DetailLog("{0},BSPrim.ApplyTorqueImpulse,taint,tImpulse={1}", LocalID, applyImpulse); 670 BulletSimAPI.RemoveFromCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
1005 BulletSimAPI.ApplyTorqueImpulse2(PhysBody.ptr, applyImpulse);
1006 }); 671 });
1007 } 672 }
1008 673 public override bool SubscribedEvents() {
1009 public override void SetMomentum(OMV.Vector3 momentum) { 674 return (_subscribedEventsMs > 0);
1010 // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum);
1011 } 675 }
676
1012 #region Mass Calculation 677 #region Mass Calculation
1013 678
1014 private float CalculateMass() 679 private float CalculateMass()
@@ -1017,19 +682,19 @@ public sealed class BSPrim : BSPhysObject
1017 float tmp; 682 float tmp;
1018 683
1019 float returnMass = 0; 684 float returnMass = 0;
1020 float hollowAmount = (float)BaseShape.ProfileHollow * 2.0e-5f; 685 float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f;
1021 float hollowVolume = hollowAmount * hollowAmount; 686 float hollowVolume = hollowAmount * hollowAmount;
1022 687
1023 switch (BaseShape.ProfileShape) 688 switch (_pbs.ProfileShape)
1024 { 689 {
1025 case ProfileShape.Square: 690 case ProfileShape.Square:
1026 // default box 691 // default box
1027 692
1028 if (BaseShape.PathCurve == (byte)Extrusion.Straight) 693 if (_pbs.PathCurve == (byte)Extrusion.Straight)
1029 { 694 {
1030 if (hollowAmount > 0.0) 695 if (hollowAmount > 0.0)
1031 { 696 {
1032 switch (BaseShape.HollowShape) 697 switch (_pbs.HollowShape)
1033 { 698 {
1034 case HollowShape.Square: 699 case HollowShape.Square:
1035 case HollowShape.Same: 700 case HollowShape.Same:
@@ -1053,19 +718,19 @@ public sealed class BSPrim : BSPhysObject
1053 } 718 }
1054 } 719 }
1055 720
1056 else if (BaseShape.PathCurve == (byte)Extrusion.Curve1) 721 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
1057 { 722 {
1058 //a tube 723 //a tube
1059 724
1060 volume *= 0.78539816339e-2f * (float)(200 - BaseShape.PathScaleX); 725 volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX);
1061 tmp= 1.0f -2.0e-2f * (float)(200 - BaseShape.PathScaleY); 726 tmp= 1.0f -2.0e-2f * (float)(200 - _pbs.PathScaleY);
1062 volume -= volume*tmp*tmp; 727 volume -= volume*tmp*tmp;
1063 728
1064 if (hollowAmount > 0.0) 729 if (hollowAmount > 0.0)
1065 { 730 {
1066 hollowVolume *= hollowAmount; 731 hollowVolume *= hollowAmount;
1067 732
1068 switch (BaseShape.HollowShape) 733 switch (_pbs.HollowShape)
1069 { 734 {
1070 case HollowShape.Square: 735 case HollowShape.Square:
1071 case HollowShape.Same: 736 case HollowShape.Same:
@@ -1090,13 +755,13 @@ public sealed class BSPrim : BSPhysObject
1090 755
1091 case ProfileShape.Circle: 756 case ProfileShape.Circle:
1092 757
1093 if (BaseShape.PathCurve == (byte)Extrusion.Straight) 758 if (_pbs.PathCurve == (byte)Extrusion.Straight)
1094 { 759 {
1095 volume *= 0.78539816339f; // elipse base 760 volume *= 0.78539816339f; // elipse base
1096 761
1097 if (hollowAmount > 0.0) 762 if (hollowAmount > 0.0)
1098 { 763 {
1099 switch (BaseShape.HollowShape) 764 switch (_pbs.HollowShape)
1100 { 765 {
1101 case HollowShape.Same: 766 case HollowShape.Same:
1102 case HollowShape.Circle: 767 case HollowShape.Circle:
@@ -1118,19 +783,19 @@ public sealed class BSPrim : BSPhysObject
1118 } 783 }
1119 } 784 }
1120 785
1121 else if (BaseShape.PathCurve == (byte)Extrusion.Curve1) 786 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
1122 { 787 {
1123 volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - BaseShape.PathScaleX); 788 volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX);
1124 tmp = 1.0f - .02f * (float)(200 - BaseShape.PathScaleY); 789 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
1125 volume *= (1.0f - tmp * tmp); 790 volume *= (1.0f - tmp * tmp);
1126 791
1127 if (hollowAmount > 0.0) 792 if (hollowAmount > 0.0)
1128 { 793 {
1129 794
1130 // calculate the hollow volume by it's shape compared to the prim shape 795 // calculate the hollow volume by it's shape compared to the prim shape
1131 hollowVolume *= hollowAmount; 796 hollowVolume *= hollowAmount;
1132 797
1133 switch (BaseShape.HollowShape) 798 switch (_pbs.HollowShape)
1134 { 799 {
1135 case HollowShape.Same: 800 case HollowShape.Same:
1136 case HollowShape.Circle: 801 case HollowShape.Circle:
@@ -1154,7 +819,7 @@ public sealed class BSPrim : BSPhysObject
1154 break; 819 break;
1155 820
1156 case ProfileShape.HalfCircle: 821 case ProfileShape.HalfCircle:
1157 if (BaseShape.PathCurve == (byte)Extrusion.Curve1) 822 if (_pbs.PathCurve == (byte)Extrusion.Curve1)
1158 { 823 {
1159 volume *= 0.52359877559829887307710723054658f; 824 volume *= 0.52359877559829887307710723054658f;
1160 } 825 }
@@ -1162,7 +827,7 @@ public sealed class BSPrim : BSPhysObject
1162 827
1163 case ProfileShape.EquilateralTriangle: 828 case ProfileShape.EquilateralTriangle:
1164 829
1165 if (BaseShape.PathCurve == (byte)Extrusion.Straight) 830 if (_pbs.PathCurve == (byte)Extrusion.Straight)
1166 { 831 {
1167 volume *= 0.32475953f; 832 volume *= 0.32475953f;
1168 833
@@ -1170,7 +835,7 @@ public sealed class BSPrim : BSPhysObject
1170 { 835 {
1171 836
1172 // calculate the hollow volume by it's shape compared to the prim shape 837 // calculate the hollow volume by it's shape compared to the prim shape
1173 switch (BaseShape.HollowShape) 838 switch (_pbs.HollowShape)
1174 { 839 {
1175 case HollowShape.Same: 840 case HollowShape.Same:
1176 case HollowShape.Triangle: 841 case HollowShape.Triangle:
@@ -1195,11 +860,11 @@ public sealed class BSPrim : BSPhysObject
1195 volume *= (1.0f - hollowVolume); 860 volume *= (1.0f - hollowVolume);
1196 } 861 }
1197 } 862 }
1198 else if (BaseShape.PathCurve == (byte)Extrusion.Curve1) 863 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
1199 { 864 {
1200 volume *= 0.32475953f; 865 volume *= 0.32475953f;
1201 volume *= 0.01f * (float)(200 - BaseShape.PathScaleX); 866 volume *= 0.01f * (float)(200 - _pbs.PathScaleX);
1202 tmp = 1.0f - .02f * (float)(200 - BaseShape.PathScaleY); 867 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
1203 volume *= (1.0f - tmp * tmp); 868 volume *= (1.0f - tmp * tmp);
1204 869
1205 if (hollowAmount > 0.0) 870 if (hollowAmount > 0.0)
@@ -1207,7 +872,7 @@ public sealed class BSPrim : BSPhysObject
1207 872
1208 hollowVolume *= hollowAmount; 873 hollowVolume *= hollowAmount;
1209 874
1210 switch (BaseShape.HollowShape) 875 switch (_pbs.HollowShape)
1211 { 876 {
1212 case HollowShape.Same: 877 case HollowShape.Same:
1213 case HollowShape.Triangle: 878 case HollowShape.Triangle:
@@ -1247,26 +912,26 @@ public sealed class BSPrim : BSPhysObject
1247 float profileBegin; 912 float profileBegin;
1248 float profileEnd; 913 float profileEnd;
1249 914
1250 if (BaseShape.PathCurve == (byte)Extrusion.Straight || BaseShape.PathCurve == (byte)Extrusion.Flexible) 915 if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible)
1251 { 916 {
1252 taperX1 = BaseShape.PathScaleX * 0.01f; 917 taperX1 = _pbs.PathScaleX * 0.01f;
1253 if (taperX1 > 1.0f) 918 if (taperX1 > 1.0f)
1254 taperX1 = 2.0f - taperX1; 919 taperX1 = 2.0f - taperX1;
1255 taperX = 1.0f - taperX1; 920 taperX = 1.0f - taperX1;
1256 921
1257 taperY1 = BaseShape.PathScaleY * 0.01f; 922 taperY1 = _pbs.PathScaleY * 0.01f;
1258 if (taperY1 > 1.0f) 923 if (taperY1 > 1.0f)
1259 taperY1 = 2.0f - taperY1; 924 taperY1 = 2.0f - taperY1;
1260 taperY = 1.0f - taperY1; 925 taperY = 1.0f - taperY1;
1261 } 926 }
1262 else 927 else
1263 { 928 {
1264 taperX = BaseShape.PathTaperX * 0.01f; 929 taperX = _pbs.PathTaperX * 0.01f;
1265 if (taperX < 0.0f) 930 if (taperX < 0.0f)
1266 taperX = -taperX; 931 taperX = -taperX;
1267 taperX1 = 1.0f - taperX; 932 taperX1 = 1.0f - taperX;
1268 933
1269 taperY = BaseShape.PathTaperY * 0.01f; 934 taperY = _pbs.PathTaperY * 0.01f;
1270 if (taperY < 0.0f) 935 if (taperY < 0.0f)
1271 taperY = -taperY; 936 taperY = -taperY;
1272 taperY1 = 1.0f - taperY; 937 taperY1 = 1.0f - taperY;
@@ -1276,18 +941,20 @@ public sealed class BSPrim : BSPhysObject
1276 941
1277 volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY); 942 volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY);
1278 943
1279 pathBegin = (float)BaseShape.PathBegin * 2.0e-5f; 944 pathBegin = (float)_pbs.PathBegin * 2.0e-5f;
1280 pathEnd = 1.0f - (float)BaseShape.PathEnd * 2.0e-5f; 945 pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f;
1281 volume *= (pathEnd - pathBegin); 946 volume *= (pathEnd - pathBegin);
1282 947
1283 // this is crude aproximation 948 // this is crude aproximation
1284 profileBegin = (float)BaseShape.ProfileBegin * 2.0e-5f; 949 profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f;
1285 profileEnd = 1.0f - (float)BaseShape.ProfileEnd * 2.0e-5f; 950 profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f;
1286 volume *= (profileEnd - profileBegin); 951 volume *= (profileEnd - profileBegin);
1287 952
1288 returnMass = _density * volume; 953 returnMass = _density * volume;
1289 954
1290 /* Comment out code that computes the mass of the linkset. That is done in the Linkset class. 955 /*
956 * This change means each object keeps its own mass and the Mass property
957 * will return the sum if we're part of a linkset.
1291 if (IsRootOfLinkset) 958 if (IsRootOfLinkset)
1292 { 959 {
1293 foreach (BSPrim prim in _childrenPrims) 960 foreach (BSPrim prim in _childrenPrims)
@@ -1300,42 +967,296 @@ public sealed class BSPrim : BSPhysObject
1300 if (returnMass <= 0) 967 if (returnMass <= 0)
1301 returnMass = 0.0001f; 968 returnMass = 0.0001f;
1302 969
1303 if (returnMass > PhysicsScene.MaximumObjectMass) 970 if (returnMass > _scene.MaximumObjectMass)
1304 returnMass = PhysicsScene.MaximumObjectMass; 971 returnMass = _scene.MaximumObjectMass;
1305 972
1306 return returnMass; 973 return returnMass;
1307 }// end CalculateMass 974 }// end CalculateMass
1308 #endregion Mass Calculation 975 #endregion Mass Calculation
1309 976
1310 // Rebuild the geometry and object. 977 // Create the geometry information in Bullet for later use
1311 // This is called when the shape changes so we need to recreate the mesh/hull. 978 // The objects needs a hull if it's physical otherwise a mesh is enough
1312 // Called at taint-time!!! 979 // No locking here because this is done when we know physics is not simulating
1313 private void CreateGeomAndObject(bool forceRebuild) 980 // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used
981 // Returns 'true' if the geometry was rebuilt
982 private bool CreateGeom(bool forceRebuild)
1314 { 983 {
1315 // If this prim is part of a linkset, we must remove and restore the physical 984 // the mesher thought this was too simple to mesh. Use a native Bullet collision shape.
1316 // links if the body is rebuilt. 985 bool ret = false;
1317 bool needToRestoreLinkset = false; 986 if (!_scene.NeedsMeshing(_pbs))
1318
1319 // Create the correct physical representation for this type of object.
1320 // Updates BSBody and BSShape with the new information.
1321 // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary.
1322 // Returns 'true' if either the body or the shape was changed.
1323 PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, null, delegate(BulletBody dBody)
1324 { 987 {
1325 // Called if the current prim body is about to be destroyed. 988 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
1326 // Remove all the physical dependencies on the old body. 989 {
1327 // (Maybe someday make the changing of BSShape an event handled by BSLinkset.) 990 // if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
1328 needToRestoreLinkset = Linkset.RemoveBodyDependencies(this); 991 // {
1329 }); 992 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size);
993 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE))
994 {
995 // DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild);
996 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE;
997 // Bullet native objects are scaled by the Bullet engine so pass the size in
998 _scale = _size;
999 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before?
1000 ret = true;
1001 }
1002 // }
1003 }
1004 else
1005 {
1006 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size);
1007 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX))
1008 {
1009 // DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild);
1010 _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX;
1011 _scale = _size;
1012 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before?
1013 ret = true;
1014 }
1015 }
1016 }
1017 else
1018 {
1019 if (IsPhysical)
1020 {
1021 if (forceRebuild || _hullKey == 0)
1022 {
1023 // physical objects require a hull for interaction.
1024 // This will create the mesh if it doesn't already exist
1025 CreateGeomHull();
1026 ret = true;
1027 }
1028 }
1029 else
1030 {
1031 if (forceRebuild || _meshKey == 0)
1032 {
1033 // Static (non-physical) objects only need a mesh for bumping into
1034 CreateGeomMesh();
1035 ret = true;
1036 }
1037 }
1038 }
1039 return ret;
1040 }
1041
1042 // No locking here because this is done when we know physics is not simulating
1043 private void CreateGeomMesh()
1044 {
1045 float lod = _pbs.SculptEntry ? _scene.SculptLOD : _scene.MeshLOD;
1046 ulong newMeshKey = (ulong)_pbs.GetMeshKey(_size, lod);
1047 // m_log.DebugFormat("{0}: CreateGeomMesh: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _meshKey, newMeshKey);
1048
1049 // if this new shape is the same as last time, don't recreate the mesh
1050 if (_meshKey == newMeshKey) return;
1051
1052 // DetailLog("{0},BSPrim.CreateGeomMesh,create,key={1}", LocalID, newMeshKey);
1053 // Since we're recreating new, get rid of any previously generated shape
1054 if (_meshKey != 0)
1055 {
1056 // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey);
1057 // DetailLog("{0},BSPrim.CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey);
1058 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey);
1059 _mesh = null;
1060 _meshKey = 0;
1061 }
1062
1063 _meshKey = newMeshKey;
1064 // always pass false for physicalness as this creates some sort of bounding box which we don't need
1065 _mesh = _scene.mesher.CreateMesh(_avName, _pbs, _size, lod, false);
1066
1067 int[] indices = _mesh.getIndexListAsInt();
1068 List<OMV.Vector3> vertices = _mesh.getVertexList();
1069
1070 float[] verticesAsFloats = new float[vertices.Count * 3];
1071 int vi = 0;
1072 foreach (OMV.Vector3 vv in vertices)
1073 {
1074 verticesAsFloats[vi++] = vv.X;
1075 verticesAsFloats[vi++] = vv.Y;
1076 verticesAsFloats[vi++] = vv.Z;
1077 }
1078
1079 // m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}",
1080 // LogHeader, _localID, _meshKey, indices.Length, vertices.Count);
1081 BulletSimAPI.CreateMesh(_scene.WorldID, _meshKey, indices.GetLength(0), indices,
1082 vertices.Count, verticesAsFloats);
1083
1084 _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH;
1085 // meshes are already scaled by the meshmerizer
1086 _scale = new OMV.Vector3(1f, 1f, 1f);
1087 // DetailLog("{0},BSPrim.CreateGeomMesh,done", LocalID);
1088 return;
1089 }
1090
1091 // No locking here because this is done when we know physics is not simulating
1092 private void CreateGeomHull()
1093 {
1094 float lod = _pbs.SculptEntry ? _scene.SculptLOD : _scene.MeshLOD;
1095 ulong newHullKey = (ulong)_pbs.GetMeshKey(_size, lod);
1096 // m_log.DebugFormat("{0}: CreateGeomHull: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _hullKey, newHullKey);
1097
1098 // if the hull hasn't changed, don't rebuild it
1099 if (newHullKey == _hullKey) return;
1330 1100
1331 if (needToRestoreLinkset) 1101 // DetailLog("{0},BSPrim.CreateGeomHull,create,oldKey={1},newKey={2}", LocalID, _hullKey, newHullKey);
1102
1103 // Since we're recreating new, get rid of any previously generated shape
1104 if (_hullKey != 0)
1332 { 1105 {
1333 // If physical body dependencies were removed, restore them 1106 // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey);
1334 Linkset.RestoreBodyDependencies(this); 1107 // DetailLog("{0},BSPrim.CreateGeomHull,deleteOldHull,key={1}", LocalID, _hullKey);
1108 BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey);
1109 _hullKey = 0;
1110 }
1111
1112 _hullKey = newHullKey;
1113
1114 // Make sure the underlying mesh exists and is correct
1115 CreateGeomMesh();
1116
1117 int[] indices = _mesh.getIndexListAsInt();
1118 List<OMV.Vector3> vertices = _mesh.getVertexList();
1119
1120 //format conversion from IMesh format to DecompDesc format
1121 List<int> convIndices = new List<int>();
1122 List<float3> convVertices = new List<float3>();
1123 for (int ii = 0; ii < indices.GetLength(0); ii++)
1124 {
1125 convIndices.Add(indices[ii]);
1126 }
1127 foreach (OMV.Vector3 vv in vertices)
1128 {
1129 convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
1130 }
1131
1132 // setup and do convex hull conversion
1133 _hulls = new List<ConvexResult>();
1134 DecompDesc dcomp = new DecompDesc();
1135 dcomp.mIndices = convIndices;
1136 dcomp.mVertices = convVertices;
1137 ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
1138 // create the hull into the _hulls variable
1139 convexBuilder.process(dcomp);
1140
1141 // Convert the vertices and indices for passing to unmanaged.
1142 // The hull information is passed as a large floating point array.
1143 // The format is:
1144 // convHulls[0] = number of hulls
1145 // convHulls[1] = number of vertices in first hull
1146 // convHulls[2] = hull centroid X coordinate
1147 // convHulls[3] = hull centroid Y coordinate
1148 // convHulls[4] = hull centroid Z coordinate
1149 // convHulls[5] = first hull vertex X
1150 // convHulls[6] = first hull vertex Y
1151 // convHulls[7] = first hull vertex Z
1152 // convHulls[8] = second hull vertex X
1153 // ...
1154 // convHulls[n] = number of vertices in second hull
1155 // convHulls[n+1] = second hull centroid X coordinate
1156 // ...
1157 //
1158 // TODO: is is very inefficient. Someday change the convex hull generator to return
1159 // data structures that do not need to be converted in order to pass to Bullet.
1160 // And maybe put the values directly into pinned memory rather than marshaling.
1161 int hullCount = _hulls.Count;
1162 int totalVertices = 1; // include one for the count of the hulls
1163 foreach (ConvexResult cr in _hulls)
1164 {
1165 totalVertices += 4; // add four for the vertex count and centroid
1166 totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
1167 }
1168 float[] convHulls = new float[totalVertices];
1169
1170 convHulls[0] = (float)hullCount;
1171 int jj = 1;
1172 foreach (ConvexResult cr in _hulls)
1173 {
1174 // copy vertices for index access
1175 float3[] verts = new float3[cr.HullVertices.Count];
1176 int kk = 0;
1177 foreach (float3 ff in cr.HullVertices)
1178 {
1179 verts[kk++] = ff;
1180 }
1181
1182 // add to the array one hull's worth of data
1183 convHulls[jj++] = cr.HullIndices.Count;
1184 convHulls[jj++] = 0f; // centroid x,y,z
1185 convHulls[jj++] = 0f;
1186 convHulls[jj++] = 0f;
1187 foreach (int ind in cr.HullIndices)
1188 {
1189 convHulls[jj++] = verts[ind].x;
1190 convHulls[jj++] = verts[ind].y;
1191 convHulls[jj++] = verts[ind].z;
1192 }
1335 } 1193 }
1336 1194
1337 // Make sure the properties are set on the new object 1195 // create the hull definition in Bullet
1338 UpdatePhysicalParameters(); 1196 // m_log.DebugFormat("{0}: CreateGeom: calling CreateHull. lid={1}, key={2}, hulls={3}", LogHeader, _localID, _hullKey, hullCount);
1197 BulletSimAPI.CreateHull(_scene.WorldID, _hullKey, hullCount, convHulls);
1198 _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL;
1199 // meshes are already scaled by the meshmerizer
1200 _scale = new OMV.Vector3(1f, 1f, 1f);
1201 // DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID);
1202 return;
1203 }
1204
1205 // Callback from convex hull creater with a newly created hull.
1206 // Just add it to the collection of hulls for this shape.
1207 private void HullReturn(ConvexResult result)
1208 {
1209 _hulls.Add(result);
1210 return;
1211 }
1212
1213 // Create an object in Bullet if it has not already been created
1214 // No locking here because this is done when the physics engine is not simulating
1215 // Returns 'true' if an object was actually created.
1216 private bool CreateObject()
1217 {
1218 // this routine is called when objects are rebuilt.
1219
1220 // the mesh or hull must have already been created in Bullet
1221 ShapeData shape;
1222 FillShapeInfo(out shape);
1223 // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type);
1224 bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape);
1225
1226 // the CreateObject() may have recreated the rigid body. Make sure we have the latest.
1227 Body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
1228
1229 return ret;
1230 }
1231
1232 // Copy prim's info into the BulletSim shape description structure
1233 public void FillShapeInfo(out ShapeData shape)
1234 {
1235 shape.ID = _localID;
1236 shape.Type = _shapeType;
1237 shape.Position = _position;
1238 shape.Rotation = _orientation;
1239 shape.Velocity = _velocity;
1240 shape.Scale = _scale;
1241 shape.Mass = _isPhysical ? _mass : 0f;
1242 shape.Buoyancy = _buoyancy;
1243 shape.HullKey = _hullKey;
1244 shape.MeshKey = _meshKey;
1245 shape.Friction = _friction;
1246 shape.Restitution = _restitution;
1247 shape.Collidable = (!IsPhantom) ? ShapeData.numericTrue : ShapeData.numericFalse;
1248 shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue;
1249 }
1250
1251
1252 // Rebuild the geometry and object.
1253 // This is called when the shape changes so we need to recreate the mesh/hull.
1254 // No locking here because this is done when the physics engine is not simulating
1255 private void RecreateGeomAndObject()
1256 {
1257 // m_log.DebugFormat("{0}: RecreateGeomAndObject. lID={1}", LogHeader, _localID);
1258 if (CreateGeom(true))
1259 CreateObject();
1339 return; 1260 return;
1340 } 1261 }
1341 1262
@@ -1356,7 +1277,7 @@ public sealed class BSPrim : BSPhysObject
1356 const float ACCELERATION_TOLERANCE = 0.01f; 1277 const float ACCELERATION_TOLERANCE = 0.01f;
1357 const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f; 1278 const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f;
1358 1279
1359 public override void UpdateProperties(EntityProperties entprop) 1280 public void UpdateProperties(EntityProperties entprop)
1360 { 1281 {
1361 /* 1282 /*
1362 UpdatedProperties changed = 0; 1283 UpdatedProperties changed = 0;
@@ -1404,7 +1325,7 @@ public sealed class BSPrim : BSPhysObject
1404 // Don't check for damping here -- it's done in BulletSim and SceneObjectPart. 1325 // Don't check for damping here -- it's done in BulletSim and SceneObjectPart.
1405 1326
1406 // Updates only for individual prims and for the root object of a linkset. 1327 // Updates only for individual prims and for the root object of a linkset.
1407 if (Linkset.IsRoot(this)) 1328 if (_linkset.IsRoot(this))
1408 { 1329 {
1409 // Assign to the local variables so the normal set action does not happen 1330 // Assign to the local variables so the normal set action does not happen
1410 _position = entprop.Position; 1331 _position = entprop.Position;
@@ -1413,32 +1334,69 @@ public sealed class BSPrim : BSPhysObject
1413 _acceleration = entprop.Acceleration; 1334 _acceleration = entprop.Acceleration;
1414 _rotationalVelocity = entprop.RotationalVelocity; 1335 _rotationalVelocity = entprop.RotationalVelocity;
1415 1336
1416 // remember the current and last set values 1337 // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}",
1417 LastEntityProperties = CurrentEntityProperties; 1338 // LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
1418 CurrentEntityProperties = entprop; 1339 // DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
1419 1340 // LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
1420 PositionSanityCheck(true);
1421
1422 OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation;
1423 DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}",
1424 LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity);
1425
1426 // BulletSimAPI.DumpRigidBody2(PhysicsScene.World.ptr, BSBody.ptr); // DEBUG DEBUG DEBUG
1427 1341
1428 base.RequestPhysicsterseUpdate(); 1342 base.RequestPhysicsterseUpdate();
1429 } 1343 }
1430 /* 1344 /*
1431 else 1345 else
1432 { 1346 {
1433 // For debugging, report the movement of children 1347 // For debugging, we also report the movement of children
1434 DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", 1348 DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
1435 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, 1349 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
1436 entprop.Acceleration, entprop.RotationalVelocity); 1350 entprop.Acceleration, entprop.RotationalVelocity);
1437 } 1351 }
1438 */ 1352 */
1353 }
1354
1355 // I've collided with something
1356 CollisionEventUpdate collisionCollection;
1357 public void Collide(uint collidingWith, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
1358 {
1359 // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith);
1360
1361 // The following lines make IsColliding() and IsCollidingGround() work
1362 _collidingStep = _scene.SimulationStep;
1363 if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID)
1364 {
1365 _collidingGroundStep = _scene.SimulationStep;
1366 }
1367
1368 // DetailLog("{0},BSPrim.Collison,call,with={1}", LocalID, collidingWith);
1369
1370 // if someone is subscribed to collision events....
1371 if (_subscribedEventsMs != 0) {
1372 // throttle the collisions to the number of milliseconds specified in the subscription
1373 int nowTime = _scene.SimulationNowTime;
1374 if (nowTime >= _nextCollisionOkTime) {
1375 _nextCollisionOkTime = nowTime + _subscribedEventsMs;
1439 1376
1440 // The linkset implimentation might want to know about this. 1377 if (collisionCollection == null)
1441 Linkset.UpdateProperties(this); 1378 collisionCollection = new CollisionEventUpdate();
1379 collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
1380 }
1381 }
1382 }
1383
1384 // The scene is telling us it's time to pass our collected collisions into the simulator
1385 public void SendCollisions()
1386 {
1387 if (collisionCollection != null && collisionCollection.Count > 0)
1388 {
1389 base.SendCollisionUpdate(collisionCollection);
1390 // The collisionCollection structure is passed around in the simulator.
1391 // Make sure we don't have a handle to that one and that a new one is used next time.
1392 collisionCollection = null;
1393 }
1394 }
1395
1396 // Invoke the detailed logger and output something if it's enabled.
1397 private void DetailLog(string msg, params Object[] args)
1398 {
1399 Scene.PhysicsLogging.Write(msg, args);
1442 } 1400 }
1443} 1401}
1444} 1402}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 740f339..a31c578 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -39,88 +39,96 @@ using log4net;
39using OpenMetaverse; 39using OpenMetaverse;
40 40
41// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim) 41// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim)
42// Test sculpties (verified that they don't work) 42// Debug linkset
43// Test with multiple regions in one simulator
44// Adjust character capsule size when height is adjusted (ScenePresence.SetHeight)
45// Test sculpties
43// Compute physics FPS reasonably 46// Compute physics FPS reasonably
44// Based on material, set density and friction 47// Based on material, set density and friction
45// Don't use constraints in linksets of non-physical objects. Means having to move children manually. 48// More efficient memory usage when passing hull information from BSPrim to BulletSim
49// Move all logic out of the C++ code and into the C# code for easier future modifications.
46// Four states of prim: Physical, regular, phantom and selected. Are we modeling these correctly? 50// Four states of prim: Physical, regular, phantom and selected. Are we modeling these correctly?
47// In SL one can set both physical and phantom (gravity, does not effect others, makes collisions with ground) 51// In SL one can set both physical and phantom (gravity, does not effect others, makes collisions with ground)
48// At the moment, physical and phantom causes object to drop through the terrain 52// At the moment, physical and phantom causes object to drop through the terrain
49// Physical phantom objects and related typing (collision options ) 53// Physical phantom objects and related typing (collision options )
54// Use collision masks for collision with terrain and phantom objects
50// Check out llVolumeDetect. Must do something for that. 55// Check out llVolumeDetect. Must do something for that.
51// Use collision masks for collision with terrain and phantom objects
52// More efficient memory usage when passing hull information from BSPrim to BulletSim
53// Should prim.link() and prim.delink() membership checking happen at taint time? 56// Should prim.link() and prim.delink() membership checking happen at taint time?
54// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once. 57// changing the position and orientation of a linked prim must rebuild the constraint with the root.
58// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once
55// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect 59// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect
60// Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions)
56// Implement LockAngularMotion 61// Implement LockAngularMotion
57// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation) 62// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation)
63// Does NeedsMeshing() really need to exclude all the different shapes?
58// Remove mesh and Hull stuff. Use mesh passed to bullet and use convexdecom from bullet. 64// Remove mesh and Hull stuff. Use mesh passed to bullet and use convexdecom from bullet.
59// Add PID movement operations. What does ScenePresence.MoveToTarget do? 65// Add PID movement operations. What does ScenePresence.MoveToTarget do?
60// Check terrain size. 128 or 127? 66// Check terrain size. 128 or 127?
61// Raycast 67// Raycast
62// 68//
63namespace OpenSim.Region.Physics.BulletSPlugin 69namespace OpenSim.Region.Physics.BulletSPlugin
64{ 70{
65public sealed class BSScene : PhysicsScene, IPhysicsParameters 71public class BSScene : PhysicsScene, IPhysicsParameters
66{ 72{
67 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 73 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
68 private static readonly string LogHeader = "[BULLETS SCENE]"; 74 private static readonly string LogHeader = "[BULLETS SCENE]";
69 75
70 // The name of the region we're working for. 76 public void DebugLog(string mm, params Object[] xx) { if (ShouldDebugLog) m_log.DebugFormat(mm, xx); }
71 public string RegionName { get; private set; }
72 77
73 public string BulletSimVersion = "?"; 78 public string BulletSimVersion = "?";
74 79
75 public Dictionary<uint, BSPhysObject> PhysObjects; 80 private Dictionary<uint, BSCharacter> m_avatars = new Dictionary<uint, BSCharacter>();
76 public BSShapeCollection Shapes; 81 private Dictionary<uint, BSPrim> m_prims = new Dictionary<uint, BSPrim>();
77 82 private HashSet<BSCharacter> m_avatarsWithCollisions = new HashSet<BSCharacter>();
78 // Keeping track of the objects with collisions so we can report begin and end of a collision 83 private HashSet<BSPrim> m_primsWithCollisions = new HashSet<BSPrim>();
79 public HashSet<BSPhysObject> ObjectsWithCollisions = new HashSet<BSPhysObject>(); 84 private List<BSPrim> m_vehicles = new List<BSPrim>();
80 public HashSet<BSPhysObject> ObjectsWithNoMoreCollisions = new HashSet<BSPhysObject>(); 85 private float[] m_heightMap;
81 // Keep track of all the avatars so we can send them a collision event 86 private float m_waterLevel;
82 // every tick so OpenSim will update its animation. 87 private uint m_worldID;
83 private HashSet<BSPhysObject> m_avatars = new HashSet<BSPhysObject>(); 88 public uint WorldID { get { return m_worldID; } }
84
85 // List of all the objects that have vehicle properties and should be called
86 // to update each physics step.
87 private List<BSPhysObject> m_vehicles = new List<BSPhysObject>();
88 89
89 // let my minuions use my logger 90 // let my minuions use my logger
90 public ILog Logger { get { return m_log; } } 91 public ILog Logger { get { return m_log; } }
91 92
92 public IMesher mesher; 93 private bool m_initialized = false;
93 // Level of Detail values kept as float because that's what the Meshmerizer wants
94 public float MeshLOD { get; private set; }
95 public float MeshMegaPrimLOD { get; private set; }
96 public float MeshMegaPrimThreshold { get; private set; }
97 public float SculptLOD { get; private set; }
98 94
99 public uint WorldID { get; private set; } 95 private int m_detailedStatsStep = 0;
100 public BulletSim World { get; private set; } 96
97 public IMesher mesher;
98 private float m_meshLOD;
99 public float MeshLOD
100 {
101 get { return m_meshLOD; }
102 }
103 private float m_sculptLOD;
104 public float SculptLOD
105 {
106 get { return m_sculptLOD; }
107 }
101 108
102 // All the constraints that have been allocated in this instance. 109 private BulletSim m_worldSim;
103 public BSConstraintCollection Constraints { get; private set; } 110 public BulletSim World
111 {
112 get { return m_worldSim; }
113 }
114 private BSConstraintCollection m_constraintCollection;
115 public BSConstraintCollection Constraints
116 {
117 get { return m_constraintCollection; }
118 }
104 119
105 // Simulation parameters
106 private int m_maxSubSteps; 120 private int m_maxSubSteps;
107 private float m_fixedTimeStep; 121 private float m_fixedTimeStep;
108 private long m_simulationStep = 0; 122 private long m_simulationStep = 0;
109 public long SimulationStep { get { return m_simulationStep; } } 123 public long SimulationStep { get { return m_simulationStep; } }
110 private int m_taintsToProcessPerStep; 124
125 public float LastSimulatedTimestep { get; private set; }
111 126
112 // A value of the time now so all the collision and update routines do not have to get their own 127 // A value of the time now so all the collision and update routines do not have to get their own
113 // Set to 'now' just before all the prims and actors are called for collisions and updates 128 // Set to 'now' just before all the prims and actors are called for collisions and updates
114 public int SimulationNowTime { get; private set; } 129 private int m_simulationNowTime;
115 130 public int SimulationNowTime { get { return m_simulationNowTime; } }
116 // True if initialized and ready to do simulation steps
117 private bool m_initialized = false;
118
119 // Flag which is true when processing taints.
120 // Not guaranteed to be correct all the time (don't depend on this) but good for debugging.
121 public bool InTaintTime { get; private set; }
122 131
123 // Pinned memory used to pass step information between managed and unmanaged
124 private int m_maxCollisionsPerFrame; 132 private int m_maxCollisionsPerFrame;
125 private CollisionDesc[] m_collisionArray; 133 private CollisionDesc[] m_collisionArray;
126 private GCHandle m_collisionArrayPinnedHandle; 134 private GCHandle m_collisionArrayPinnedHandle;
@@ -129,19 +137,14 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
129 private EntityProperties[] m_updateArray; 137 private EntityProperties[] m_updateArray;
130 private GCHandle m_updateArrayPinnedHandle; 138 private GCHandle m_updateArrayPinnedHandle;
131 139
132 public bool ShouldMeshSculptedPrim { get; private set; } // cause scuplted prims to get meshed 140 private bool _meshSculptedPrim = true; // cause scuplted prims to get meshed
133 public bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes 141 private bool _forceSimplePrimMeshing = false; // if a cube or sphere, let Bullet do internal shapes
134 public bool ShouldUseHullsForPhysicalObjects { get; private set; } // 'true' if should create hulls for physical objects
135 142
136 public float PID_D { get; private set; } // derivative 143 public float PID_D { get; private set; } // derivative
137 public float PID_P { get; private set; } // proportional 144 public float PID_P { get; private set; } // proportional
138 145
139 public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero 146 public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero
140 public const uint GROUNDPLANE_ID = 1; 147 public const uint GROUNDPLANE_ID = 1;
141 public const uint CHILDTERRAIN_ID = 2; // Terrain allocated based on our mega-prim childre start here
142
143 private float m_waterLevel;
144 public BSTerrainManager TerrainManager { get; private set; }
145 148
146 public ConfigurationParameters Params 149 public ConfigurationParameters Params
147 { 150 {
@@ -151,18 +154,13 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
151 { 154 {
152 get { return new Vector3(0f, 0f, Params.gravity); } 155 get { return new Vector3(0f, 0f, Params.gravity); }
153 } 156 }
154 // Just the Z value of the gravity 157
155 public float DefaultGravityZ 158 private float m_maximumObjectMass;
159 public float MaximumObjectMass
156 { 160 {
157 get { return Params.gravity; } 161 get { return m_maximumObjectMass; }
158 } 162 }
159 163
160 public float MaximumObjectMass { get; private set; }
161
162 // When functions in the unmanaged code must be called, it is only
163 // done at a known time just before the simulation step. The taint
164 // system saves all these function calls and executes them in
165 // order before the simulation.
166 public delegate void TaintCallback(); 164 public delegate void TaintCallback();
167 private struct TaintCallbackEntry 165 private struct TaintCallbackEntry
168 { 166 {
@@ -174,19 +172,15 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
174 callback = c; 172 callback = c;
175 } 173 }
176 } 174 }
177 private Object _taintLock = new Object(); // lock for using the next object 175 private List<TaintCallbackEntry> _taintedObjects;
178 private List<TaintCallbackEntry> _taintOperations; 176 private Object _taintLock = new Object();
179 private Dictionary<string, TaintCallbackEntry> _postTaintOperations;
180 private List<TaintCallbackEntry> _postStepOperations;
181 177
182 // A pointer to an instance if this structure is passed to the C++ code 178 // A pointer to an instance if this structure is passed to the C++ code
183 // Used to pass basic configuration values to the unmanaged code.
184 ConfigurationParameters[] m_params; 179 ConfigurationParameters[] m_params;
185 GCHandle m_paramsHandle; 180 GCHandle m_paramsHandle;
186 181
187 // Handle to the callback used by the unmanaged code to call into the managed code. 182 public bool ShouldDebugLog { get; private set; }
188 // Used for debug logging. 183
189 // Need to store the handle in a persistant variable so it won't be freed.
190 private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle; 184 private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle;
191 185
192 // Sometimes you just have to log everything. 186 // Sometimes you just have to log everything.
@@ -195,26 +189,17 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
195 private string m_physicsLoggingDir; 189 private string m_physicsLoggingDir;
196 private string m_physicsLoggingPrefix; 190 private string m_physicsLoggingPrefix;
197 private int m_physicsLoggingFileMinutes; 191 private int m_physicsLoggingFileMinutes;
198 // 'true' of the vehicle code is to log lots of details
199 public bool VehicleLoggingEnabled { get; private set; }
200 192
201 #region Construction and Initialization 193 private bool m_vehicleLoggingEnabled;
194 public bool VehicleLoggingEnabled { get { return m_vehicleLoggingEnabled; } }
195
202 public BSScene(string identifier) 196 public BSScene(string identifier)
203 { 197 {
204 m_initialized = false; 198 m_initialized = false;
205 // we are passed the name of the region we're working for.
206 RegionName = identifier;
207 } 199 }
208 200
209 public override void Initialise(IMesher meshmerizer, IConfigSource config) 201 public override void Initialise(IMesher meshmerizer, IConfigSource config)
210 { 202 {
211 mesher = meshmerizer;
212 _taintOperations = new List<TaintCallbackEntry>();
213 _postTaintOperations = new Dictionary<string, TaintCallbackEntry>();
214 _postStepOperations = new List<TaintCallbackEntry>();
215 PhysObjects = new Dictionary<uint, BSPhysObject>();
216 Shapes = new BSShapeCollection(this);
217
218 // Allocate pinned memory to pass parameters. 203 // Allocate pinned memory to pass parameters.
219 m_params = new ConfigurationParameters[1]; 204 m_params = new ConfigurationParameters[1];
220 m_paramsHandle = GCHandle.Alloc(m_params, GCHandleType.Pinned); 205 m_paramsHandle = GCHandle.Alloc(m_params, GCHandleType.Pinned);
@@ -230,7 +215,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
230 215
231 // Enable very detailed logging. 216 // Enable very detailed logging.
232 // By creating an empty logger when not logging, the log message invocation code 217 // By creating an empty logger when not logging, the log message invocation code
233 // can be left in and every call doesn't have to check for null. 218 // can be left in and every call doesn't have to check for null.
234 if (m_physicsLoggingEnabled) 219 if (m_physicsLoggingEnabled)
235 { 220 {
236 PhysicsLogging = new Logging.LogWriter(m_physicsLoggingDir, m_physicsLoggingPrefix, m_physicsLoggingFileMinutes); 221 PhysicsLogging = new Logging.LogWriter(m_physicsLoggingDir, m_physicsLoggingPrefix, m_physicsLoggingFileMinutes);
@@ -240,43 +225,39 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
240 PhysicsLogging = new Logging.LogWriter(); 225 PhysicsLogging = new Logging.LogWriter();
241 } 226 }
242 227
243 // If Debug logging level, enable logging from the unmanaged code 228 // Get the version of the DLL
244 m_DebugLogCallbackHandle = null; 229 // TODO: this doesn't work yet. Something wrong with marshaling the returned string.
230 // BulletSimVersion = BulletSimAPI.GetVersion();
231 // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion);
232
233 // if Debug, enable logging from the unmanaged code
245 if (m_log.IsDebugEnabled || PhysicsLogging.Enabled) 234 if (m_log.IsDebugEnabled || PhysicsLogging.Enabled)
246 { 235 {
247 m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader); 236 m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader);
248 if (PhysicsLogging.Enabled) 237 if (PhysicsLogging.Enabled)
249 // The handle is saved in a variable to make sure it doesn't get freed after this call
250 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLoggerPhysLog); 238 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLoggerPhysLog);
251 else 239 else
252 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger); 240 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger);
241 // the handle is saved in a variable to make sure it doesn't get freed after this call
242 BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle);
253 } 243 }
254 244
255 // Get the version of the DLL 245 _taintedObjects = new List<TaintCallbackEntry>();
256 // TODO: this doesn't work yet. Something wrong with marshaling the returned string.
257 // BulletSimVersion = BulletSimAPI.GetVersion();
258 // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion);
259 246
260 // The bounding box for the simulated world. The origin is 0,0,0 unless we're 247 mesher = meshmerizer;
261 // a child in a mega-region. 248 // The bounding box for the simulated world
262 // Bullet actually doesn't care about the extents of the simulated 249 Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, 8192f);
263 // area. It tracks active objects no matter where they are.
264 Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
265 250
266 // m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader); 251 // m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader);
267 World = new BulletSim(0, this, BulletSimAPI.Initialize2(worldExtent, m_paramsHandle.AddrOfPinnedObject(), 252 m_worldID = BulletSimAPI.Initialize(worldExtent, m_paramsHandle.AddrOfPinnedObject(),
268 m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(), 253 m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(),
269 m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject(), 254 m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject());
270 m_DebugLogCallbackHandle));
271
272 Constraints = new BSConstraintCollection(World);
273 255
274 TerrainManager = new BSTerrainManager(this); 256 // Initialization to support the transition to a new API which puts most of the logic
275 TerrainManager.CreateInitialGroundPlaneAndTerrain(); 257 // into the C# code so it is easier to modify and add to.
258 m_worldSim = new BulletSim(m_worldID, this, BulletSimAPI.GetSimHandle2(m_worldID));
259 m_constraintCollection = new BSConstraintCollection(World);
276 260
277 m_log.WarnFormat("{0} Linksets implemented with {1}", LogHeader, (BSLinkset.LinksetImplementation)Params.linksetImplementation);
278
279 InTaintTime = false;
280 m_initialized = true; 261 m_initialized = true;
281 } 262 }
282 263
@@ -300,13 +281,10 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
300 // Very detailed logging for physics debugging 281 // Very detailed logging for physics debugging
301 m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false); 282 m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false);
302 m_physicsLoggingDir = pConfig.GetString("PhysicsLoggingDir", "."); 283 m_physicsLoggingDir = pConfig.GetString("PhysicsLoggingDir", ".");
303 m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-%REGIONNAME%-"); 284 m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-");
304 m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5); 285 m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5);
305 // Very detailed logging for vehicle debugging 286 // Very detailed logging for vehicle debugging
306 VehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false); 287 m_vehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false);
307
308 // Do any replacements in the parameters
309 m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName);
310 } 288 }
311 } 289 }
312 } 290 }
@@ -331,50 +309,12 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
331 { 309 {
332 m_log.Debug("[BULLETS UNMANAGED]:" + msg); 310 m_log.Debug("[BULLETS UNMANAGED]:" + msg);
333 } 311 }
334 312
335 // Called directly from unmanaged code so don't do much 313 // Called directly from unmanaged code so don't do much
336 private void BulletLoggerPhysLog(string msg) 314 private void BulletLoggerPhysLog(string msg)
337 { 315 {
338 DetailLog("[BULLETS UNMANAGED]:" + msg); 316 PhysicsLogging.Write("[BULLETS UNMANAGED]:" + msg);
339 }
340
341 public override void Dispose()
342 {
343 // m_log.DebugFormat("{0}: Dispose()", LogHeader);
344
345 // make sure no stepping happens while we're deleting stuff
346 m_initialized = false;
347
348 TerrainManager.ReleaseGroundPlaneAndTerrain();
349
350 foreach (KeyValuePair<uint, BSPhysObject> kvp in PhysObjects)
351 {
352 kvp.Value.Destroy();
353 }
354 PhysObjects.Clear();
355
356 // Now that the prims are all cleaned up, there should be no constraints left
357 if (Constraints != null)
358 {
359 Constraints.Dispose();
360 Constraints = null;
361 }
362
363 if (Shapes != null)
364 {
365 Shapes.Dispose();
366 Shapes = null;
367 }
368
369 // Anything left in the unmanaged code should be cleaned out
370 BulletSimAPI.Shutdown2(World.ptr);
371
372 // Not logging any more
373 PhysicsLogging.Close();
374 } 317 }
375 #endregion // Construction and Initialization
376
377 #region Prim and Avatar addition and removal
378 318
379 public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying) 319 public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying)
380 { 320 {
@@ -389,13 +329,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
389 if (!m_initialized) return null; 329 if (!m_initialized) return null;
390 330
391 BSCharacter actor = new BSCharacter(localID, avName, this, position, size, isFlying); 331 BSCharacter actor = new BSCharacter(localID, avName, this, position, size, isFlying);
392 lock (PhysObjects) PhysObjects.Add(localID, actor); 332 lock (m_avatars) m_avatars.Add(localID, actor);
393
394 // TODO: Remove kludge someday.
395 // We must generate a collision for avatars whether they collide or not.
396 // This is required by OpenSim to update avatar animations, etc.
397 lock (m_avatars) m_avatars.Add(actor);
398
399 return actor; 333 return actor;
400 } 334 }
401 335
@@ -410,9 +344,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
410 { 344 {
411 try 345 try
412 { 346 {
413 lock (PhysObjects) PhysObjects.Remove(actor.LocalID); 347 lock (m_avatars) m_avatars.Remove(actor.LocalID);
414 // Remove kludge someday
415 lock (m_avatars) m_avatars.Remove(bsactor);
416 } 348 }
417 catch (Exception e) 349 catch (Exception e)
418 { 350 {
@@ -430,11 +362,11 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
430 BSPrim bsprim = prim as BSPrim; 362 BSPrim bsprim = prim as BSPrim;
431 if (bsprim != null) 363 if (bsprim != null)
432 { 364 {
433 DetailLog("{0},RemovePrim,call", bsprim.LocalID); 365 // DetailLog("{0},RemovePrim,call", bsprim.LocalID);
434 // m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID); 366 // m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID);
435 try 367 try
436 { 368 {
437 lock (PhysObjects) PhysObjects.Remove(bsprim.LocalID); 369 lock (m_prims) m_prims.Remove(bsprim.LocalID);
438 } 370 }
439 catch (Exception e) 371 catch (Exception e)
440 { 372 {
@@ -456,21 +388,18 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
456 388
457 if (!m_initialized) return null; 389 if (!m_initialized) return null;
458 390
459 DetailLog("{0},AddPrimShape,call", localID); 391 // DetailLog("{0},AddPrimShape,call", localID);
460 392
461 BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical); 393 BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical);
462 lock (PhysObjects) PhysObjects.Add(localID, prim); 394 lock (m_prims) m_prims.Add(localID, prim);
463 return prim; 395 return prim;
464 } 396 }
465 397
466 // This is a call from the simulator saying that some physical property has been updated. 398 // This is a call from the simulator saying that some physical property has been updated.
467 // The BulletSim driver senses the changing of relevant properties so this taint 399 // The BulletSim driver senses the changing of relevant properties so this taint
468 // information call is not needed. 400 // information call is not needed.
469 public override void AddPhysicsActorTaint(PhysicsActor prim) { } 401 public override void AddPhysicsActorTaint(PhysicsActor prim) { }
470 402
471 #endregion // Prim and Avatar addition and removal
472
473 #region Simulation
474 // Simulate one timestep 403 // Simulate one timestep
475 public override float Simulate(float timeStep) 404 public override float Simulate(float timeStep)
476 { 405 {
@@ -479,45 +408,34 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
479 int collidersCount = 0; 408 int collidersCount = 0;
480 IntPtr collidersPtr; 409 IntPtr collidersPtr;
481 410
482 int beforeTime = 0; 411 LastSimulatedTimestep = timeStep;
483 int simTime = 0;
484 412
485 // prevent simulation until we've been initialized 413 // prevent simulation until we've been initialized
486 if (!m_initialized) return 5.0f; 414 if (!m_initialized) return 10.0f;
415
416 int simulateStartTime = Util.EnvironmentTickCount();
487 417
488 // update the prim states while we know the physics engine is not busy 418 // update the prim states while we know the physics engine is not busy
489 int numTaints = _taintOperations.Count;
490 ProcessTaints(); 419 ProcessTaints();
491 420
492 // Some of the prims operate with special vehicle properties 421 // Some of the prims operate with special vehicle properties
493 ProcessVehicles(timeStep); 422 ProcessVehicles(timeStep);
494 numTaints += _taintOperations.Count;
495 ProcessTaints(); // the vehicles might have added taints 423 ProcessTaints(); // the vehicles might have added taints
496 424
497 // step the physical world one interval 425 // step the physical world one interval
498 m_simulationStep++; 426 m_simulationStep++;
499 int numSubSteps = 0; 427 int numSubSteps = 0;
500
501 try 428 try
502 { 429 {
503 // DumpVehicles(); // DEBUG 430 numSubSteps = BulletSimAPI.PhysicsStep(m_worldID, timeStep, m_maxSubSteps, m_fixedTimeStep,
504 if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount();
505
506 numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep,
507 out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr); 431 out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr);
508 432 // DetailLog("{0},Simulate,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount);
509 if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime);
510 DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}",
511 DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount);
512 // DumpVehicles(); // DEBUG
513 } 433 }
514 catch (Exception e) 434 catch (Exception e)
515 { 435 {
516 m_log.WarnFormat("{0},PhysicsStep Exception: nTaints={1}, substeps={2}, updates={3}, colliders={4}, e={5}", 436 m_log.WarnFormat("{0},PhysicsStep Exception: substeps={1}, updates={2}, colliders={3}, e={4}", LogHeader, numSubSteps, updatedEntityCount, collidersCount, e);
517 LogHeader, numTaints, numSubSteps, updatedEntityCount, collidersCount, e); 437 // DetailLog("{0},PhysicsStepException,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount);
518 DetailLog("{0},PhysicsStepException,call, nTaints={1}, substeps={2}, updates={3}, colliders={4}", 438 // updatedEntityCount = 0;
519 DetailLogZero, numTaints, numSubSteps, updatedEntityCount, collidersCount);
520 updatedEntityCount = 0;
521 collidersCount = 0; 439 collidersCount = 0;
522 } 440 }
523 441
@@ -525,7 +443,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
525 // Don't have to use the pointers passed back since we know it is the same pinned memory we passed in 443 // Don't have to use the pointers passed back since we know it is the same pinned memory we passed in
526 444
527 // Get a value for 'now' so all the collision and update routines don't have to get their own 445 // Get a value for 'now' so all the collision and update routines don't have to get their own
528 SimulationNowTime = Util.EnvironmentTickCount(); 446 m_simulationNowTime = Util.EnvironmentTickCount();
529 447
530 // If there were collisions, process them by sending the event to the prim. 448 // If there were collisions, process them by sending the event to the prim.
531 // Collisions must be processed before updates. 449 // Collisions must be processed before updates.
@@ -544,32 +462,19 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
544 462
545 // The above SendCollision's batch up the collisions on the objects. 463 // The above SendCollision's batch up the collisions on the objects.
546 // Now push the collisions into the simulator. 464 // Now push the collisions into the simulator.
547 if (ObjectsWithCollisions.Count > 0) 465 foreach (BSPrim bsp in m_primsWithCollisions)
548 { 466 bsp.SendCollisions();
549 foreach (BSPhysObject bsp in ObjectsWithCollisions) 467 m_primsWithCollisions.Clear();
550 if (!bsp.SendCollisions()) 468
551 { 469 // This is a kludge to get avatar movement updated.
552 // If the object is done colliding, see that it's removed from the colliding list 470 // Don't send collisions only if there were collisions -- send everytime.
553 ObjectsWithNoMoreCollisions.Add(bsp); 471 // ODE sends collisions even if there are none and this is used to update
554 } 472 // avatar animations and stuff.
555 } 473 // foreach (BSCharacter bsc in m_avatarsWithCollisions)
556 474 // bsc.SendCollisions();
557 // This is a kludge to get avatar movement updates. 475 foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars)
558 // The simulator expects collisions for avatars even if there are have been no collisions. 476 kvp.Value.SendCollisions();
559 // The event updates avatar animations and stuff. 477 m_avatarsWithCollisions.Clear();
560 // If you fix avatar animation updates, remove this overhead and let normal collision processing happen.
561 foreach (BSPhysObject bsp in m_avatars)
562 if (!ObjectsWithCollisions.Contains(bsp)) // don't call avatars twice
563 bsp.SendCollisions();
564
565 // Objects that are done colliding are removed from the ObjectsWithCollisions list.
566 // Not done above because it is inside an iteration of ObjectWithCollisions.
567 if (ObjectsWithNoMoreCollisions.Count > 0)
568 {
569 foreach (BSPhysObject po in ObjectsWithNoMoreCollisions)
570 ObjectsWithCollisions.Remove(po);
571 ObjectsWithNoMoreCollisions.Clear();
572 }
573 478
574 // If any of the objects had updated properties, tell the object it has been changed by the physics engine 479 // If any of the objects had updated properties, tell the object it has been changed by the physics engine
575 if (updatedEntityCount > 0) 480 if (updatedEntityCount > 0)
@@ -577,310 +482,320 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
577 for (int ii = 0; ii < updatedEntityCount; ii++) 482 for (int ii = 0; ii < updatedEntityCount; ii++)
578 { 483 {
579 EntityProperties entprop = m_updateArray[ii]; 484 EntityProperties entprop = m_updateArray[ii];
580 BSPhysObject pobj; 485 BSPrim prim;
581 if (PhysObjects.TryGetValue(entprop.ID, out pobj)) 486 if (m_prims.TryGetValue(entprop.ID, out prim))
487 {
488 prim.UpdateProperties(entprop);
489 continue;
490 }
491 BSCharacter actor;
492 if (m_avatars.TryGetValue(entprop.ID, out actor))
582 { 493 {
583 pobj.UpdateProperties(entprop); 494 actor.UpdateProperties(entprop);
495 continue;
584 } 496 }
585 } 497 }
586 } 498 }
587 499
588 ProcessPostStepTaints(); 500 // If enabled, call into the physics engine to dump statistics
589 501 if (m_detailedStatsStep > 0)
590 // This causes the unmanaged code to output ALL the values found in ALL the objects in the world. 502 {
591 // Only enable this in a limited test world with few objects. 503 if ((m_simulationStep % m_detailedStatsStep) == 0)
592 // BulletSimAPI.DumpAllInfo2(World.ptr); // DEBUG DEBUG DEBUG 504 {
505 BulletSimAPI.DumpBulletStatistics();
506 }
507 }
593 508
594 // The physics engine returns the number of milliseconds it simulated this call. 509 // this is a waste since the outside routine also calcuates the physics simulation
595 // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. 510 // period. TODO: There should be a way of computing physics frames from simulator computation.
596 // We multiply by 55 to give a recognizable running rate (55 or less). 511 // long simulateTotalTime = Util.EnvironmentTickCountSubtract(simulateStartTime);
597 return numSubSteps * m_fixedTimeStep * 1000 * 55; 512 // return (timeStep * (float)simulateTotalTime);
598 // return timeStep * 1000 * 55; 513
514 // TODO: FIX THIS: fps calculation possibly wrong.
515 // This calculation says 1/timeStep is the ideal frame rate. Any time added to
516 // that by the physics simulation gives a slower frame rate.
517 long totalSimulationTime = Util.EnvironmentTickCountSubtract(simulateStartTime);
518 if (totalSimulationTime >= timeStep)
519 return 0;
520 return 1f / (timeStep + totalSimulationTime);
599 } 521 }
600 522
601 // Something has collided 523 // Something has collided
602 private void SendCollision(uint localID, uint collidingWith, Vector3 collidePoint, Vector3 collideNormal, float penetration) 524 private void SendCollision(uint localID, uint collidingWith, Vector3 collidePoint, Vector3 collideNormal, float penitration)
603 { 525 {
604 if (localID <= TerrainManager.HighestTerrainID) 526 if (localID == TERRAIN_ID || localID == GROUNDPLANE_ID)
605 { 527 {
606 return; // don't send collisions to the terrain 528 return; // don't send collisions to the terrain
607 } 529 }
608 530
609 BSPhysObject collider; 531 ActorTypes type = ActorTypes.Prim;
610 if (!PhysObjects.TryGetValue(localID, out collider)) 532 if (collidingWith == TERRAIN_ID || collidingWith == GROUNDPLANE_ID)
611 { 533 type = ActorTypes.Ground;
612 // If the object that is colliding cannot be found, just ignore the collision. 534 else if (m_avatars.ContainsKey(collidingWith))
613 DetailLog("{0},BSScene.SendCollision,colliderNotInObjectList,id={1},with={2}", DetailLogZero, localID, collidingWith); 535 type = ActorTypes.Agent;
536
537 BSPrim prim;
538 if (m_prims.TryGetValue(localID, out prim)) {
539 prim.Collide(collidingWith, type, collidePoint, collideNormal, penitration);
540 m_primsWithCollisions.Add(prim);
614 return; 541 return;
615 } 542 }
616 543 BSCharacter actor;
617 // The terrain is not in the physical object list so 'collidee' can be null when Collide() is called. 544 if (m_avatars.TryGetValue(localID, out actor)) {
618 BSPhysObject collidee = null; 545 actor.Collide(collidingWith, type, collidePoint, collideNormal, penitration);
619 PhysObjects.TryGetValue(collidingWith, out collidee); 546 m_avatarsWithCollisions.Add(actor);
620 547 return;
621 // DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith);
622
623 if (collider.Collide(collidingWith, collidee, collidePoint, collideNormal, penetration))
624 {
625 // If a collision was posted, remember to send it to the simulator
626 ObjectsWithCollisions.Add(collider);
627 } 548 }
628
629 return; 549 return;
630 } 550 }
631 551
632 #endregion // Simulation
633
634 public override void GetResults() { } 552 public override void GetResults() { }
635 553
636 #region Terrain
637
638 public override void SetTerrain(float[] heightMap) { 554 public override void SetTerrain(float[] heightMap) {
639 TerrainManager.SetTerrain(heightMap); 555 m_heightMap = heightMap;
556 this.TaintedObject("BSScene.SetTerrain", delegate()
557 {
558 BulletSimAPI.SetHeightmap(m_worldID, m_heightMap);
559 });
640 } 560 }
641 561
642 public override void SetWaterLevel(float baseheight) 562 // Someday we will have complex terrain with caves and tunnels
563 // For the moment, it's flat and convex
564 public float GetTerrainHeightAtXYZ(Vector3 loc)
643 { 565 {
644 m_waterLevel = baseheight; 566 return GetTerrainHeightAtXY(loc.X, loc.Y);
645 }
646 // Someday....
647 public float GetWaterLevelAtXYZ(Vector3 loc)
648 {
649 return m_waterLevel;
650 } 567 }
651 568
652 public override void DeleteTerrain() 569 public float GetTerrainHeightAtXY(float tX, float tY)
653 { 570 {
654 // m_log.DebugFormat("{0}: DeleteTerrain()", LogHeader); 571 if (tX < 0 || tX >= Constants.RegionSize || tY < 0 || tY >= Constants.RegionSize)
572 return 30;
573 return m_heightMap[((int)tX) * Constants.RegionSize + ((int)tY)];
655 } 574 }
656 575
657 // Although no one seems to check this, I do support combining. 576 public override void SetWaterLevel(float baseheight)
658 public override bool SupportsCombining()
659 { 577 {
660 return TerrainManager.SupportsCombining(); 578 m_waterLevel = baseheight;
579 // TODO: pass to physics engine so things will float?
661 } 580 }
662 // This call says I am a child to region zero in a mega-region. 'pScene' is that 581 public float GetWaterLevel()
663 // of region zero, 'offset' is my offset from regions zero's origin, and
664 // 'extents' is the largest XY that is handled in my region.
665 public override void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents)
666 { 582 {
667 TerrainManager.Combine(pScene, offset, extents); 583 return m_waterLevel;
668 } 584 }
669 585
670 // Unhook all the combining that I know about. 586 public override void DeleteTerrain()
671 public override void UnCombine(PhysicsScene pScene)
672 { 587 {
673 TerrainManager.UnCombine(pScene); 588 // m_log.DebugFormat("{0}: DeleteTerrain()", LogHeader);
674 } 589 }
675 590
676 #endregion // Terrain 591 public override void Dispose()
677
678 public override Dictionary<uint, float> GetTopColliders()
679 { 592 {
680 return new Dictionary<uint, float>(); 593 // m_log.DebugFormat("{0}: Dispose()", LogHeader);
681 }
682 594
683 public override bool IsThreaded { get { return false; } } 595 // make sure no stepping happens while we're deleting stuff
596 m_initialized = false;
684 597
685 #region Taints 598 foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars)
599 {
600 kvp.Value.Destroy();
601 }
602 m_avatars.Clear();
686 603
687 // Calls to the PhysicsActors can't directly call into the physics engine 604 foreach (KeyValuePair<uint, BSPrim> kvp in m_prims)
688 // because it might be busy. We delay changes to a known time. 605 {
689 // We rely on C#'s closure to save and restore the context for the delegate. 606 kvp.Value.Destroy();
690 public void TaintedObject(String ident, TaintCallback callback) 607 }
691 { 608 m_prims.Clear();
692 if (!m_initialized) return;
693 609
694 lock (_taintLock) 610 // Now that the prims are all cleaned up, there should be no constraints left
611 if (m_constraintCollection != null)
695 { 612 {
696 _taintOperations.Add(new TaintCallbackEntry(ident, callback)); 613 m_constraintCollection.Dispose();
614 m_constraintCollection = null;
697 } 615 }
698 616
699 return; 617 // Anything left in the unmanaged code should be cleaned out
700 } 618 BulletSimAPI.Shutdown(WorldID);
701 619
702 // Sometimes a potentially tainted operation can be used in and out of taint time. 620 // Not logging any more
703 // This routine executes the command immediately if in taint-time otherwise it is queued. 621 PhysicsLogging.Close();
704 public void TaintedObject(bool inTaintTime, string ident, TaintCallback callback)
705 {
706 if (inTaintTime)
707 callback();
708 else
709 TaintedObject(ident, callback);
710 } 622 }
711 623
712 // When someone tries to change a property on a BSPrim or BSCharacter, the object queues 624 public override Dictionary<uint, float> GetTopColliders()
713 // a callback into itself to do the actual property change. That callback is called
714 // here just before the physics engine is called to step the simulation.
715 public void ProcessTaints()
716 { 625 {
717 InTaintTime = true; 626 return new Dictionary<uint, float>();
718 ProcessRegularTaints();
719 ProcessPostTaintTaints();
720 InTaintTime = false;
721 } 627 }
722 628
723 private void ProcessRegularTaints() 629 public override bool IsThreaded { get { return false; } }
630
631 /// <summary>
632 /// Routine to figure out if we need to mesh this prim with our mesher
633 /// </summary>
634 /// <param name="pbs"></param>
635 /// <returns>true if the prim needs meshing</returns>
636 public bool NeedsMeshing(PrimitiveBaseShape pbs)
724 { 637 {
725 if (_taintOperations.Count > 0) // save allocating new list if there is nothing to process 638 // most of this is redundant now as the mesher will return null if it cant mesh a prim
639 // but we still need to check for sculptie meshing being enabled so this is the most
640 // convenient place to do it for now...
641
642 // int iPropertiesNotSupportedDefault = 0;
643
644 if (pbs.SculptEntry && !_meshSculptedPrim)
726 { 645 {
727 int taintCount = m_taintsToProcessPerStep; 646 // Render sculpties as boxes
728 TaintCallbackEntry oneCallback = new TaintCallbackEntry(); 647 return false;
729 while (_taintOperations.Count > 0 && taintCount-- > 0) 648 }
649
650 // if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since Bullet
651 // can use an internal representation for the prim
652 if (!_forceSimplePrimMeshing)
653 {
654 if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
655 || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1
656 && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z))
730 { 657 {
731 bool gotOne = false; 658
732 lock (_taintLock) 659 if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
733 { 660 && pbs.ProfileHollow == 0
734 if (_taintOperations.Count > 0) 661 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
735 { 662 && pbs.PathBegin == 0 && pbs.PathEnd == 0
736 oneCallback = _taintOperations[0]; 663 && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
737 _taintOperations.RemoveAt(0); 664 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
738 gotOne = true; 665 && pbs.PathShearX == 0 && pbs.PathShearY == 0)
739 }
740 }
741 if (gotOne)
742 { 666 {
743 try 667 return false;
744 {
745 DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, oneCallback.ident);
746 oneCallback.callback();
747 }
748 catch (Exception e)
749 {
750 DetailLog("{0},BSScene.ProcessTaints,doTaintException,id={1}", DetailLogZero, oneCallback.ident); // DEBUG DEBUG DEBUG
751 m_log.ErrorFormat("{0}: ProcessTaints: {1}: Exception: {2}", LogHeader, oneCallback.ident, e);
752 }
753 } 668 }
754 } 669 }
755 /* 670 }
756 // swizzle a new list into the list location so we can process what's there 671
757 List<TaintCallbackEntry> oldList; 672 /* TODO: verify that the mesher will now do all these shapes
758 lock (_taintLock) 673 if (pbs.ProfileHollow != 0)
674 iPropertiesNotSupportedDefault++;
675
676 if ((pbs.PathBegin != 0) || pbs.PathEnd != 0)
677 iPropertiesNotSupportedDefault++;
678
679 if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0))
680 iPropertiesNotSupportedDefault++;
681
682 if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0)
683 iPropertiesNotSupportedDefault++;
684
685 if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100))
686 iPropertiesNotSupportedDefault++;
687
688 if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0))
689 iPropertiesNotSupportedDefault++;
690
691 if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
692 iPropertiesNotSupportedDefault++;
693
694 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 && (pbs.Scale.X != pbs.Scale.Y || pbs.Scale.Y != pbs.Scale.Z || pbs.Scale.Z != pbs.Scale.X))
695 iPropertiesNotSupportedDefault++;
696
697 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte) Extrusion.Curve1)
698 iPropertiesNotSupportedDefault++;
699
700 // test for torus
701 if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
702 {
703 if (pbs.PathCurve == (byte)Extrusion.Curve1)
759 { 704 {
760 oldList = _taintedObjects; 705 iPropertiesNotSupportedDefault++;
761 _taintedObjects = new List<TaintCallbackEntry>();
762 } 706 }
763 707 }
764 foreach (TaintCallbackEntry tcbe in oldList) 708 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
709 {
710 if (pbs.PathCurve == (byte)Extrusion.Straight)
765 { 711 {
766 try 712 iPropertiesNotSupportedDefault++;
767 { 713 }
768 DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, tcbe.ident); // DEBUG DEBUG DEBUG 714 // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
769 tcbe.callback(); 715 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
770 } 716 {
771 catch (Exception e) 717 iPropertiesNotSupportedDefault++;
772 {
773 m_log.ErrorFormat("{0}: ProcessTaints: {1}: Exception: {2}", LogHeader, tcbe.ident, e);
774 }
775 } 718 }
776 oldList.Clear();
777 */
778 } 719 }
779 } 720 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
780
781 // Schedule an update to happen after all the regular taints are processed.
782 // Note that new requests for the same operation ("ident") for the same object ("ID")
783 // will replace any previous operation by the same object.
784 public void PostTaintObject(String ident, uint ID, TaintCallback callback)
785 {
786 if (!m_initialized) return;
787
788 string uniqueIdent = ident + "-" + ID.ToString();
789 lock (_taintLock)
790 { 721 {
791 _postTaintOperations[uniqueIdent] = new TaintCallbackEntry(uniqueIdent, callback); 722 if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2)
723 {
724 iPropertiesNotSupportedDefault++;
725 }
792 } 726 }
793 727 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
794 return;
795 }
796
797 private void ProcessPostTaintTaints()
798 {
799 if (_postTaintOperations.Count > 0)
800 { 728 {
801 Dictionary<string, TaintCallbackEntry> oldList; 729 if (pbs.PathCurve == (byte)Extrusion.Straight)
802 lock (_taintLock)
803 { 730 {
804 oldList = _postTaintOperations; 731 iPropertiesNotSupportedDefault++;
805 _postTaintOperations = new Dictionary<string, TaintCallbackEntry>();
806 } 732 }
807 733 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
808 foreach (KeyValuePair<string,TaintCallbackEntry> kvp in oldList)
809 { 734 {
810 try 735 iPropertiesNotSupportedDefault++;
811 {
812 DetailLog("{0},BSScene.ProcessPostTaintTaints,doTaint,id={1}", DetailLogZero, kvp.Key); // DEBUG DEBUG DEBUG
813 kvp.Value.callback();
814 }
815 catch (Exception e)
816 {
817 m_log.ErrorFormat("{0}: ProcessPostTaintTaints: {1}: Exception: {2}", LogHeader, kvp.Key, e);
818 }
819 } 736 }
820 oldList.Clear();
821 } 737 }
738 if (iPropertiesNotSupportedDefault == 0)
739 {
740 return false;
741 }
742 */
743 return true;
822 } 744 }
823 745
824 public void PostStepTaintObject(String ident, TaintCallback callback) 746 // Calls to the PhysicsActors can't directly call into the physics engine
747 // because it might be busy. We delay changes to a known time.
748 // We rely on C#'s closure to save and restore the context for the delegate.
749 public void TaintedObject(String ident, TaintCallback callback)
825 { 750 {
826 if (!m_initialized) return; 751 if (!m_initialized) return;
827 752
828 lock (_taintLock) 753 lock (_taintLock)
829 { 754 _taintedObjects.Add(new TaintCallbackEntry(ident, callback));
830 _postStepOperations.Add(new TaintCallbackEntry(ident, callback));
831 }
832
833 return; 755 return;
834 } 756 }
835 757
836 private void ProcessPostStepTaints() 758 // When someone tries to change a property on a BSPrim or BSCharacter, the object queues
759 // a callback into itself to do the actual property change. That callback is called
760 // here just before the physics engine is called to step the simulation.
761 public void ProcessTaints()
837 { 762 {
838 if (_postStepOperations.Count > 0) 763 if (_taintedObjects.Count > 0) // save allocating new list if there is nothing to process
839 { 764 {
765 // swizzle a new list into the list location so we can process what's there
840 List<TaintCallbackEntry> oldList; 766 List<TaintCallbackEntry> oldList;
841 lock (_taintLock) 767 lock (_taintLock)
842 { 768 {
843 oldList = _postStepOperations; 769 oldList = _taintedObjects;
844 _postStepOperations = new List<TaintCallbackEntry>(); 770 _taintedObjects = new List<TaintCallbackEntry>();
845 } 771 }
846 772
847 foreach (TaintCallbackEntry tcbe in oldList) 773 foreach (TaintCallbackEntry tcbe in oldList)
848 { 774 {
849 try 775 try
850 { 776 {
851 DetailLog("{0},BSScene.ProcessPostStepTaints,doTaint,id={1}", DetailLogZero, tcbe.ident); // DEBUG DEBUG DEBUG
852 tcbe.callback(); 777 tcbe.callback();
853 } 778 }
854 catch (Exception e) 779 catch (Exception e)
855 { 780 {
856 m_log.ErrorFormat("{0}: ProcessPostStepTaints: {1}: Exception: {2}", LogHeader, tcbe.ident, e); 781 m_log.ErrorFormat("{0}: ProcessTaints: {1}: Exception: {2}", LogHeader, tcbe.ident, e);
857 } 782 }
858 } 783 }
859 oldList.Clear(); 784 oldList.Clear();
860 } 785 }
861 } 786 }
862 787
863 public bool AssertInTaintTime(string whereFrom)
864 {
865 if (!InTaintTime)
866 {
867 DetailLog("{0},BSScene.AssertInTaintTime,NOT IN TAINT TIME,Region={1},Where={2}", DetailLogZero, RegionName, whereFrom);
868 m_log.ErrorFormat("{0} NOT IN TAINT TIME!! Region={1}, Where={2}", LogHeader, RegionName, whereFrom);
869 Util.PrintCallStack();
870 }
871 return InTaintTime;
872 }
873
874 #endregion // Taints
875
876 #region Vehicles 788 #region Vehicles
877 789
878 public void VehicleInSceneTypeChanged(BSPrim vehic, Vehicle newType) 790 public void VehicleInSceneTypeChanged(BSPrim vehic, Vehicle newType)
879 { 791 {
880 RemoveVehiclePrim(vehic); 792 if (newType == Vehicle.TYPE_NONE)
881 if (newType != Vehicle.TYPE_NONE)
882 { 793 {
883 // make it so the scene will call us each tick to do vehicle things 794 RemoveVehiclePrim(vehic);
795 }
796 else
797 {
798 // make it so the scene will call us each tick to do vehicle things
884 AddVehiclePrim(vehic); 799 AddVehiclePrim(vehic);
885 } 800 }
886 } 801 }
@@ -912,22 +827,21 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
912 } 827 }
913 828
914 // Some prims have extra vehicle actions 829 // Some prims have extra vehicle actions
915 // Called at taint time! 830 // no locking because only called when physics engine is not busy
916 private void ProcessVehicles(float timeStep) 831 private void ProcessVehicles(float timeStep)
917 { 832 {
918 foreach (BSPhysObject pobj in m_vehicles) 833 foreach (BSPrim prim in m_vehicles)
919 { 834 {
920 pobj.StepVehicle(timeStep); 835 prim.StepVehicle(timeStep);
921 } 836 }
922 } 837 }
923 #endregion Vehicles 838 #endregion Vehicles
924 839
925 #region INI and command line parameter processing 840 #region Parameters
926 841
927 delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val); 842 delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val);
928 delegate float ParamGet(BSScene scene); 843 delegate float ParamGet(BSScene scene);
929 delegate void ParamSet(BSScene scene, string paramName, uint localID, float val); 844 delegate void ParamSet(BSScene scene, string paramName, uint localID, float val);
930 delegate void SetOnObject(BSScene scene, BSPhysObject obj, float val);
931 845
932 private struct ParameterDefn 846 private struct ParameterDefn
933 { 847 {
@@ -937,7 +851,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
937 public ParamUser userParam; // get the value from the configuration file 851 public ParamUser userParam; // get the value from the configuration file
938 public ParamGet getter; // return the current value stored for this parameter 852 public ParamGet getter; // return the current value stored for this parameter
939 public ParamSet setter; // set the current value for this parameter 853 public ParamSet setter; // set the current value for this parameter
940 public SetOnObject onObject; // set the value on an object in the physical domain
941 public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s) 854 public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s)
942 { 855 {
943 name = n; 856 name = n;
@@ -946,17 +859,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
946 userParam = u; 859 userParam = u;
947 getter = g; 860 getter = g;
948 setter = s; 861 setter = s;
949 onObject = null;
950 }
951 public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s, SetOnObject o)
952 {
953 name = n;
954 desc = d;
955 defaultValue = v;
956 userParam = u;
957 getter = g;
958 setter = s;
959 onObject = o;
960 } 862 }
961 } 863 }
962 864
@@ -967,7 +869,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
967 // getters and setters. 869 // getters and setters.
968 // It is easiest to find an existing definition and copy it. 870 // It is easiest to find an existing definition and copy it.
969 // Parameter values are floats. Booleans are converted to a floating value. 871 // Parameter values are floats. Booleans are converted to a floating value.
970 // 872 //
971 // A ParameterDefn() takes the following parameters: 873 // A ParameterDefn() takes the following parameters:
972 // -- the text name of the parameter. This is used for console input and ini file. 874 // -- the text name of the parameter. This is used for console input and ini file.
973 // -- a short text description of the parameter. This shows up in the console listing. 875 // -- a short text description of the parameter. This shows up in the console listing.
@@ -978,7 +880,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
978 // 880 //
979 // The single letter parameters for the delegates are: 881 // The single letter parameters for the delegates are:
980 // s = BSScene 882 // s = BSScene
981 // o = BSPhysObject
982 // p = string parameter name 883 // p = string parameter name
983 // l = localID of referenced object 884 // l = localID of referenced object
984 // v = float value 885 // v = float value
@@ -987,40 +888,25 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
987 { 888 {
988 new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties", 889 new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties",
989 ConfigurationParameters.numericTrue, 890 ConfigurationParameters.numericTrue,
990 (s,cf,p,v) => { s.ShouldMeshSculptedPrim = cf.GetBoolean(p, s.BoolNumeric(v)); }, 891 (s,cf,p,v) => { s._meshSculptedPrim = cf.GetBoolean(p, s.BoolNumeric(v)); },
991 (s) => { return s.NumericBool(s.ShouldMeshSculptedPrim); }, 892 (s) => { return s.NumericBool(s._meshSculptedPrim); },
992 (s,p,l,v) => { s.ShouldMeshSculptedPrim = s.BoolNumeric(v); } ), 893 (s,p,l,v) => { s._meshSculptedPrim = s.BoolNumeric(v); } ),
993 new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects", 894 new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects",
994 ConfigurationParameters.numericFalse, 895 ConfigurationParameters.numericFalse,
995 (s,cf,p,v) => { s.ShouldForceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); }, 896 (s,cf,p,v) => { s._forceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); },
996 (s) => { return s.NumericBool(s.ShouldForceSimplePrimMeshing); }, 897 (s) => { return s.NumericBool(s._forceSimplePrimMeshing); },
997 (s,p,l,v) => { s.ShouldForceSimplePrimMeshing = s.BoolNumeric(v); } ), 898 (s,p,l,v) => { s._forceSimplePrimMeshing = s.BoolNumeric(v); } ),
998 new ParameterDefn("UseHullsForPhysicalObjects", "If true, create hulls for physical objects",
999 ConfigurationParameters.numericTrue,
1000 (s,cf,p,v) => { s.ShouldUseHullsForPhysicalObjects = cf.GetBoolean(p, s.BoolNumeric(v)); },
1001 (s) => { return s.NumericBool(s.ShouldUseHullsForPhysicalObjects); },
1002 (s,p,l,v) => { s.ShouldUseHullsForPhysicalObjects = s.BoolNumeric(v); } ),
1003 899
1004 new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)", 900 new ParameterDefn("MeshLOD", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)",
1005 8f, 901 8f,
1006 (s,cf,p,v) => { s.MeshLOD = (float)cf.GetInt(p, (int)v); }, 902 (s,cf,p,v) => { s.m_meshLOD = cf.GetInt(p, (int)v); },
1007 (s) => { return s.MeshLOD; }, 903 (s) => { return (float)s.m_meshLOD; },
1008 (s,p,l,v) => { s.MeshLOD = v; } ), 904 (s,p,l,v) => { s.m_meshLOD = (int)v; } ),
1009 new ParameterDefn("MeshLevelOfDetailMegaPrim", "Level of detail to render meshes larger than threshold meters", 905 new ParameterDefn("SculptLOD", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)",
1010 16f,
1011 (s,cf,p,v) => { s.MeshMegaPrimLOD = (float)cf.GetInt(p, (int)v); },
1012 (s) => { return s.MeshMegaPrimLOD; },
1013 (s,p,l,v) => { s.MeshMegaPrimLOD = v; } ),
1014 new ParameterDefn("MeshLevelOfDetailMegaPrimThreshold", "Size (in meters) of a mesh before using MeshMegaPrimLOD",
1015 10f,
1016 (s,cf,p,v) => { s.MeshMegaPrimThreshold = (float)cf.GetInt(p, (int)v); },
1017 (s) => { return s.MeshMegaPrimThreshold; },
1018 (s,p,l,v) => { s.MeshMegaPrimThreshold = v; } ),
1019 new ParameterDefn("SculptLevelOfDetail", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)",
1020 32f, 906 32f,
1021 (s,cf,p,v) => { s.SculptLOD = (float)cf.GetInt(p, (int)v); }, 907 (s,cf,p,v) => { s.m_sculptLOD = cf.GetInt(p, (int)v); },
1022 (s) => { return s.SculptLOD; }, 908 (s) => { return (float)s.m_sculptLOD; },
1023 (s,p,l,v) => { s.SculptLOD = v; } ), 909 (s,p,l,v) => { s.m_sculptLOD = (int)v; } ),
1024 910
1025 new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps", 911 new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps",
1026 10f, 912 10f,
@@ -1042,16 +928,11 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1042 (s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); }, 928 (s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); },
1043 (s) => { return (float)s.m_maxUpdatesPerFrame; }, 929 (s) => { return (float)s.m_maxUpdatesPerFrame; },
1044 (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ), 930 (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ),
1045 new ParameterDefn("MaxTaintsToProcessPerStep", "Number of update taints to process before each simulation step",
1046 100f,
1047 (s,cf,p,v) => { s.m_taintsToProcessPerStep = cf.GetInt(p, (int)v); },
1048 (s) => { return (float)s.m_taintsToProcessPerStep; },
1049 (s,p,l,v) => { s.m_taintsToProcessPerStep = (int)v; } ),
1050 new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)", 931 new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)",
1051 10000.01f, 932 10000.01f,
1052 (s,cf,p,v) => { s.MaximumObjectMass = cf.GetFloat(p, v); }, 933 (s,cf,p,v) => { s.m_maximumObjectMass = cf.GetFloat(p, v); },
1053 (s) => { return (float)s.MaximumObjectMass; }, 934 (s) => { return (float)s.m_maximumObjectMass; },
1054 (s,p,l,v) => { s.MaximumObjectMass = v; } ), 935 (s,p,l,v) => { s.m_maximumObjectMass = v; } ),
1055 936
1056 new ParameterDefn("PID_D", "Derivitive factor for motion smoothing", 937 new ParameterDefn("PID_D", "Derivitive factor for motion smoothing",
1057 2200f, 938 2200f,
@@ -1088,118 +969,104 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1088 -9.80665f, 969 -9.80665f,
1089 (s,cf,p,v) => { s.m_params[0].gravity = cf.GetFloat(p, v); }, 970 (s,cf,p,v) => { s.m_params[0].gravity = cf.GetFloat(p, v); },
1090 (s) => { return s.m_params[0].gravity; }, 971 (s) => { return s.m_params[0].gravity; },
1091 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].gravity, p, PhysParameterEntry.APPLY_TO_NONE, v); }, 972 (s,p,l,v) => { s.m_params[0].gravity = v; s.TaintedUpdateParameter(p,l,v); } ),
1092 (s,o,v) => { BulletSimAPI.SetGravity2(s.World.ptr, new Vector3(0f,0f,v)); } ),
1093 973
1094 974
1095 new ParameterDefn("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)", 975 new ParameterDefn("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)",
1096 0f, 976 0f,
1097 (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); }, 977 (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); },
1098 (s) => { return s.m_params[0].linearDamping; }, 978 (s) => { return s.m_params[0].linearDamping; },
1099 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearDamping, p, l, v); }, 979 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearDamping, p, l, v); } ),
1100 (s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, v, v); } ),
1101 new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)", 980 new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)",
1102 0f, 981 0f,
1103 (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); }, 982 (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); },
1104 (s) => { return s.m_params[0].angularDamping; }, 983 (s) => { return s.m_params[0].angularDamping; },
1105 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularDamping, p, l, v); }, 984 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularDamping, p, l, v); } ),
1106 (s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, v, v); } ),
1107 new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static", 985 new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static",
1108 0.2f, 986 0.2f,
1109 (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); }, 987 (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); },
1110 (s) => { return s.m_params[0].deactivationTime; }, 988 (s) => { return s.m_params[0].deactivationTime; },
1111 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].deactivationTime, p, l, v); }, 989 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].deactivationTime, p, l, v); } ),
1112 (s,o,v) => { BulletSimAPI.SetDeactivationTime2(o.PhysBody.ptr, v); } ),
1113 new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static", 990 new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static",
1114 0.8f, 991 0.8f,
1115 (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); }, 992 (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); },
1116 (s) => { return s.m_params[0].linearSleepingThreshold; }, 993 (s) => { return s.m_params[0].linearSleepingThreshold; },
1117 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearSleepingThreshold, p, l, v); }, 994 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearSleepingThreshold, p, l, v); } ),
1118 (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.PhysBody.ptr, v, v); } ),
1119 new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static", 995 new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static",
1120 1.0f, 996 1.0f,
1121 (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); }, 997 (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); },
1122 (s) => { return s.m_params[0].angularSleepingThreshold; }, 998 (s) => { return s.m_params[0].angularSleepingThreshold; },
1123 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularSleepingThreshold, p, l, v); }, 999 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularSleepingThreshold, p, l, v); } ),
1124 (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.PhysBody.ptr, v, v); } ),
1125 new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" , 1000 new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ,
1126 0f, // set to zero to disable 1001 0f, // set to zero to disable
1127 (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); }, 1002 (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); },
1128 (s) => { return s.m_params[0].ccdMotionThreshold; }, 1003 (s) => { return s.m_params[0].ccdMotionThreshold; },
1129 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdMotionThreshold, p, l, v); }, 1004 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdMotionThreshold, p, l, v); } ),
1130 (s,o,v) => { BulletSimAPI.SetCcdMotionThreshold2(o.PhysBody.ptr, v); } ),
1131 new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" , 1005 new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" ,
1132 0f, 1006 0f,
1133 (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); }, 1007 (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); },
1134 (s) => { return s.m_params[0].ccdSweptSphereRadius; }, 1008 (s) => { return s.m_params[0].ccdSweptSphereRadius; },
1135 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); }, 1009 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); } ),
1136 (s,o,v) => { BulletSimAPI.SetCcdSweptSphereRadius2(o.PhysBody.ptr, v); } ),
1137 new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" , 1010 new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" ,
1138 0.1f, 1011 0.1f,
1139 (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); }, 1012 (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); },
1140 (s) => { return s.m_params[0].contactProcessingThreshold; }, 1013 (s) => { return s.m_params[0].contactProcessingThreshold; },
1141 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].contactProcessingThreshold, p, l, v); }, 1014 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].contactProcessingThreshold, p, l, v); } ),
1142 (s,o,v) => { BulletSimAPI.SetContactProcessingThreshold2(o.PhysBody.ptr, v); } ),
1143 1015
1144 new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" , 1016 new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" ,
1145 0.5f, 1017 0.5f,
1146 (s,cf,p,v) => { s.m_params[0].terrainFriction = cf.GetFloat(p, v); }, 1018 (s,cf,p,v) => { s.m_params[0].terrainFriction = cf.GetFloat(p, v); },
1147 (s) => { return s.m_params[0].terrainFriction; }, 1019 (s) => { return s.m_params[0].terrainFriction; },
1148 (s,p,l,v) => { s.m_params[0].terrainFriction = v; /* TODO: set on real terrain */} ), 1020 (s,p,l,v) => { s.m_params[0].terrainFriction = v; s.TaintedUpdateParameter(p,l,v); } ),
1149 new ParameterDefn("TerrainHitFraction", "Distance to measure hit collisions" , 1021 new ParameterDefn("TerrainHitFraction", "Distance to measure hit collisions" ,
1150 0.8f, 1022 0.8f,
1151 (s,cf,p,v) => { s.m_params[0].terrainHitFraction = cf.GetFloat(p, v); }, 1023 (s,cf,p,v) => { s.m_params[0].terrainHitFraction = cf.GetFloat(p, v); },
1152 (s) => { return s.m_params[0].terrainHitFraction; }, 1024 (s) => { return s.m_params[0].terrainHitFraction; },
1153 (s,p,l,v) => { s.m_params[0].terrainHitFraction = v; /* TODO: set on real terrain */ } ), 1025 (s,p,l,v) => { s.m_params[0].terrainHitFraction = v; s.TaintedUpdateParameter(p,l,v); } ),
1154 new ParameterDefn("TerrainRestitution", "Bouncyness" , 1026 new ParameterDefn("TerrainRestitution", "Bouncyness" ,
1155 0f, 1027 0f,
1156 (s,cf,p,v) => { s.m_params[0].terrainRestitution = cf.GetFloat(p, v); }, 1028 (s,cf,p,v) => { s.m_params[0].terrainRestitution = cf.GetFloat(p, v); },
1157 (s) => { return s.m_params[0].terrainRestitution; }, 1029 (s) => { return s.m_params[0].terrainRestitution; },
1158 (s,p,l,v) => { s.m_params[0].terrainRestitution = v; /* TODO: set on real terrain */ } ), 1030 (s,p,l,v) => { s.m_params[0].terrainRestitution = v; s.TaintedUpdateParameter(p,l,v); } ),
1159 new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.", 1031 new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.",
1160 0.2f, 1032 0.5f,
1161 (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); }, 1033 (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); },
1162 (s) => { return s.m_params[0].avatarFriction; }, 1034 (s) => { return s.m_params[0].avatarFriction; },
1163 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarFriction, p, l, v); } ), 1035 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarFriction, p, l, v); } ),
1164 new ParameterDefn("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.",
1165 10f,
1166 (s,cf,p,v) => { s.m_params[0].avatarStandingFriction = cf.GetFloat(p, v); },
1167 (s) => { return s.m_params[0].avatarStandingFriction; },
1168 (s,p,l,v) => { s.m_params[0].avatarStandingFriction = v; } ),
1169 new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.", 1036 new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.",
1170 60f, 1037 60f,
1171 (s,cf,p,v) => { s.m_params[0].avatarDensity = cf.GetFloat(p, v); }, 1038 (s,cf,p,v) => { s.m_params[0].avatarDensity = cf.GetFloat(p, v); },
1172 (s) => { return s.m_params[0].avatarDensity; }, 1039 (s) => { return s.m_params[0].avatarDensity; },
1173 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarDensity, p, l, v); } ), 1040 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarDensity, p, l, v); } ),
1174 new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.", 1041 new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.",
1175 0f, 1042 0f,
1176 (s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); }, 1043 (s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); },
1177 (s) => { return s.m_params[0].avatarRestitution; }, 1044 (s) => { return s.m_params[0].avatarRestitution; },
1178 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarRestitution, p, l, v); } ), 1045 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarRestitution, p, l, v); } ),
1179 new ParameterDefn("AvatarCapsuleRadius", "Radius of space around an avatar", 1046 new ParameterDefn("AvatarCapsuleRadius", "Radius of space around an avatar",
1180 0.37f, 1047 0.37f,
1181 (s,cf,p,v) => { s.m_params[0].avatarCapsuleRadius = cf.GetFloat(p, v); }, 1048 (s,cf,p,v) => { s.m_params[0].avatarCapsuleRadius = cf.GetFloat(p, v); },
1182 (s) => { return s.m_params[0].avatarCapsuleRadius; }, 1049 (s) => { return s.m_params[0].avatarCapsuleRadius; },
1183 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ), 1050 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ),
1184 new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar", 1051 new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar",
1185 1.5f, 1052 1.5f,
1186 (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); }, 1053 (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); },
1187 (s) => { return s.m_params[0].avatarCapsuleHeight; }, 1054 (s) => { return s.m_params[0].avatarCapsuleHeight; },
1188 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ), 1055 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ),
1189 new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions", 1056 new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions",
1190 0.1f, 1057 0.1f,
1191 (s,cf,p,v) => { s.m_params[0].avatarContactProcessingThreshold = cf.GetFloat(p, v); }, 1058 (s,cf,p,v) => { s.m_params[0].avatarContactProcessingThreshold = cf.GetFloat(p, v); },
1192 (s) => { return s.m_params[0].avatarContactProcessingThreshold; }, 1059 (s) => { return s.m_params[0].avatarContactProcessingThreshold; },
1193 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ), 1060 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ),
1194 1061
1195 1062
1196 new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)", 1063 new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
1197 0f, 1064 0f, // zero to disable
1198 (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); }, 1065 (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); },
1199 (s) => { return s.m_params[0].maxPersistantManifoldPoolSize; }, 1066 (s) => { return s.m_params[0].maxPersistantManifoldPoolSize; },
1200 (s,p,l,v) => { s.m_params[0].maxPersistantManifoldPoolSize = v; } ), 1067 (s,p,l,v) => { s.m_params[0].maxPersistantManifoldPoolSize = v; } ),
1201 new ParameterDefn("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)", 1068 new ParameterDefn("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)",
1202 0f, 1069 0f, // zero to disable
1203 (s,cf,p,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = cf.GetFloat(p, v); }, 1070 (s,cf,p,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = cf.GetFloat(p, v); },
1204 (s) => { return s.m_params[0].maxCollisionAlgorithmPoolSize; }, 1071 (s) => { return s.m_params[0].maxCollisionAlgorithmPoolSize; },
1205 (s,p,l,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = v; } ), 1072 (s,p,l,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = v; } ),
@@ -1214,12 +1081,12 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1214 (s) => { return s.m_params[0].shouldForceUpdateAllAabbs; }, 1081 (s) => { return s.m_params[0].shouldForceUpdateAllAabbs; },
1215 (s,p,l,v) => { s.m_params[0].shouldForceUpdateAllAabbs = v; } ), 1082 (s,p,l,v) => { s.m_params[0].shouldForceUpdateAllAabbs = v; } ),
1216 new ParameterDefn("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction", 1083 new ParameterDefn("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction",
1217 ConfigurationParameters.numericTrue, 1084 ConfigurationParameters.numericFalse,
1218 (s,cf,p,v) => { s.m_params[0].shouldRandomizeSolverOrder = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, 1085 (s,cf,p,v) => { s.m_params[0].shouldRandomizeSolverOrder = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1219 (s) => { return s.m_params[0].shouldRandomizeSolverOrder; }, 1086 (s) => { return s.m_params[0].shouldRandomizeSolverOrder; },
1220 (s,p,l,v) => { s.m_params[0].shouldRandomizeSolverOrder = v; } ), 1087 (s,p,l,v) => { s.m_params[0].shouldRandomizeSolverOrder = v; } ),
1221 new ParameterDefn("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands", 1088 new ParameterDefn("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands",
1222 ConfigurationParameters.numericTrue, 1089 ConfigurationParameters.numericFalse,
1223 (s,cf,p,v) => { s.m_params[0].shouldSplitSimulationIslands = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, 1090 (s,cf,p,v) => { s.m_params[0].shouldSplitSimulationIslands = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1224 (s) => { return s.m_params[0].shouldSplitSimulationIslands; }, 1091 (s) => { return s.m_params[0].shouldSplitSimulationIslands; },
1225 (s,p,l,v) => { s.m_params[0].shouldSplitSimulationIslands = v; } ), 1092 (s,p,l,v) => { s.m_params[0].shouldSplitSimulationIslands = v; } ),
@@ -1234,11 +1101,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1234 (s) => { return s.m_params[0].numberOfSolverIterations; }, 1101 (s) => { return s.m_params[0].numberOfSolverIterations; },
1235 (s,p,l,v) => { s.m_params[0].numberOfSolverIterations = v; } ), 1102 (s,p,l,v) => { s.m_params[0].numberOfSolverIterations = v; } ),
1236 1103
1237 new ParameterDefn("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)",
1238 (float)BSLinkset.LinksetImplementation.Compound,
1239 (s,cf,p,v) => { s.m_params[0].linksetImplementation = cf.GetFloat(p,v); },
1240 (s) => { return s.m_params[0].linksetImplementation; },
1241 (s,p,l,v) => { s.m_params[0].linksetImplementation = v; } ),
1242 new ParameterDefn("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.", 1104 new ParameterDefn("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.",
1243 ConfigurationParameters.numericFalse, 1105 ConfigurationParameters.numericFalse,
1244 (s,cf,p,v) => { s.m_params[0].linkConstraintUseFrameOffset = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, 1106 (s,cf,p,v) => { s.m_params[0].linkConstraintUseFrameOffset = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
@@ -1259,27 +1121,28 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1259 (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = cf.GetFloat(p, v); }, 1121 (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = cf.GetFloat(p, v); },
1260 (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; }, 1122 (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; },
1261 (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ), 1123 (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ),
1262 new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1", 1124 new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=none, 1=all. Default=0",
1263 0.1f, 1125 0.0f,
1264 (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); }, 1126 (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); },
1265 (s) => { return s.m_params[0].linkConstraintCFM; }, 1127 (s) => { return s.m_params[0].linkConstraintCFM; },
1266 (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ), 1128 (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ),
1267 new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2", 1129 new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2",
1268 0.1f, 1130 0.2f,
1269 (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); }, 1131 (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); },
1270 (s) => { return s.m_params[0].linkConstraintERP; }, 1132 (s) => { return s.m_params[0].linkConstraintERP; },
1271 (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ), 1133 (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ),
1272 new ParameterDefn("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)",
1273 40,
1274 (s,cf,p,v) => { s.m_params[0].linkConstraintSolverIterations = cf.GetFloat(p, v); },
1275 (s) => { return s.m_params[0].linkConstraintSolverIterations; },
1276 (s,p,l,v) => { s.m_params[0].linkConstraintSolverIterations = v; } ),
1277 1134
1278 new ParameterDefn("LogPhysicsStatisticsFrames", "Frames between outputting detailed phys stats. (0 is off)", 1135 new ParameterDefn("DetailedStats", "Frames between outputting detailed phys stats. (0 is off)",
1279 0f, 1136 0f,
1280 (s,cf,p,v) => { s.m_params[0].physicsLoggingFrames = cf.GetInt(p, (int)v); }, 1137 (s,cf,p,v) => { s.m_detailedStatsStep = cf.GetInt(p, (int)v); },
1281 (s) => { return (float)s.m_params[0].physicsLoggingFrames; }, 1138 (s) => { return (float)s.m_detailedStatsStep; },
1282 (s,p,l,v) => { s.m_params[0].physicsLoggingFrames = (int)v; } ), 1139 (s,p,l,v) => { s.m_detailedStatsStep = (int)v; } ),
1140 new ParameterDefn("ShouldDebugLog", "Enables detailed DEBUG log statements",
1141 ConfigurationParameters.numericFalse,
1142 (s,cf,p,v) => { s.ShouldDebugLog = cf.GetBoolean(p, s.BoolNumeric(v)); },
1143 (s) => { return s.NumericBool(s.ShouldDebugLog); },
1144 (s,p,l,v) => { s.ShouldDebugLog = s.BoolNumeric(v); } ),
1145
1283 }; 1146 };
1284 1147
1285 // Convert a boolean to our numeric true and false values 1148 // Convert a boolean to our numeric true and false values
@@ -1337,12 +1200,11 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1337 1200
1338 private PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1]; 1201 private PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1];
1339 1202
1340 // This creates an array in the correct format for returning the list of
1341 // parameters. This is used by the 'list' option of the 'physics' command.
1342 private void BuildParameterTable() 1203 private void BuildParameterTable()
1343 { 1204 {
1344 if (SettableParameters.Length < ParameterDefinitions.Length) 1205 if (SettableParameters.Length < ParameterDefinitions.Length)
1345 { 1206 {
1207
1346 List<PhysParameterEntry> entries = new List<PhysParameterEntry>(); 1208 List<PhysParameterEntry> entries = new List<PhysParameterEntry>();
1347 for (int ii = 0; ii < ParameterDefinitions.Length; ii++) 1209 for (int ii = 0; ii < ParameterDefinitions.Length; ii++)
1348 { 1210 {
@@ -1387,54 +1249,60 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1387 return ret; 1249 return ret;
1388 } 1250 }
1389 1251
1252 // check to see if we are updating a parameter for a particular or all of the prims
1253 protected void UpdateParameterPrims(ref float loc, string parm, uint localID, float val)
1254 {
1255 List<uint> operateOn;
1256 lock (m_prims) operateOn = new List<uint>(m_prims.Keys);
1257 UpdateParameterSet(operateOn, ref loc, parm, localID, val);
1258 }
1259
1260 // check to see if we are updating a parameter for a particular or all of the avatars
1261 protected void UpdateParameterAvatars(ref float loc, string parm, uint localID, float val)
1262 {
1263 List<uint> operateOn;
1264 lock (m_avatars) operateOn = new List<uint>(m_avatars.Keys);
1265 UpdateParameterSet(operateOn, ref loc, parm, localID, val);
1266 }
1267
1390 // update all the localIDs specified 1268 // update all the localIDs specified
1391 // If the local ID is APPLY_TO_NONE, just change the default value 1269 // If the local ID is APPLY_TO_NONE, just change the default value
1392 // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs 1270 // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs
1393 // If the localID is a specific object, apply the parameter change to only that object 1271 // If the localID is a specific object, apply the parameter change to only that object
1394 private void UpdateParameterObject(ref float defaultLoc, string parm, uint localID, float val) 1272 protected void UpdateParameterSet(List<uint> lIDs, ref float defaultLoc, string parm, uint localID, float val)
1395 { 1273 {
1396 List<uint> objectIDs = new List<uint>();
1397 switch (localID) 1274 switch (localID)
1398 { 1275 {
1399 case PhysParameterEntry.APPLY_TO_NONE: 1276 case PhysParameterEntry.APPLY_TO_NONE:
1400 defaultLoc = val; // setting only the default value 1277 defaultLoc = val; // setting only the default value
1401 // This will cause a call into the physical world if some operation is specified (SetOnObject).
1402 objectIDs.Add(TERRAIN_ID);
1403 TaintedUpdateParameter(parm, objectIDs, val);
1404 break; 1278 break;
1405 case PhysParameterEntry.APPLY_TO_ALL: 1279 case PhysParameterEntry.APPLY_TO_ALL:
1406 defaultLoc = val; // setting ALL also sets the default value 1280 defaultLoc = val; // setting ALL also sets the default value
1407 lock (PhysObjects) objectIDs = new List<uint>(PhysObjects.Keys); 1281 List<uint> objectIDs = lIDs;
1408 TaintedUpdateParameter(parm, objectIDs, val); 1282 string xparm = parm.ToLower();
1283 float xval = val;
1284 TaintedObject("BSScene.UpdateParameterSet", delegate() {
1285 foreach (uint lID in objectIDs)
1286 {
1287 BulletSimAPI.UpdateParameter(m_worldID, lID, xparm, xval);
1288 }
1289 });
1409 break; 1290 break;
1410 default: 1291 default:
1411 // setting only one localID 1292 // setting only one localID
1412 objectIDs.Add(localID); 1293 TaintedUpdateParameter(parm, localID, val);
1413 TaintedUpdateParameter(parm, objectIDs, val);
1414 break; 1294 break;
1415 } 1295 }
1416 } 1296 }
1417 1297
1418 // schedule the actual updating of the paramter to when the phys engine is not busy 1298 // schedule the actual updating of the paramter to when the phys engine is not busy
1419 private void TaintedUpdateParameter(string parm, List<uint> lIDs, float val) 1299 protected void TaintedUpdateParameter(string parm, uint localID, float val)
1420 { 1300 {
1301 uint xlocalID = localID;
1302 string xparm = parm.ToLower();
1421 float xval = val; 1303 float xval = val;
1422 List<uint> xlIDs = lIDs; 1304 TaintedObject("BSScene.TaintedUpdateParameter", delegate() {
1423 string xparm = parm; 1305 BulletSimAPI.UpdateParameter(m_worldID, xlocalID, xparm, xval);
1424 TaintedObject("BSScene.UpdateParameterSet", delegate() {
1425 ParameterDefn thisParam;
1426 if (TryGetParameter(xparm, out thisParam))
1427 {
1428 if (thisParam.onObject != null)
1429 {
1430 foreach (uint lID in xlIDs)
1431 {
1432 BSPhysObject theObject = null;
1433 PhysObjects.TryGetValue(lID, out theObject);
1434 thisParam.onObject(this, theObject, xval);
1435 }
1436 }
1437 }
1438 }); 1306 });
1439 } 1307 }
1440 1308
@@ -1458,24 +1326,12 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1458 1326
1459 #endregion Runtime settable parameters 1327 #endregion Runtime settable parameters
1460 1328
1461 // Debugging routine for dumping detailed physical information for vehicle prims
1462 private void DumpVehicles()
1463 {
1464 foreach (BSPrim prim in m_vehicles)
1465 {
1466 BulletSimAPI.DumpRigidBody2(World.ptr, prim.PhysBody.ptr);
1467 BulletSimAPI.DumpCollisionShape2(World.ptr, prim.PhysShape.ptr);
1468 }
1469 }
1470
1471 // Invoke the detailed logger and output something if it's enabled. 1329 // Invoke the detailed logger and output something if it's enabled.
1472 public void DetailLog(string msg, params Object[] args) 1330 public void DetailLog(string msg, params Object[] args)
1473 { 1331 {
1474 PhysicsLogging.Write(msg, args); 1332 PhysicsLogging.Write(msg, args);
1475 // Add the Flush() if debugging crashes. Gets all the messages written out.
1476 PhysicsLogging.Flush();
1477 } 1333 }
1478 // Used to fill in the LocalID when there isn't one. It's the correct number of characters. 1334 // used to fill in the LocalID when there isn't one
1479 public const string DetailLogZero = "0000000000"; 1335 public const string DetailLogZero = "0000000000";
1480 1336
1481} 1337}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
deleted file mode 100755
index 29a23c0..0000000
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ /dev/null
@@ -1,1000 +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 copyrightD
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 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30using OMV = OpenMetaverse;
31using OpenSim.Framework;
32using OpenSim.Region.Physics.Manager;
33using OpenSim.Region.Physics.ConvexDecompositionDotNet;
34
35namespace OpenSim.Region.Physics.BulletSPlugin
36{
37public sealed class BSShapeCollection : IDisposable
38{
39 private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]";
40
41 private BSScene PhysicsScene { get; set; }
42
43 private Object m_collectionActivityLock = new Object();
44
45 // Description of a Mesh
46 private struct MeshDesc
47 {
48 public IntPtr ptr;
49 public int referenceCount;
50 public DateTime lastReferenced;
51 public UInt64 shapeKey;
52 }
53
54 // Description of a hull.
55 // Meshes and hulls have the same shape hash key but we only need hulls for efficient collision calculations.
56 private struct HullDesc
57 {
58 public IntPtr ptr;
59 public int referenceCount;
60 public DateTime lastReferenced;
61 public UInt64 shapeKey;
62 }
63
64 // The sharable set of meshes and hulls. Indexed by their shape hash.
65 private Dictionary<System.UInt64, MeshDesc> Meshes = new Dictionary<System.UInt64, MeshDesc>();
66 private Dictionary<System.UInt64, HullDesc> Hulls = new Dictionary<System.UInt64, HullDesc>();
67
68 public BSShapeCollection(BSScene physScene)
69 {
70 PhysicsScene = physScene;
71 }
72
73 public void Dispose()
74 {
75 // TODO!!!!!!!!!
76 }
77
78 // Callbacks called just before either the body or shape is destroyed.
79 // Mostly used for changing bodies out from under Linksets.
80 // Useful for other cases where parameters need saving.
81 // Passing 'null' says no callback.
82 public delegate void ShapeDestructionCallback(BulletShape shape);
83 public delegate void BodyDestructionCallback(BulletBody body);
84
85 // Called to update/change the body and shape for an object.
86 // First checks the shape and updates that if necessary then makes
87 // sure the body is of the right type.
88 // Return 'true' if either the body or the shape changed.
89 // 'shapeCallback' and 'bodyCallback' are, if non-null, functions called just before
90 // the current shape or body is destroyed. This allows the caller to remove any
91 // higher level dependencies on the shape or body. Mostly used for LinkSets to
92 // remove the physical constraints before the body is destroyed.
93 // Called at taint-time!!
94 public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPhysObject prim,
95 ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback)
96 {
97 PhysicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape");
98
99 bool ret = false;
100
101 // This lock could probably be pushed down lower but building shouldn't take long
102 lock (m_collectionActivityLock)
103 {
104 // Do we have the correct geometry for this type of object?
105 // Updates prim.BSShape with information/pointers to shape.
106 // Returns 'true' of BSShape is changed to a new shape.
107 bool newGeom = CreateGeom(forceRebuild, prim, shapeCallback);
108 // If we had to select a new shape geometry for the object,
109 // rebuild the body around it.
110 // Updates prim.BSBody with information/pointers to requested body
111 // Returns 'true' if BSBody was changed.
112 bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World,
113 prim.PhysShape, bodyCallback);
114 ret = newGeom || newBody;
115 }
116 DetailLog("{0},BSShapeCollection.GetBodyAndShape,taintExit,force={1},ret={2},body={3},shape={4}",
117 prim.LocalID, forceRebuild, ret, prim.PhysBody, prim.PhysShape);
118
119 return ret;
120 }
121
122 // Track another user of a body.
123 // We presume the caller has allocated the body.
124 // Bodies only have one user so the body is just put into the world if not already there.
125 public void ReferenceBody(BulletBody body, bool inTaintTime)
126 {
127 lock (m_collectionActivityLock)
128 {
129 DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body);
130 PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.ReferenceBody", delegate()
131 {
132 if (!BulletSimAPI.IsInWorld2(body.ptr))
133 {
134 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr);
135 DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body);
136 }
137 });
138 }
139 }
140
141 // Release the usage of a body.
142 // Called when releasing use of a BSBody. BSShape is handled separately.
143 public void DereferenceBody(BulletBody body, bool inTaintTime, BodyDestructionCallback bodyCallback )
144 {
145 if (body.ptr == IntPtr.Zero)
146 return;
147
148 lock (m_collectionActivityLock)
149 {
150 PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceBody", delegate()
151 {
152 DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1},inTaintTime={2}",
153 body.ID, body, inTaintTime);
154 // If the caller needs to know the old body is going away, pass the event up.
155 if (bodyCallback != null) bodyCallback(body);
156
157 if (BulletSimAPI.IsInWorld2(body.ptr))
158 {
159 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr);
160 DetailLog("{0},BSShapeCollection.DereferenceBody,removingFromWorld. Body={1}", body.ID, body);
161 }
162
163 // Zero any reference to the shape so it is not freed when the body is deleted.
164 BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero);
165 BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr);
166 });
167 }
168 }
169
170 // Track the datastructures and use count for a shape.
171 // When creating a hull, this is called first to reference the mesh
172 // and then again to reference the hull.
173 // Meshes and hulls for the same shape have the same hash key.
174 // NOTE that native shapes are not added to the mesh list or removed.
175 // Returns 'true' if this is the initial reference to the shape. Otherwise reused.
176 public bool ReferenceShape(BulletShape shape)
177 {
178 bool ret = false;
179 switch (shape.type)
180 {
181 case ShapeData.PhysicsShapeType.SHAPE_MESH:
182 MeshDesc meshDesc;
183 if (Meshes.TryGetValue(shape.shapeKey, out meshDesc))
184 {
185 // There is an existing instance of this mesh.
186 meshDesc.referenceCount++;
187 DetailLog("{0},BSShapeCollection.ReferenceShape,existingMesh,key={1},cnt={2}",
188 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
189 }
190 else
191 {
192 // This is a new reference to a mesh
193 meshDesc.ptr = shape.ptr;
194 meshDesc.shapeKey = shape.shapeKey;
195 // We keep a reference to the underlying IMesh data so a hull can be built
196 meshDesc.referenceCount = 1;
197 DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}",
198 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
199 ret = true;
200 }
201 meshDesc.lastReferenced = System.DateTime.Now;
202 Meshes[shape.shapeKey] = meshDesc;
203 break;
204 case ShapeData.PhysicsShapeType.SHAPE_HULL:
205 HullDesc hullDesc;
206 if (Hulls.TryGetValue(shape.shapeKey, out hullDesc))
207 {
208 // There is an existing instance of this hull.
209 hullDesc.referenceCount++;
210 DetailLog("{0},BSShapeCollection.ReferenceShape,existingHull,key={1},cnt={2}",
211 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
212 }
213 else
214 {
215 // This is a new reference to a hull
216 hullDesc.ptr = shape.ptr;
217 hullDesc.shapeKey = shape.shapeKey;
218 hullDesc.referenceCount = 1;
219 DetailLog("{0},BSShapeCollection.ReferenceShape,newHull,key={1},cnt={2}",
220 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
221 ret = true;
222
223 }
224 hullDesc.lastReferenced = System.DateTime.Now;
225 Hulls[shape.shapeKey] = hullDesc;
226 break;
227 case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN:
228 break;
229 default:
230 // Native shapes are not tracked and they don't go into any list
231 break;
232 }
233 return ret;
234 }
235
236 // Release the usage of a shape.
237 public void DereferenceShape(BulletShape shape, bool inTaintTime, ShapeDestructionCallback shapeCallback)
238 {
239 if (shape.ptr == IntPtr.Zero)
240 return;
241
242 PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceShape", delegate()
243 {
244 if (shape.ptr != IntPtr.Zero)
245 {
246 if (shape.isNativeShape)
247 {
248 // Native shapes are not tracked and are released immediately
249 DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}",
250 BSScene.DetailLogZero, shape.ptr.ToString("X"), inTaintTime);
251 if (shapeCallback != null) shapeCallback(shape);
252 BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr);
253 }
254 else
255 {
256 switch (shape.type)
257 {
258 case ShapeData.PhysicsShapeType.SHAPE_HULL:
259 DereferenceHull(shape, shapeCallback);
260 break;
261 case ShapeData.PhysicsShapeType.SHAPE_MESH:
262 DereferenceMesh(shape, shapeCallback);
263 break;
264 case ShapeData.PhysicsShapeType.SHAPE_COMPOUND:
265 DereferenceCompound(shape, shapeCallback);
266 break;
267 case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN:
268 break;
269 default:
270 break;
271 }
272 }
273 }
274 });
275 }
276
277 // Count down the reference count for a mesh shape
278 // Called at taint-time.
279 private void DereferenceMesh(BulletShape shape, ShapeDestructionCallback shapeCallback)
280 {
281 MeshDesc meshDesc;
282 if (Meshes.TryGetValue(shape.shapeKey, out meshDesc))
283 {
284 meshDesc.referenceCount--;
285 // TODO: release the Bullet storage
286 if (shapeCallback != null) shapeCallback(shape);
287 meshDesc.lastReferenced = System.DateTime.Now;
288 Meshes[shape.shapeKey] = meshDesc;
289 DetailLog("{0},BSShapeCollection.DereferenceMesh,shape={1},refCnt={2}",
290 BSScene.DetailLogZero, shape, meshDesc.referenceCount);
291
292 }
293 }
294
295 // Count down the reference count for a hull shape
296 // Called at taint-time.
297 private void DereferenceHull(BulletShape shape, ShapeDestructionCallback shapeCallback)
298 {
299 HullDesc hullDesc;
300 if (Hulls.TryGetValue(shape.shapeKey, out hullDesc))
301 {
302 hullDesc.referenceCount--;
303 // TODO: release the Bullet storage (aging old entries?)
304
305 // Tell upper layers that, if they have dependencies on this shape, this link is going away
306 if (shapeCallback != null) shapeCallback(shape);
307
308 hullDesc.lastReferenced = System.DateTime.Now;
309 Hulls[shape.shapeKey] = hullDesc;
310 DetailLog("{0},BSShapeCollection.DereferenceHull,shape={1},refCnt={2}",
311 BSScene.DetailLogZero, shape, hullDesc.referenceCount);
312 }
313 }
314
315 // Remove a reference to a compound shape.
316 // Taking a compound shape apart is a little tricky because if you just delete the
317 // physical shape, it will free all the underlying children. We can't do that because
318 // they could be shared. So, this removes each of the children from the compound and
319 // dereferences them separately before destroying the compound collision object itself.
320 // Called at taint-time.
321 private void DereferenceCompound(BulletShape shape, ShapeDestructionCallback shapeCallback)
322 {
323 if (!BulletSimAPI.IsCompound2(shape.ptr))
324 {
325 // Failed the sanity check!!
326 PhysicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}",
327 LogHeader, shape.type, shape.ptr.ToString("X"));
328 DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}",
329 BSScene.DetailLogZero, shape.type, shape.ptr.ToString("X"));
330 return;
331 }
332
333 int numChildren = BulletSimAPI.GetNumberOfCompoundChildren2(shape.ptr);
334 DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}", BSScene.DetailLogZero, shape, numChildren);
335
336 for (int ii = numChildren - 1; ii >= 0; ii--)
337 {
338 IntPtr childShape = BulletSimAPI.RemoveChildShapeFromCompoundShapeIndex2(shape.ptr, ii);
339 DereferenceAnonCollisionShape(childShape);
340 }
341 BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr);
342 }
343
344 // Sometimes we have a pointer to a collision shape but don't know what type it is.
345 // Figure out type and call the correct dereference routine.
346 // Called at taint-time.
347 private void DereferenceAnonCollisionShape(IntPtr cShape)
348 {
349 MeshDesc meshDesc;
350 HullDesc hullDesc;
351
352 BulletShape shapeInfo = new BulletShape(cShape);
353 if (TryGetMeshByPtr(cShape, out meshDesc))
354 {
355 shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_MESH;
356 shapeInfo.shapeKey = meshDesc.shapeKey;
357 }
358 else
359 {
360 if (TryGetHullByPtr(cShape, out hullDesc))
361 {
362 shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_HULL;
363 shapeInfo.shapeKey = hullDesc.shapeKey;
364 }
365 else
366 {
367 if (BulletSimAPI.IsCompound2(cShape))
368 {
369 shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_COMPOUND;
370 }
371 else
372 {
373 if (BulletSimAPI.IsNativeShape2(cShape))
374 {
375 shapeInfo.isNativeShape = true;
376 shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter)
377 }
378 }
379 }
380 }
381
382 DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo);
383
384 if (shapeInfo.type != ShapeData.PhysicsShapeType.SHAPE_UNKNOWN)
385 {
386 DereferenceShape(shapeInfo, true, null);
387 }
388 else
389 {
390 PhysicsScene.Logger.ErrorFormat("{0} Could not decypher shape type. Region={1}, addr={2}",
391 LogHeader, PhysicsScene.RegionName, cShape.ToString("X"));
392 }
393 }
394
395 // Create the geometry information in Bullet for later use.
396 // The objects needs a hull if it's physical otherwise a mesh is enough.
397 // if 'forceRebuild' is true, the geometry is unconditionally rebuilt. For meshes and hulls,
398 // shared geometries will be used. If the parameters of the existing shape are the same
399 // as this request, the shape is not rebuilt.
400 // Info in prim.BSShape is updated to the new shape.
401 // Returns 'true' if the geometry was rebuilt.
402 // Called at taint-time!
403 private bool CreateGeom(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback)
404 {
405 bool ret = false;
406 bool haveShape = false;
407
408 if (!haveShape && prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_AVATAR)
409 {
410 // an avatar capsule is close to a native shape (it is not shared)
411 ret = GetReferenceToNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_AVATAR,
412 ShapeData.FixedShapeKey.KEY_CAPSULE, shapeCallback);
413 DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape);
414 ret = true;
415 haveShape = true;
416 }
417
418 // Compound shapes are handled special as they are rebuilt from scratch.
419 // This isn't too great a hardship since most of the child shapes will already been created.
420 if (!haveShape && prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_COMPOUND)
421 {
422 ret = GetReferenceToCompoundShape(prim, shapeCallback);
423 DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape);
424 haveShape = true;
425 }
426
427 if (!haveShape)
428 {
429 ret = CreateGeomNonSpecial(forceRebuild, prim, shapeCallback);
430 }
431
432 return ret;
433 }
434
435 // Create a mesh/hull shape or a native shape if 'nativeShapePossible' is 'true'.
436 private bool CreateGeomNonSpecial(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback)
437 {
438 bool ret = false;
439 bool haveShape = false;
440 bool nativeShapePossible = true;
441 PrimitiveBaseShape pbs = prim.BaseShape;
442
443 // If the prim attributes are simple, this could be a simple Bullet native shape
444 if (!haveShape
445 && pbs != null
446 && nativeShapePossible
447 && ((pbs.SculptEntry && !PhysicsScene.ShouldMeshSculptedPrim)
448 || (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
449 && pbs.ProfileHollow == 0
450 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
451 && pbs.PathBegin == 0 && pbs.PathEnd == 0
452 && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
453 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
454 && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) )
455 {
456 // It doesn't look like Bullet scales spheres so make sure the scales are all equal
457 if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
458 && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z)
459 {
460 haveShape = true;
461 if (forceRebuild
462 || prim.Scale != prim.Size
463 || prim.PhysShape.type != ShapeData.PhysicsShapeType.SHAPE_SPHERE
464 )
465 {
466 ret = GetReferenceToNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_SPHERE,
467 ShapeData.FixedShapeKey.KEY_SPHERE, shapeCallback);
468 DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}",
469 prim.LocalID, forceRebuild, prim.PhysShape);
470 }
471 }
472 if (!haveShape && pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
473 {
474 haveShape = true;
475 if (forceRebuild
476 || prim.Scale != prim.Size
477 || prim.PhysShape.type != ShapeData.PhysicsShapeType.SHAPE_BOX
478 )
479 {
480 ret = GetReferenceToNativeShape( prim, ShapeData.PhysicsShapeType.SHAPE_BOX,
481 ShapeData.FixedShapeKey.KEY_BOX, shapeCallback);
482 DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}",
483 prim.LocalID, forceRebuild, prim.PhysShape);
484 }
485 }
486 }
487
488 // If a simple shape is not happening, create a mesh and possibly a hull.
489 if (!haveShape && pbs != null)
490 {
491 ret = CreateGeomMeshOrHull(prim, shapeCallback);
492 }
493
494 return ret;
495 }
496
497 public bool CreateGeomMeshOrHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
498 {
499
500 bool ret = false;
501 // Note that if it's a native shape, the check for physical/non-physical is not
502 // made. Native shapes work in either case.
503 if (prim.IsPhysical && PhysicsScene.ShouldUseHullsForPhysicalObjects)
504 {
505 // Update prim.BSShape to reference a hull of this shape.
506 ret = GetReferenceToHull(prim,shapeCallback);
507 DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}",
508 prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
509 }
510 else
511 {
512 ret = GetReferenceToMesh(prim, shapeCallback);
513 DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}",
514 prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
515 }
516 return ret;
517 }
518
519 // Creates a native shape and assignes it to prim.BSShape.
520 // "Native" shapes are never shared. they are created here and destroyed in DereferenceShape().
521 private bool GetReferenceToNativeShape(BSPhysObject prim,
522 ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey,
523 ShapeDestructionCallback shapeCallback)
524 {
525 // release any previous shape
526 DereferenceShape(prim.PhysShape, true, shapeCallback);
527
528 // Bullet native objects are scaled by the Bullet engine so pass the size in
529 prim.Scale = prim.Size;
530
531 BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey);
532
533 // Don't need to do a 'ReferenceShape()' here because native shapes are not shared.
534 DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}",
535 prim.LocalID, newShape, prim.Scale);
536
537 prim.PhysShape = newShape;
538 return true;
539 }
540
541 private BulletShape BuildPhysicalNativeShape(BSPhysObject prim, ShapeData.PhysicsShapeType shapeType,
542 ShapeData.FixedShapeKey shapeKey)
543 {
544 BulletShape newShape;
545 // Need to make sure the passed shape information is for the native type.
546 ShapeData nativeShapeData = new ShapeData();
547 nativeShapeData.Type = shapeType;
548 nativeShapeData.ID = prim.LocalID;
549 nativeShapeData.Scale = prim.Scale;
550 nativeShapeData.Size = prim.Scale;
551 nativeShapeData.MeshKey = (ulong)shapeKey;
552 nativeShapeData.HullKey = (ulong)shapeKey;
553
554 if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR)
555 {
556 newShape = new BulletShape(
557 BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1f, 1f, prim.Scale)
558 , shapeType);
559 DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale);
560 }
561 else
562 {
563 newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, nativeShapeData), shapeType);
564 }
565 if (newShape.ptr == IntPtr.Zero)
566 {
567 PhysicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}",
568 LogHeader, prim.LocalID, shapeType);
569 }
570 newShape.shapeKey = (System.UInt64)shapeKey;
571 newShape.isNativeShape = true;
572
573 return newShape;
574 }
575
576 // Builds a mesh shape in the physical world and updates prim.BSShape.
577 // Dereferences previous shape in BSShape and adds a reference for this new shape.
578 // Returns 'true' of a mesh was actually built. Otherwise .
579 // Called at taint-time!
580 private bool GetReferenceToMesh(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
581 {
582 BulletShape newShape = new BulletShape(IntPtr.Zero);
583
584 float lod;
585 System.UInt64 newMeshKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
586
587 // if this new shape is the same as last time, don't recreate the mesh
588 if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH)
589 return false;
590
591 DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2}",
592 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X"));
593
594 // Since we're recreating new, get rid of the reference to the previous shape
595 DereferenceShape(prim.PhysShape, true, shapeCallback);
596
597 newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, prim.BaseShape, prim.Size, lod);
598 // Take evasive action if the mesh was not constructed.
599 newShape = VerifyMeshCreated(newShape, prim);
600
601 ReferenceShape(newShape);
602
603 // meshes are already scaled by the meshmerizer
604 prim.Scale = new OMV.Vector3(1f, 1f, 1f);
605 prim.PhysShape = newShape;
606
607 return true; // 'true' means a new shape has been added to this prim
608 }
609
610 private BulletShape CreatePhysicalMesh(string objName, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
611 {
612 IMesh meshData = null;
613 IntPtr meshPtr = IntPtr.Zero;
614 MeshDesc meshDesc;
615 if (Meshes.TryGetValue(newMeshKey, out meshDesc))
616 {
617 // If the mesh has already been built just use it.
618 meshPtr = meshDesc.ptr;
619 }
620 else
621 {
622 // Pass false for physicalness as this creates some sort of bounding box which we don't need
623 meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false);
624
625 if (meshData != null)
626 {
627 int[] indices = meshData.getIndexListAsInt();
628 List<OMV.Vector3> vertices = meshData.getVertexList();
629
630 float[] verticesAsFloats = new float[vertices.Count * 3];
631 int vi = 0;
632 foreach (OMV.Vector3 vv in vertices)
633 {
634 verticesAsFloats[vi++] = vv.X;
635 verticesAsFloats[vi++] = vv.Y;
636 verticesAsFloats[vi++] = vv.Z;
637 }
638
639 // m_log.DebugFormat("{0}: BSShapeCollection.CreatePhysicalMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}",
640 // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count);
641
642 meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr,
643 indices.GetLength(0), indices, vertices.Count, verticesAsFloats);
644 }
645 }
646 BulletShape newShape = new BulletShape(meshPtr, ShapeData.PhysicsShapeType.SHAPE_MESH);
647 newShape.shapeKey = newMeshKey;
648
649 return newShape;
650 }
651
652 // See that hull shape exists in the physical world and update prim.BSShape.
653 // We could be creating the hull because scale changed or whatever.
654 private bool GetReferenceToHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
655 {
656 BulletShape newShape;
657
658 float lod;
659 System.UInt64 newHullKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
660
661 // if the hull hasn't changed, don't rebuild it
662 if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL)
663 return false;
664
665 DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}",
666 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X"));
667
668 // Remove usage of the previous shape.
669 DereferenceShape(prim.PhysShape, true, shapeCallback);
670
671 newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, prim.BaseShape, prim.Size, lod);
672 newShape = VerifyMeshCreated(newShape, prim);
673
674 ReferenceShape(newShape);
675
676 // hulls are already scaled by the meshmerizer
677 prim.Scale = new OMV.Vector3(1f, 1f, 1f);
678 prim.PhysShape = newShape;
679 return true; // 'true' means a new shape has been added to this prim
680 }
681
682 List<ConvexResult> m_hulls;
683 private BulletShape CreatePhysicalHull(string objName, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
684 {
685
686 IntPtr hullPtr = IntPtr.Zero;
687 HullDesc hullDesc;
688 if (Hulls.TryGetValue(newHullKey, out hullDesc))
689 {
690 // If the hull shape already is created, just use it.
691 hullPtr = hullDesc.ptr;
692 }
693 else
694 {
695 // Build a new hull in the physical world
696 // Pass false for physicalness as this creates some sort of bounding box which we don't need
697 IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false);
698 if (meshData != null)
699 {
700
701 int[] indices = meshData.getIndexListAsInt();
702 List<OMV.Vector3> vertices = meshData.getVertexList();
703
704 //format conversion from IMesh format to DecompDesc format
705 List<int> convIndices = new List<int>();
706 List<float3> convVertices = new List<float3>();
707 for (int ii = 0; ii < indices.GetLength(0); ii++)
708 {
709 convIndices.Add(indices[ii]);
710 }
711 foreach (OMV.Vector3 vv in vertices)
712 {
713 convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
714 }
715
716 // setup and do convex hull conversion
717 m_hulls = new List<ConvexResult>();
718 DecompDesc dcomp = new DecompDesc();
719 dcomp.mIndices = convIndices;
720 dcomp.mVertices = convVertices;
721 ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
722 // create the hull into the _hulls variable
723 convexBuilder.process(dcomp);
724
725 // Convert the vertices and indices for passing to unmanaged.
726 // The hull information is passed as a large floating point array.
727 // The format is:
728 // convHulls[0] = number of hulls
729 // convHulls[1] = number of vertices in first hull
730 // convHulls[2] = hull centroid X coordinate
731 // convHulls[3] = hull centroid Y coordinate
732 // convHulls[4] = hull centroid Z coordinate
733 // convHulls[5] = first hull vertex X
734 // convHulls[6] = first hull vertex Y
735 // convHulls[7] = first hull vertex Z
736 // convHulls[8] = second hull vertex X
737 // ...
738 // convHulls[n] = number of vertices in second hull
739 // convHulls[n+1] = second hull centroid X coordinate
740 // ...
741 //
742 // TODO: is is very inefficient. Someday change the convex hull generator to return
743 // data structures that do not need to be converted in order to pass to Bullet.
744 // And maybe put the values directly into pinned memory rather than marshaling.
745 int hullCount = m_hulls.Count;
746 int totalVertices = 1; // include one for the count of the hulls
747 foreach (ConvexResult cr in m_hulls)
748 {
749 totalVertices += 4; // add four for the vertex count and centroid
750 totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
751 }
752 float[] convHulls = new float[totalVertices];
753
754 convHulls[0] = (float)hullCount;
755 int jj = 1;
756 foreach (ConvexResult cr in m_hulls)
757 {
758 // copy vertices for index access
759 float3[] verts = new float3[cr.HullVertices.Count];
760 int kk = 0;
761 foreach (float3 ff in cr.HullVertices)
762 {
763 verts[kk++] = ff;
764 }
765
766 // add to the array one hull's worth of data
767 convHulls[jj++] = cr.HullIndices.Count;
768 convHulls[jj++] = 0f; // centroid x,y,z
769 convHulls[jj++] = 0f;
770 convHulls[jj++] = 0f;
771 foreach (int ind in cr.HullIndices)
772 {
773 convHulls[jj++] = verts[ind].x;
774 convHulls[jj++] = verts[ind].y;
775 convHulls[jj++] = verts[ind].z;
776 }
777 }
778 // create the hull data structure in Bullet
779 hullPtr = BulletSimAPI.CreateHullShape2(PhysicsScene.World.ptr, hullCount, convHulls);
780 }
781 }
782
783 BulletShape newShape = new BulletShape(hullPtr, ShapeData.PhysicsShapeType.SHAPE_HULL);
784 newShape.shapeKey = newHullKey;
785
786 return newShape; // 'true' means a new shape has been added to this prim
787 }
788
789 // Callback from convex hull creater with a newly created hull.
790 // Just add it to our collection of hulls for this shape.
791 private void HullReturn(ConvexResult result)
792 {
793 m_hulls.Add(result);
794 return;
795 }
796
797 // Compound shapes are always built from scratch.
798 // This shouldn't be to bad since most of the parts will be meshes that had been built previously.
799 private bool GetReferenceToCompoundShape(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
800 {
801 // Remove reference to the old shape
802 // Don't need to do this as the shape is freed when the new root shape is created below.
803 // DereferenceShape(prim.PhysShape, true, shapeCallback);
804
805 BulletShape cShape = new BulletShape(
806 BulletSimAPI.CreateCompoundShape2(PhysicsScene.World.ptr, false), ShapeData.PhysicsShapeType.SHAPE_COMPOUND);
807
808 // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape.
809 CreateGeomMeshOrHull(prim, shapeCallback);
810 BulletSimAPI.AddChildShapeToCompoundShape2(cShape.ptr, prim.PhysShape.ptr, OMV.Vector3.Zero, OMV.Quaternion.Identity);
811 DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addRootPrim,compShape={1},rootShape={2}",
812 prim.LocalID, cShape, prim.PhysShape);
813
814 prim.PhysShape = cShape;
815
816 return true;
817 }
818
819 // Create a hash of all the shape parameters to be used as a key
820 // for this particular shape.
821 private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod)
822 {
823 // level of detail based on size and type of the object
824 float lod = PhysicsScene.MeshLOD;
825 if (pbs.SculptEntry)
826 lod = PhysicsScene.SculptLOD;
827
828 // Mega prims usually get more detail because one can interact with shape approximations at this size.
829 float maxAxis = Math.Max(size.X, Math.Max(size.Y, size.Z));
830 if (maxAxis > PhysicsScene.MeshMegaPrimThreshold)
831 lod = PhysicsScene.MeshMegaPrimLOD;
832
833 retLod = lod;
834 return pbs.GetMeshKey(size, lod);
835 }
836 // For those who don't want the LOD
837 private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs)
838 {
839 float lod;
840 return ComputeShapeKey(size, pbs, out lod);
841 }
842
843 // The creation of a mesh or hull can fail if an underlying asset is not available.
844 // There are two cases: 1) the asset is not in the cache and it needs to be fetched;
845 // and 2) the asset cannot be converted (like failed decompression of JPEG2000s).
846 // The first case causes the asset to be fetched. The second case requires
847 // us to not loop forever.
848 // Called after creating a physical mesh or hull. If the physical shape was created,
849 // just return.
850 private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim)
851 {
852 // If the shape was successfully created, nothing more to do
853 if (newShape.ptr != IntPtr.Zero)
854 return newShape;
855
856 // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset
857 if (prim.BaseShape.SculptEntry && !prim.LastAssetBuildFailed && prim.BaseShape.SculptTexture != OMV.UUID.Zero)
858 {
859 prim.LastAssetBuildFailed = true;
860 BSPhysObject xprim = prim;
861 DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset,lID={1},lastFailed={2}",
862 LogHeader, prim.LocalID, prim.LastAssetBuildFailed);
863 Util.FireAndForget(delegate
864 {
865 RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod;
866 if (assetProvider != null)
867 {
868 BSPhysObject yprim = xprim; // probably not necessary, but, just in case.
869 assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset)
870 {
871 if (!yprim.BaseShape.SculptEntry)
872 return;
873 if (yprim.BaseShape.SculptTexture.ToString() != asset.ID)
874 return;
875
876 yprim.BaseShape.SculptData = asset.Data;
877 // This will cause the prim to see that the filler shape is not the right
878 // one and try again to build the object.
879 // No race condition with the normal shape setting since the rebuild is at taint time.
880 yprim.ForceBodyShapeRebuild(false);
881
882 });
883 }
884 });
885 }
886 else
887 {
888 if (prim.LastAssetBuildFailed)
889 {
890 PhysicsScene.Logger.ErrorFormat("{0} Mesh failed to fetch asset. lID={1}, texture={2}",
891 LogHeader, prim.LocalID, prim.BaseShape.SculptTexture);
892 }
893 }
894
895 // While we figure out the real problem, stick a simple native shape on the object.
896 BulletShape fillinShape =
897 BuildPhysicalNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_BOX, ShapeData.FixedShapeKey.KEY_BOX);
898
899 return fillinShape;
900 }
901
902 // Create a body object in Bullet.
903 // Updates prim.BSBody with the information about the new body if one is created.
904 // Returns 'true' if an object was actually created.
905 // Called at taint-time.
906 private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletSim sim, BulletShape shape,
907 BodyDestructionCallback bodyCallback)
908 {
909 bool ret = false;
910
911 // the mesh, hull or native shape must have already been created in Bullet
912 bool mustRebuild = (prim.PhysBody.ptr == IntPtr.Zero);
913
914 // If there is an existing body, verify it's of an acceptable type.
915 // If not a solid object, body is a GhostObject. Otherwise a RigidBody.
916 if (!mustRebuild)
917 {
918 CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(prim.PhysBody.ptr);
919 if (prim.IsSolid && bodyType != CollisionObjectTypes.CO_RIGID_BODY
920 || !prim.IsSolid && bodyType != CollisionObjectTypes.CO_GHOST_OBJECT)
921 {
922 // If the collisionObject is not the correct type for solidness, rebuild what's there
923 mustRebuild = true;
924 }
925 }
926
927 if (mustRebuild || forceRebuild)
928 {
929 // Free any old body
930 DereferenceBody(prim.PhysBody, true, bodyCallback);
931
932 BulletBody aBody;
933 IntPtr bodyPtr = IntPtr.Zero;
934 if (prim.IsSolid)
935 {
936 bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr,
937 prim.LocalID, prim.RawPosition, prim.RawOrientation);
938 DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X"));
939 }
940 else
941 {
942 bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr,
943 prim.LocalID, prim.ForcePosition, prim.ForceOrientation);
944 DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X"));
945 }
946 aBody = new BulletBody(prim.LocalID, bodyPtr);
947
948 ReferenceBody(aBody, true);
949
950 prim.PhysBody = aBody;
951
952 ret = true;
953 }
954
955 return ret;
956 }
957
958 private bool TryGetMeshByPtr(IntPtr addr, out MeshDesc outDesc)
959 {
960 bool ret = false;
961 MeshDesc foundDesc = new MeshDesc();
962 foreach (MeshDesc md in Meshes.Values)
963 {
964 if (md.ptr == addr)
965 {
966 foundDesc = md;
967 ret = true;
968 break;
969 }
970
971 }
972 outDesc = foundDesc;
973 return ret;
974 }
975
976 private bool TryGetHullByPtr(IntPtr addr, out HullDesc outDesc)
977 {
978 bool ret = false;
979 HullDesc foundDesc = new HullDesc();
980 foreach (HullDesc hd in Hulls.Values)
981 {
982 if (hd.ptr == addr)
983 {
984 foundDesc = hd;
985 ret = true;
986 break;
987 }
988
989 }
990 outDesc = foundDesc;
991 return ret;
992 }
993
994 private void DetailLog(string msg, params Object[] args)
995 {
996 if (PhysicsScene.PhysicsLogging.Enabled)
997 PhysicsScene.DetailLog(msg, args);
998 }
999}
1000}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
deleted file mode 100755
index 7c34af2..0000000
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
+++ /dev/null
@@ -1,479 +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 copyrightD
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 */
27using System;
28using System.Collections.Generic;
29using System.Text;
30
31using OpenSim.Framework;
32using OpenSim.Region.Framework;
33using OpenSim.Region.CoreModules;
34using OpenSim.Region.Physics.Manager;
35
36using Nini.Config;
37using log4net;
38
39using OpenMetaverse;
40
41namespace OpenSim.Region.Physics.BulletSPlugin
42{
43public sealed class BSTerrainManager
44{
45 static string LogHeader = "[BULLETSIM TERRAIN MANAGER]";
46
47 // These height values are fractional so the odd values will be
48 // noticable when debugging.
49 public const float HEIGHT_INITIALIZATION = 24.987f;
50 public const float HEIGHT_INITIAL_LASTHEIGHT = 24.876f;
51 public const float HEIGHT_GETHEIGHT_RET = 24.765f;
52
53 // If the min and max height are equal, we reduce the min by this
54 // amount to make sure that a bounding box is built for the terrain.
55 public const float HEIGHT_EQUAL_FUDGE = 0.2f;
56
57 public const float TERRAIN_COLLISION_MARGIN = 0.0f;
58
59 // Until the whole simulator is changed to pass us the region size, we rely on constants.
60 public Vector3 DefaultRegionSize = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
61
62 // The scene that I am part of
63 private BSScene PhysicsScene { get; set; }
64
65 // The ground plane created to keep thing from falling to infinity.
66 private BulletBody m_groundPlane;
67
68 // If doing mega-regions, if we're region zero we will be managing multiple
69 // region terrains since region zero does the physics for the whole mega-region.
70 private Dictionary<Vector2, BulletHeightMapInfo> m_heightMaps;
71
72 // True of the terrain has been modified.
73 // Used to force recalculation of terrain height after terrain has been modified
74 private bool m_terrainModified;
75
76 // If we are doing mega-regions, terrains are added from TERRAIN_ID to m_terrainCount.
77 // This is incremented before assigning to new region so it is the last ID allocated.
78 private uint m_terrainCount = BSScene.CHILDTERRAIN_ID - 1;
79 public uint HighestTerrainID { get {return m_terrainCount; } }
80
81 // If doing mega-regions, this holds our offset from region zero of
82 // the mega-regions. "parentScene" points to the PhysicsScene of region zero.
83 private Vector3 m_worldOffset;
84 // If the parent region (region 0), this is the extent of the combined regions
85 // relative to the origin of region zero
86 private Vector3 m_worldMax;
87 private PhysicsScene MegaRegionParentPhysicsScene { get; set; }
88
89 public BSTerrainManager(BSScene physicsScene)
90 {
91 PhysicsScene = physicsScene;
92 m_heightMaps = new Dictionary<Vector2,BulletHeightMapInfo>();
93 m_terrainModified = false;
94
95 // Assume one region of default size
96 m_worldOffset = Vector3.Zero;
97 m_worldMax = new Vector3(DefaultRegionSize);
98 MegaRegionParentPhysicsScene = null;
99 }
100
101 // Create the initial instance of terrain and the underlying ground plane.
102 // The objects are allocated in the unmanaged space and the pointers are tracked
103 // by the managed code.
104 // The terrains and the groundPlane are not added to the list of PhysObjects.
105 // This is called from the initialization routine so we presume it is
106 // safe to call Bullet in real time. We hope no one is moving prims around yet.
107 public void CreateInitialGroundPlaneAndTerrain()
108 {
109 // The ground plane is here to catch things that are trying to drop to negative infinity
110 BulletShape groundPlaneShape = new BulletShape(
111 BulletSimAPI.CreateGroundPlaneShape2(BSScene.GROUNDPLANE_ID, 1f, TERRAIN_COLLISION_MARGIN),
112 ShapeData.PhysicsShapeType.SHAPE_GROUNDPLANE);
113 m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID,
114 BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID,
115 Vector3.Zero, Quaternion.Identity));
116 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr);
117 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_groundPlane.ptr);
118 // Ground plane does not move
119 BulletSimAPI.ForceActivationState2(m_groundPlane.ptr, ActivationState.DISABLE_SIMULATION);
120 // Everything collides with the ground plane.
121 BulletSimAPI.SetCollisionFilterMask2(m_groundPlane.ptr,
122 (uint)CollisionFilterGroups.GroundPlaneFilter, (uint)CollisionFilterGroups.GroundPlaneMask);
123
124 Vector3 minTerrainCoords = new Vector3(0f, 0f, HEIGHT_INITIALIZATION - HEIGHT_EQUAL_FUDGE);
125 Vector3 maxTerrainCoords = new Vector3(DefaultRegionSize.X, DefaultRegionSize.Y, HEIGHT_INITIALIZATION);
126 int totalHeights = (int)maxTerrainCoords.X * (int)maxTerrainCoords.Y;
127 float[] initialMap = new float[totalHeights];
128 for (int ii = 0; ii < totalHeights; ii++)
129 {
130 initialMap[ii] = HEIGHT_INITIALIZATION;
131 }
132 UpdateOrCreateTerrain(BSScene.TERRAIN_ID, initialMap, minTerrainCoords, maxTerrainCoords, true);
133 }
134
135 // Release all the terrain structures we might have allocated
136 public void ReleaseGroundPlaneAndTerrain()
137 {
138 if (m_groundPlane.ptr != IntPtr.Zero)
139 {
140 if (BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr))
141 {
142 BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_groundPlane.ptr);
143 }
144 m_groundPlane.ptr = IntPtr.Zero;
145 }
146
147 ReleaseTerrain();
148 }
149
150 // Release all the terrain we have allocated
151 public void ReleaseTerrain()
152 {
153 foreach (KeyValuePair<Vector2, BulletHeightMapInfo> kvp in m_heightMaps)
154 {
155 if (BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, kvp.Value.terrainBody.ptr))
156 {
157 BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, kvp.Value.terrainBody.ptr);
158 BulletSimAPI.ReleaseHeightMapInfo2(kvp.Value.Ptr);
159 }
160 }
161 m_heightMaps.Clear();
162 }
163
164 // The simulator wants to set a new heightmap for the terrain.
165 public void SetTerrain(float[] heightMap) {
166 float[] localHeightMap = heightMap;
167 PhysicsScene.TaintedObject("TerrainManager.SetTerrain", delegate()
168 {
169 if (m_worldOffset != Vector3.Zero && MegaRegionParentPhysicsScene != null)
170 {
171 // If a child of a mega-region, we shouldn't have any terrain allocated for us
172 ReleaseGroundPlaneAndTerrain();
173 // If doing the mega-prim stuff and we are the child of the zero region,
174 // the terrain is added to our parent
175 if (MegaRegionParentPhysicsScene is BSScene)
176 {
177 DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}",
178 BSScene.DetailLogZero, m_worldOffset, m_worldMax);
179 ((BSScene)MegaRegionParentPhysicsScene).TerrainManager.UpdateOrCreateTerrain(BSScene.CHILDTERRAIN_ID,
180 localHeightMap, m_worldOffset, m_worldOffset + DefaultRegionSize, true);
181 }
182 }
183 else
184 {
185 // If not doing the mega-prim thing, just change the terrain
186 DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero);
187
188 UpdateOrCreateTerrain(BSScene.TERRAIN_ID, localHeightMap,
189 m_worldOffset, m_worldOffset + DefaultRegionSize, true);
190 }
191 });
192 }
193
194 // If called with no mapInfo for the terrain, this will create a new mapInfo and terrain
195 // based on the passed information. The 'id' should be either the terrain id or
196 // BSScene.CHILDTERRAIN_ID. If the latter, a new child terrain ID will be allocated and used.
197 // The latter feature is for creating child terrains for mega-regions.
198 // If called with a mapInfo in m_heightMaps but the terrain has no body yet (mapInfo.terrainBody.Ptr == 0)
199 // then a new body and shape is created and the mapInfo is filled.
200 // This call is used for doing the initial terrain creation.
201 // If called with a mapInfo in m_heightMaps and there is an existing terrain body, a new
202 // terrain shape is created and added to the body.
203 // This call is most often used to update the heightMap and parameters of the terrain.
204 // (The above does suggest that some simplification/refactoring is in order.)
205 private void UpdateOrCreateTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords, bool inTaintTime)
206 {
207 DetailLog("{0},BSTerrainManager.UpdateOrCreateTerrain,call,minC={1},maxC={2},inTaintTime={3}",
208 BSScene.DetailLogZero, minCoords, maxCoords, inTaintTime);
209
210 float minZ = float.MaxValue;
211 float maxZ = float.MinValue;
212 Vector2 terrainRegionBase = new Vector2(minCoords.X, minCoords.Y);
213
214 int heightMapSize = heightMap.Length;
215 for (int ii = 0; ii < heightMapSize; ii++)
216 {
217 float height = heightMap[ii];
218 if (height < minZ) minZ = height;
219 if (height > maxZ) maxZ = height;
220 }
221
222 // The shape of the terrain is from its base to its extents.
223 minCoords.Z = minZ;
224 maxCoords.Z = maxZ;
225
226 BulletHeightMapInfo mapInfo;
227 if (m_heightMaps.TryGetValue(terrainRegionBase, out mapInfo))
228 {
229 // If this is terrain we know about, it's easy to update
230
231 mapInfo.heightMap = heightMap;
232 mapInfo.minCoords = minCoords;
233 mapInfo.maxCoords = maxCoords;
234 mapInfo.minZ = minZ;
235 mapInfo.maxZ = maxZ;
236 mapInfo.sizeX = maxCoords.X - minCoords.X;
237 mapInfo.sizeY = maxCoords.Y - minCoords.Y;
238 DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,call,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}",
239 BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY);
240
241 PhysicsScene.TaintedObject(inTaintTime, "BSScene.UpdateOrCreateTerrain:UpdateExisting", delegate()
242 {
243 if (MegaRegionParentPhysicsScene != null)
244 {
245 // It's possible that Combine() was called after this code was queued.
246 // If we are a child of combined regions, we don't create any terrain for us.
247 DetailLog("{0},UpdateOrCreateTerrain:AmACombineChild,taint", BSScene.DetailLogZero);
248
249 // Get rid of any terrain that may have been allocated for us.
250 ReleaseGroundPlaneAndTerrain();
251
252 // I hate doing this, but just bail
253 return;
254 }
255
256 if (mapInfo.terrainBody.ptr != IntPtr.Zero)
257 {
258 // Updating an existing terrain.
259 DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,taint,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}",
260 BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY);
261
262 // Remove from the dynamics world because we're going to mangle this object
263 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr);
264
265 // Get rid of the old terrain
266 BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr);
267 BulletSimAPI.ReleaseHeightMapInfo2(mapInfo.Ptr);
268 mapInfo.Ptr = IntPtr.Zero;
269
270 /*
271 // NOTE: This routine is half here because I can't get the terrain shape replacement
272 // to work. In the short term, the above three lines completely delete the old
273 // terrain and the code below recreates one from scratch.
274 // Hopefully the Bullet community will help me out on this one.
275
276 // First, release the old collision shape (there is only one terrain)
277 BulletSimAPI.DeleteCollisionShape2(m_physicsScene.World.Ptr, mapInfo.terrainShape.Ptr);
278
279 // Fill the existing height map info with the new location and size information
280 BulletSimAPI.FillHeightMapInfo2(m_physicsScene.World.Ptr, mapInfo.Ptr, mapInfo.ID,
281 mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN);
282
283 // Create a terrain shape based on the new info
284 mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr));
285
286 // Stuff the shape into the existing terrain body
287 BulletSimAPI.SetBodyShape2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr, mapInfo.terrainShape.Ptr);
288 */
289 }
290 // else
291 {
292 // Creating a new terrain.
293 DetailLog("{0},UpdateOrCreateTerrain:CreateNewTerrain,taint,baseX={1},baseY={2},minZ={3},maxZ={4}",
294 BSScene.DetailLogZero, mapInfo.minCoords.X, mapInfo.minCoords.Y, minZ, maxZ);
295
296 mapInfo.ID = id;
297 mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, mapInfo.ID,
298 mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN);
299
300 // Create the terrain shape from the mapInfo
301 mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr),
302 ShapeData.PhysicsShapeType.SHAPE_TERRAIN);
303
304 // The terrain object initial position is at the center of the object
305 Vector3 centerPos;
306 centerPos.X = minCoords.X + (mapInfo.sizeX / 2f);
307 centerPos.Y = minCoords.Y + (mapInfo.sizeY / 2f);
308 centerPos.Z = minZ + ((maxZ - minZ) / 2f);
309
310 mapInfo.terrainBody = new BulletBody(mapInfo.ID,
311 BulletSimAPI.CreateBodyWithDefaultMotionState2(mapInfo.terrainShape.ptr,
312 id, centerPos, Quaternion.Identity));
313 }
314
315 // Make sure the entry is in the heightmap table
316 m_heightMaps[terrainRegionBase] = mapInfo;
317
318 // Set current terrain attributes
319 BulletSimAPI.SetFriction2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainFriction);
320 BulletSimAPI.SetHitFraction2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainHitFraction);
321 BulletSimAPI.SetRestitution2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainRestitution);
322 BulletSimAPI.SetCollisionFlags2(mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT);
323
324 // Return the new terrain to the world of physical objects
325 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr);
326
327 // redo its bounding box now that it is in the world
328 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr);
329
330 BulletSimAPI.SetCollisionFilterMask2(mapInfo.terrainBody.ptr,
331 (uint)CollisionFilterGroups.TerrainFilter,
332 (uint)CollisionFilterGroups.TerrainMask);
333
334 // Make sure the new shape is processed.
335 // BulletSimAPI.Activate2(mapInfo.terrainBody.ptr, true);
336 // BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.ISLAND_SLEEPING);
337 BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION);
338
339 m_terrainModified = true;
340 });
341 }
342 else
343 {
344 // We don't know about this terrain so either we are creating a new terrain or
345 // our mega-prim child is giving us a new terrain to add to the phys world
346
347 // if this is a child terrain, calculate a unique terrain id
348 uint newTerrainID = id;
349 if (newTerrainID >= BSScene.CHILDTERRAIN_ID)
350 newTerrainID = ++m_terrainCount;
351
352 float[] heightMapX = heightMap;
353 Vector3 minCoordsX = minCoords;
354 Vector3 maxCoordsX = maxCoords;
355
356 DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,call,id={1}, minC={2}, maxC={3}",
357 BSScene.DetailLogZero, newTerrainID, minCoords, minCoords);
358
359 // Code that must happen at taint-time
360 PhysicsScene.TaintedObject(inTaintTime, "BSScene.UpdateOrCreateTerrain:NewTerrain", delegate()
361 {
362 DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,taint,baseX={1},baseY={2}", BSScene.DetailLogZero, minCoords.X, minCoords.Y);
363 // Create a new mapInfo that will be filled with the new info
364 mapInfo = new BulletHeightMapInfo(id, heightMapX,
365 BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, newTerrainID,
366 minCoordsX, maxCoordsX, heightMapX, TERRAIN_COLLISION_MARGIN));
367 // Put the unfilled heightmap info into the collection of same
368 m_heightMaps.Add(terrainRegionBase, mapInfo);
369 // Build the terrain
370 UpdateOrCreateTerrain(newTerrainID, heightMap, minCoords, maxCoords, true);
371
372 m_terrainModified = true;
373 });
374 }
375 }
376
377 // Someday we will have complex terrain with caves and tunnels
378 public float GetTerrainHeightAtXYZ(Vector3 loc)
379 {
380 // For the moment, it's flat and convex
381 return GetTerrainHeightAtXY(loc.X, loc.Y);
382 }
383
384 // Given an X and Y, find the height of the terrain.
385 // Since we could be handling multiple terrains for a mega-region,
386 // the base of the region is calcuated assuming all regions are
387 // the same size and that is the default.
388 // Once the heightMapInfo is found, we have all the information to
389 // compute the offset into the array.
390 private float lastHeightTX = 999999f;
391 private float lastHeightTY = 999999f;
392 private float lastHeight = HEIGHT_INITIAL_LASTHEIGHT;
393 private float GetTerrainHeightAtXY(float tX, float tY)
394 {
395 // You'd be surprized at the number of times this routine is called
396 // with the same parameters as last time.
397 if (!m_terrainModified && lastHeightTX == tX && lastHeightTY == tY)
398 return lastHeight;
399
400 lastHeightTX = tX;
401 lastHeightTY = tY;
402 float ret = HEIGHT_GETHEIGHT_RET;
403
404 int offsetX = ((int)(tX / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X;
405 int offsetY = ((int)(tY / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y;
406 Vector2 terrainBaseXY = new Vector2(offsetX, offsetY);
407
408 BulletHeightMapInfo mapInfo;
409 if (m_heightMaps.TryGetValue(terrainBaseXY, out mapInfo))
410 {
411 float regionX = tX - offsetX;
412 float regionY = tY - offsetY;
413 int mapIndex = (int)regionY * (int)mapInfo.sizeY + (int)regionX;
414 try
415 {
416 ret = mapInfo.heightMap[mapIndex];
417 }
418 catch
419 {
420 // Sometimes they give us wonky values of X and Y. Give a warning and return something.
421 PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, x={2}, y={3}",
422 LogHeader, terrainBaseXY, regionX, regionY);
423 ret = HEIGHT_GETHEIGHT_RET;
424 }
425 // DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXY,bX={1},baseY={2},szX={3},szY={4},regX={5},regY={6},index={7},ht={8}",
426 // BSScene.DetailLogZero, offsetX, offsetY, mapInfo.sizeX, mapInfo.sizeY, regionX, regionY, mapIndex, ret);
427 }
428 else
429 {
430 PhysicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}",
431 LogHeader, PhysicsScene.RegionName, tX, tY);
432 }
433 m_terrainModified = false;
434 lastHeight = ret;
435 return ret;
436 }
437
438 // Although no one seems to check this, I do support combining.
439 public bool SupportsCombining()
440 {
441 return true;
442 }
443
444 // This routine is called two ways:
445 // One with 'offset' and 'pScene' zero and null but 'extents' giving the maximum
446 // extent of the combined regions. This is to inform the parent of the size
447 // of the combined regions.
448 // and one with 'offset' as the offset of the child region to the base region,
449 // 'pScene' pointing to the parent and 'extents' of zero. This informs the
450 // child of its relative base and new parent.
451 public void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents)
452 {
453 m_worldOffset = offset;
454 m_worldMax = extents;
455 MegaRegionParentPhysicsScene = pScene;
456 if (pScene != null)
457 {
458 // We are a child.
459 // We want m_worldMax to be the highest coordinate of our piece of terrain.
460 m_worldMax = offset + DefaultRegionSize;
461 }
462 DetailLog("{0},BSTerrainManager.Combine,offset={1},extents={2},wOffset={3},wMax={4}",
463 BSScene.DetailLogZero, offset, extents, m_worldOffset, m_worldMax);
464 }
465
466 // Unhook all the combining that I know about.
467 public void UnCombine(PhysicsScene pScene)
468 {
469 // Just like ODE, for the moment a NOP
470 DetailLog("{0},BSTerrainManager.UnCombine", BSScene.DetailLogZero);
471 }
472
473
474 private void DetailLog(string msg, params Object[] args)
475 {
476 PhysicsScene.PhysicsLogging.Write(msg, args);
477 }
478}
479}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
index 702bd77..504bd3c 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
@@ -33,153 +33,38 @@ using OpenMetaverse;
33namespace OpenSim.Region.Physics.BulletSPlugin { 33namespace OpenSim.Region.Physics.BulletSPlugin {
34 34
35// Classes to allow some type checking for the API 35// Classes to allow some type checking for the API
36// These hold pointers to allocated objects in the unmanaged space.
37
38// The physics engine controller class created at initialization
39public struct BulletSim 36public struct BulletSim
40{ 37{
41 public BulletSim(uint worldId, BSScene bss, IntPtr xx) 38 public BulletSim(uint id, BSScene bss, IntPtr xx) { ID = id; scene = bss; Ptr = xx; }
42 { 39 public uint ID;
43 ptr = xx;
44 worldID = worldId;
45 physicsScene = bss;
46 }
47 public IntPtr ptr;
48 public uint worldID;
49 // The scene is only in here so very low level routines have a handle to print debug/error messages 40 // The scene is only in here so very low level routines have a handle to print debug/error messages
50 public BSScene physicsScene; 41 public BSScene scene;
42 public IntPtr Ptr;
51} 43}
52 44
53// An allocated Bullet btRigidBody
54public struct BulletBody 45public struct BulletBody
55{ 46{
56 public BulletBody(uint id, IntPtr xx) 47 public BulletBody(uint id, IntPtr xx) { ID = id; Ptr = xx; }
57 { 48 public IntPtr Ptr;
58 ID = id;
59 ptr = xx;
60 collisionFilter = 0;
61 collisionMask = 0;
62 }
63 public IntPtr ptr;
64 public uint ID; 49 public uint ID;
65 public CollisionFilterGroups collisionFilter;
66 public CollisionFilterGroups collisionMask;
67 public override string ToString()
68 {
69 StringBuilder buff = new StringBuilder();
70 buff.Append("<id=");
71 buff.Append(ID.ToString());
72 buff.Append(",p=");
73 buff.Append(ptr.ToString("X"));
74 if (collisionFilter != 0 || collisionMask != 0)
75 {
76 buff.Append(",f=");
77 buff.Append(collisionFilter.ToString("X"));
78 buff.Append(",m=");
79 buff.Append(collisionMask.ToString("X"));
80 }
81 buff.Append(">");
82 return buff.ToString();
83 }
84}
85
86public struct BulletShape
87{
88 public BulletShape(IntPtr xx)
89 {
90 ptr = xx;
91 type=ShapeData.PhysicsShapeType.SHAPE_UNKNOWN;
92 shapeKey = 0;
93 isNativeShape = false;
94 }
95 public BulletShape(IntPtr xx, ShapeData.PhysicsShapeType typ)
96 {
97 ptr = xx;
98 type = typ;
99 shapeKey = 0;
100 isNativeShape = false;
101 }
102 public IntPtr ptr;
103 public ShapeData.PhysicsShapeType type;
104 public System.UInt64 shapeKey;
105 public bool isNativeShape;
106 public override string ToString()
107 {
108 StringBuilder buff = new StringBuilder();
109 buff.Append("<p=");
110 buff.Append(ptr.ToString("X"));
111 buff.Append(",s=");
112 buff.Append(type.ToString());
113 buff.Append(",k=");
114 buff.Append(shapeKey.ToString("X"));
115 buff.Append(",n=");
116 buff.Append(isNativeShape.ToString());
117 buff.Append(">");
118 return buff.ToString();
119 }
120} 50}
121 51
122 // Constraint type values as defined by Bullet
123public enum ConstraintType : int
124{
125 POINT2POINT_CONSTRAINT_TYPE = 3,
126 HINGE_CONSTRAINT_TYPE,
127 CONETWIST_CONSTRAINT_TYPE,
128 D6_CONSTRAINT_TYPE,
129 SLIDER_CONSTRAINT_TYPE,
130 CONTACT_CONSTRAINT_TYPE,
131 D6_SPRING_CONSTRAINT_TYPE,
132 MAX_CONSTRAINT_TYPE
133}
134
135// An allocated Bullet btConstraint
136public struct BulletConstraint 52public struct BulletConstraint
137{ 53{
138 public BulletConstraint(IntPtr xx) 54 public BulletConstraint(IntPtr xx) { Ptr = xx; }
139 {
140 ptr = xx;
141 }
142 public IntPtr ptr;
143}
144
145// An allocated HeightMapThing which holds various heightmap info.
146// Made a class rather than a struct so there would be only one
147// instance of this and C# will pass around pointers rather
148// than making copies.
149public class BulletHeightMapInfo
150{
151 public BulletHeightMapInfo(uint id, float[] hm, IntPtr xx) {
152 ID = id;
153 Ptr = xx;
154 heightMap = hm;
155 terrainRegionBase = new Vector2(0f, 0f);
156 minCoords = new Vector3(100f, 100f, 25f);
157 maxCoords = new Vector3(101f, 101f, 26f);
158 minZ = maxZ = 0f;
159 sizeX = sizeY = 256f;
160 }
161 public uint ID;
162 public IntPtr Ptr; 55 public IntPtr Ptr;
163 public float[] heightMap;
164 public Vector2 terrainRegionBase;
165 public Vector3 minCoords;
166 public Vector3 maxCoords;
167 public float sizeX, sizeY;
168 public float minZ, maxZ;
169 public BulletShape terrainShape;
170 public BulletBody terrainBody;
171} 56}
172 57
173// =============================================================================== 58// ===============================================================================
174[StructLayout(LayoutKind.Sequential)] 59[StructLayout(LayoutKind.Sequential)]
175public struct ConvexHull 60public struct ConvexHull
176{ 61{
177 Vector3 Offset; 62 Vector3 Offset;
178 int VertexCount; 63 int VertexCount;
179 Vector3[] Vertices; 64 Vector3[] Vertices;
180} 65}
181[StructLayout(LayoutKind.Sequential)] 66[StructLayout(LayoutKind.Sequential)]
182public struct ShapeData 67public struct ShapeData
183{ 68{
184 public enum PhysicsShapeType 69 public enum PhysicsShapeType
185 { 70 {
@@ -190,11 +75,7 @@ public struct ShapeData
190 SHAPE_CYLINDER = 4, 75 SHAPE_CYLINDER = 4,
191 SHAPE_SPHERE = 5, 76 SHAPE_SPHERE = 5,
192 SHAPE_MESH = 6, 77 SHAPE_MESH = 6,
193 SHAPE_HULL = 7, 78 SHAPE_HULL = 7
194 // following defined by BulletSim
195 SHAPE_GROUNDPLANE = 20,
196 SHAPE_TERRAIN = 21,
197 SHAPE_COMPOUND = 22,
198 }; 79 };
199 public uint ID; 80 public uint ID;
200 public PhysicsShapeType Type; 81 public PhysicsShapeType Type;
@@ -210,25 +91,13 @@ public struct ShapeData
210 public float Restitution; 91 public float Restitution;
211 public float Collidable; // true of things bump into this 92 public float Collidable; // true of things bump into this
212 public float Static; // true if a static object. Otherwise gravity, etc. 93 public float Static; // true if a static object. Otherwise gravity, etc.
213 public float Solid; // true if object cannot be passed through
214 public Vector3 Size;
215 94
216 // note that bools are passed as floats since bool size changes by language and architecture 95 // note that bools are passed as floats since bool size changes by language and architecture
217 public const float numericTrue = 1f; 96 public const float numericTrue = 1f;
218 public const float numericFalse = 0f; 97 public const float numericFalse = 0f;
219
220 // The native shapes have predefined shape hash keys
221 public enum FixedShapeKey : ulong
222 {
223 KEY_BOX = 1,
224 KEY_SPHERE = 2,
225 KEY_CONE = 3,
226 KEY_CYLINDER = 4,
227 KEY_CAPSULE = 5,
228 }
229} 98}
230[StructLayout(LayoutKind.Sequential)] 99[StructLayout(LayoutKind.Sequential)]
231public struct SweepHit 100public struct SweepHit
232{ 101{
233 public uint ID; 102 public uint ID;
234 public float Fraction; 103 public float Fraction;
@@ -284,7 +153,6 @@ public struct ConfigurationParameters
284 public float terrainHitFraction; 153 public float terrainHitFraction;
285 public float terrainRestitution; 154 public float terrainRestitution;
286 public float avatarFriction; 155 public float avatarFriction;
287 public float avatarStandingFriction;
288 public float avatarDensity; 156 public float avatarDensity;
289 public float avatarRestitution; 157 public float avatarRestitution;
290 public float avatarCapsuleRadius; 158 public float avatarCapsuleRadius;
@@ -300,45 +168,18 @@ public struct ConfigurationParameters
300 public float shouldEnableFrictionCaching; 168 public float shouldEnableFrictionCaching;
301 public float numberOfSolverIterations; 169 public float numberOfSolverIterations;
302 170
303 public float linksetImplementation;
304 public float linkConstraintUseFrameOffset; 171 public float linkConstraintUseFrameOffset;
305 public float linkConstraintEnableTransMotor; 172 public float linkConstraintEnableTransMotor;
306 public float linkConstraintTransMotorMaxVel; 173 public float linkConstraintTransMotorMaxVel;
307 public float linkConstraintTransMotorMaxForce; 174 public float linkConstraintTransMotorMaxForce;
308 public float linkConstraintERP; 175 public float linkConstraintERP;
309 public float linkConstraintCFM; 176 public float linkConstraintCFM;
310 public float linkConstraintSolverIterations;
311
312 public float physicsLoggingFrames;
313 177
314 public const float numericTrue = 1f; 178 public const float numericTrue = 1f;
315 public const float numericFalse = 0f; 179 public const float numericFalse = 0f;
316} 180}
317 181
318 182// Values used by Bullet and BulletSim to control collisions
319// The states a bullet collision object can have
320public enum ActivationState : uint
321{
322 ACTIVE_TAG = 1,
323 ISLAND_SLEEPING,
324 WANTS_DEACTIVATION,
325 DISABLE_DEACTIVATION,
326 DISABLE_SIMULATION,
327}
328
329public enum CollisionObjectTypes : int
330{
331 CO_COLLISION_OBJECT = 1 << 0,
332 CO_RIGID_BODY = 1 << 1,
333 CO_GHOST_OBJECT = 1 << 2,
334 CO_SOFT_BODY = 1 << 3,
335 CO_HF_FLUID = 1 << 4,
336 CO_USER_TYPE = 1 << 5,
337}
338
339// Values used by Bullet and BulletSim to control object properties.
340// Bullet's "CollisionFlags" has more to do with operations on the
341// object (if collisions happen, if gravity effects it, ...).
342public enum CollisionFlags : uint 183public enum CollisionFlags : uint
343{ 184{
344 CF_STATIC_OBJECT = 1 << 0, 185 CF_STATIC_OBJECT = 1 << 0,
@@ -350,54 +191,9 @@ public enum CollisionFlags : uint
350 CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6, 191 CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6,
351 // Following used by BulletSim to control collisions 192 // Following used by BulletSim to control collisions
352 BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10, 193 BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10,
353 BS_FLOATS_ON_WATER = 1 << 11, 194 BS_VOLUME_DETECT_OBJECT = 1 << 11,
354 BS_NONE = 0, 195 BS_PHANTOM_OBJECT = 1 << 12,
355 BS_ALL = 0xFFFFFFFF, 196 BS_PHYSICAL_OBJECT = 1 << 13,
356
357 // These are the collision flags switched depending on physical state.
358 // The other flags are used for other things and should not be fooled with.
359 BS_ACTIVE = CF_STATIC_OBJECT
360 | CF_KINEMATIC_OBJECT
361 | CF_NO_CONTACT_RESPONSE
362};
363
364// Values for collisions groups and masks
365public enum CollisionFilterGroups : uint
366{
367 // Don't use the bit definitions!! Define the use in a
368 // filter/mask definition below. This way collision interactions
369 // are more easily debugged.
370 BNoneFilter = 0,
371 BDefaultFilter = 1 << 0,
372 BStaticFilter = 1 << 1,
373 BKinematicFilter = 1 << 2,
374 BDebrisFilter = 1 << 3,
375 BSensorTrigger = 1 << 4,
376 BCharacterFilter = 1 << 5,
377 BAllFilter = 0xFFFFFFFF,
378 // Filter groups defined by BulletSim
379 BGroundPlaneFilter = 1 << 10,
380 BTerrainFilter = 1 << 11,
381 BRaycastFilter = 1 << 12,
382 BSolidFilter = 1 << 13,
383 BLinksetFilter = 1 << 14,
384
385 // The collsion filters and masked are defined in one place -- don't want them scattered
386 AvatarFilter = BCharacterFilter,
387 AvatarMask = BAllFilter,
388 ObjectFilter = BSolidFilter,
389 ObjectMask = BAllFilter,
390 StaticObjectFilter = BStaticFilter,
391 StaticObjectMask = BAllFilter,
392 LinksetFilter = BLinksetFilter,
393 LinksetMask = BAllFilter & ~BLinksetFilter,
394 VolumeDetectFilter = BSensorTrigger,
395 VolumeDetectMask = ~BSensorTrigger,
396 TerrainFilter = BTerrainFilter,
397 TerrainMask = BAllFilter & ~BStaticFilter,
398 GroundPlaneFilter = BGroundPlaneFilter,
399 GroundPlaneMask = BAllFilter
400
401}; 197};
402 198
403// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0 199// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0
@@ -425,23 +221,14 @@ public enum ConstraintParamAxis : int
425// =============================================================================== 221// ===============================================================================
426static class BulletSimAPI { 222static class BulletSimAPI {
427 223
428// Link back to the managed code for outputting log messages
429[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
430public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg);
431
432[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 224[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
433[return: MarshalAs(UnmanagedType.LPStr)] 225[return: MarshalAs(UnmanagedType.LPStr)]
434public static extern string GetVersion(); 226public static extern string GetVersion();
435 227
436/* Remove the linkage to the old api methods
437[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 228[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
438public static extern uint Initialize(Vector3 maxPosition, IntPtr parms, 229public static extern uint Initialize(Vector3 maxPosition, IntPtr parms,
439 int maxCollisions, IntPtr collisionArray, 230 int maxCollisions, IntPtr collisionArray,
440 int maxUpdates, IntPtr updateArray, 231 int maxUpdates, IntPtr updateArray);
441 DebugLogCallback logRoutine);
442
443[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
444public static extern void CreateInitialGroundPlaneAndTerrain(uint worldID);
445 232
446[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 233[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
447public static extern void SetHeightmap(uint worldID, [MarshalAs(UnmanagedType.LPArray)] float[] heightMap); 234public static extern void SetHeightmap(uint worldID, [MarshalAs(UnmanagedType.LPArray)] float[] heightMap);
@@ -455,19 +242,19 @@ public static extern bool UpdateParameter(uint worldID, uint localID,
455 242
456// =============================================================================== 243// ===============================================================================
457[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 244[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
458public static extern int PhysicsStep(uint worldID, float timeStep, int maxSubSteps, float fixedTimeStep, 245public static extern int PhysicsStep(uint worldID, float timeStep, int maxSubSteps, float fixedTimeStep,
459 out int updatedEntityCount, 246 out int updatedEntityCount,
460 out IntPtr updatedEntitiesPtr, 247 out IntPtr updatedEntitiesPtr,
461 out int collidersCount, 248 out int collidersCount,
462 out IntPtr collidersPtr); 249 out IntPtr collidersPtr);
463 250
464[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 251[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
465public static extern bool CreateHull(uint worldID, System.UInt64 meshKey, 252public static extern bool CreateHull(uint worldID, System.UInt64 meshKey,
466 int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls 253 int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls
467 ); 254 );
468 255
469[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 256[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
470public static extern bool CreateMesh(uint worldID, System.UInt64 meshKey, 257public static extern bool CreateMesh(uint worldID, System.UInt64 meshKey,
471 int indexCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices, 258 int indexCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices,
472 int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices 259 int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices
473 ); 260 );
@@ -481,6 +268,23 @@ public static extern bool DestroyMesh(uint worldID, System.UInt64 meshKey);
481[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 268[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
482public static extern bool CreateObject(uint worldID, ShapeData shapeData); 269public static extern bool CreateObject(uint worldID, ShapeData shapeData);
483 270
271/* Remove old functionality
272[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
273public static extern void CreateLinkset(uint worldID, int objectCount, ShapeData[] shapeDatas);
274
275[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
276public static extern void AddConstraint(uint worldID, uint id1, uint id2,
277 Vector3 frame1, Quaternion frame1rot,
278 Vector3 frame2, Quaternion frame2rot,
279 Vector3 lowLinear, Vector3 hiLinear, Vector3 lowAngular, Vector3 hiAngular);
280
281[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
282public static extern bool RemoveConstraintByID(uint worldID, uint id1);
283
284[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
285public static extern bool RemoveConstraint(uint worldID, uint id1, uint id2);
286 */
287
484[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 288[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
485public static extern Vector3 GetObjectPosition(uint WorldID, uint id); 289public static extern Vector3 GetObjectPosition(uint WorldID, uint id);
486 290
@@ -496,7 +300,6 @@ public static extern bool SetObjectVelocity(uint worldID, uint id, Vector3 veloc
496[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 300[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
497public static extern bool SetObjectAngularVelocity(uint worldID, uint id, Vector3 angularVelocity); 301public static extern bool SetObjectAngularVelocity(uint worldID, uint id, Vector3 angularVelocity);
498 302
499// Set the current force acting on the object
500[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 303[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
501public static extern bool SetObjectForce(uint worldID, uint id, Vector3 force); 304public static extern bool SetObjectForce(uint worldID, uint id, Vector3 force);
502 305
@@ -537,8 +340,10 @@ public static extern Vector3 RecoverFromPenetration(uint worldID, uint id);
537// =============================================================================== 340// ===============================================================================
538[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 341[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
539public static extern void DumpBulletStatistics(); 342public static extern void DumpBulletStatistics();
540*/ 343
541// Log a debug message 344// Log a debug message
345[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
346public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg);
542[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 347[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
543public static extern void SetDebugLogCallback(DebugLogCallback callback); 348public static extern void SetDebugLogCallback(DebugLogCallback callback);
544 349
@@ -553,7 +358,6 @@ public static extern void SetDebugLogCallback(DebugLogCallback callback);
553// The names have a "2" tacked on. This will be removed as the C# code gets rebuilt 358// The names have a "2" tacked on. This will be removed as the C# code gets rebuilt
554// and the old code is removed. 359// and the old code is removed.
555 360
556// Functions use while converting from API1 to API2. Can be removed when totally converted.
557[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 361[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
558public static extern IntPtr GetSimHandle2(uint worldID); 362public static extern IntPtr GetSimHandle2(uint worldID);
559 363
@@ -564,25 +368,23 @@ public static extern IntPtr GetBodyHandleWorldID2(uint worldID, uint id);
564public static extern IntPtr GetBodyHandle2(IntPtr world, uint id); 368public static extern IntPtr GetBodyHandle2(IntPtr world, uint id);
565 369
566// =============================================================================== 370// ===============================================================================
567// Initialization and simulation
568[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 371[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
569public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms, 372public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms,
570 int maxCollisions, IntPtr collisionArray, 373 int maxCollisions, IntPtr collisionArray,
571 int maxUpdates, IntPtr updateArray, 374 int maxUpdates, IntPtr updateArray);
572 DebugLogCallback logRoutine);
573 375
574[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 376[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
575public static extern bool UpdateParameter2(IntPtr world, uint localID, String parm, float value); 377public static extern bool UpdateParameter2(IntPtr world, uint localID, String parm, float value);
576 378
577[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 379[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
578public static extern void SetHeightMap2(IntPtr world, float[] heightmap); 380public static extern void SetHeightmap2(IntPtr world, float[] heightmap);
579 381
580[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 382[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
581public static extern void Shutdown2(IntPtr sim); 383public static extern void Shutdown2(IntPtr sim);
582 384
583[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 385[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
584public static extern int PhysicsStep2(IntPtr world, float timeStep, int maxSubSteps, float fixedTimeStep, 386public static extern int PhysicsStep2(IntPtr world, float timeStep, int maxSubSteps, float fixedTimeStep,
585 out int updatedEntityCount, 387 out int updatedEntityCount,
586 out IntPtr updatedEntitiesPtr, 388 out IntPtr updatedEntitiesPtr,
587 out int collidersCount, 389 out int collidersCount,
588 out IntPtr collidersPtr); 390 out IntPtr collidersPtr);
@@ -590,98 +392,23 @@ public static extern int PhysicsStep2(IntPtr world, float timeStep, int maxSubSt
590[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 392[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
591public static extern bool PushUpdate2(IntPtr obj); 393public static extern bool PushUpdate2(IntPtr obj);
592 394
593// ===================================================================================== 395/*
594// Mesh, hull, shape and body creation helper routines
595[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
596public static extern IntPtr CreateMeshShape2(IntPtr world,
597 int indicesCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices,
598 int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices );
599
600[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
601public static extern IntPtr CreateHullShape2(IntPtr world,
602 int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls);
603
604[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
605public static extern IntPtr BuildHullShapeFromMesh2(IntPtr world, IntPtr meshShape);
606
607[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
608public static extern IntPtr BuildNativeShape2(IntPtr world, ShapeData shapeData);
609
610[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
611public static extern bool IsNativeShape2(IntPtr shape);
612
613[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
614public static extern IntPtr BuildCapsuleShape2(IntPtr world, float radius, float height, Vector3 scale);
615
616[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
617public static extern IntPtr CreateCompoundShape2(IntPtr sim, bool enableDynamicAabbTree);
618
619[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
620public static extern int GetNumberOfCompoundChildren2(IntPtr cShape);
621
622[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
623public static extern void AddChildShapeToCompoundShape2(IntPtr cShape, IntPtr addShape, Vector3 pos, Quaternion rot);
624
625[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
626public static extern IntPtr GetChildShapeFromCompoundShapeIndex2(IntPtr cShape, int indx);
627
628[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
629public static extern IntPtr RemoveChildShapeFromCompoundShapeIndex2(IntPtr cShape, int indx);
630
631[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
632public static extern void RemoveChildShapeFromCompoundShape2(IntPtr cShape, IntPtr removeShape);
633
634[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
635public static extern IntPtr DuplicateCollisionShape2(IntPtr sim, IntPtr srcShape, uint id);
636
637[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
638public static extern IntPtr CreateBodyFromShapeAndInfo2(IntPtr sim, IntPtr shape, uint id, IntPtr constructionInfo);
639
640[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
641public static extern bool DeleteCollisionShape2(IntPtr world, IntPtr shape);
642
643[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
644public static extern int GetBodyType2(IntPtr obj);
645
646[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
647public static extern IntPtr CreateBodyFromShape2(IntPtr sim, IntPtr shape, uint id, Vector3 pos, Quaternion rot);
648
649[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
650public static extern IntPtr CreateBodyWithDefaultMotionState2(IntPtr shape, uint id, Vector3 pos, Quaternion rot);
651
652[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
653public static extern IntPtr CreateGhostFromShape2(IntPtr sim, IntPtr shape, uint id, Vector3 pos, Quaternion rot);
654
655[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
656public static extern IntPtr AllocateBodyInfo2(IntPtr obj);
657
658[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
659public static extern void ReleaseBodyInfo2(IntPtr obj);
660
661[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
662public static extern void DestroyObject2(IntPtr sim, IntPtr obj);
663
664// =====================================================================================
665// Terrain creation and helper routines
666[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 396[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
667public static extern IntPtr CreateHeightMapInfo2(IntPtr sim, uint id, Vector3 minCoords, Vector3 maxCoords, 397public static extern IntPtr CreateMesh2(IntPtr world, int indicesCount, int* indices, int verticesCount, float* vertices );
668 [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin);
669 398
670[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 399[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
671public static extern IntPtr FillHeightMapInfo2(IntPtr sim, IntPtr mapInfo, uint id, Vector3 minCoords, Vector3 maxCoords, 400public static extern bool BuildHull2(IntPtr world, IntPtr mesh);
672 [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin);
673 401
674[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 402[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
675public static extern bool ReleaseHeightMapInfo2(IntPtr heightMapInfo); 403public static extern bool ReleaseHull2(IntPtr world, IntPtr mesh);
676 404
677[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 405[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
678public static extern IntPtr CreateGroundPlaneShape2(uint id, float height, float collisionMargin); 406public static extern bool DestroyMesh2(IntPtr world, IntPtr mesh);
679 407
680[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 408[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
681public static extern IntPtr CreateTerrainShape2(IntPtr mapInfo); 409public static extern IntPtr CreateObject2(IntPtr world, ShapeData shapeData);
410*/
682 411
683// =====================================================================================
684// Constraint creation and helper routines
685[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 412[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
686public static extern IntPtr Create6DofConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2, 413public static extern IntPtr Create6DofConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
687 Vector3 frame1loc, Quaternion frame1rot, 414 Vector3 frame1loc, Quaternion frame1rot,
@@ -706,7 +433,7 @@ public static extern void SetConstraintEnable2(IntPtr constrain, float numericTr
706public static extern void SetConstraintNumSolverIterations2(IntPtr constrain, float iterations); 433public static extern void SetConstraintNumSolverIterations2(IntPtr constrain, float iterations);
707 434
708[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 435[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
709public static extern bool SetFrames2(IntPtr constrain, 436public static extern bool SetFrames2(IntPtr constrain,
710 Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot); 437 Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot);
711 438
712[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 439[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
@@ -733,108 +460,11 @@ public static extern bool SetConstraintParam2(IntPtr constrain, ConstraintParams
733[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 460[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
734public static extern bool DestroyConstraint2(IntPtr world, IntPtr constrain); 461public static extern bool DestroyConstraint2(IntPtr world, IntPtr constrain);
735 462
736// =====================================================================================
737// btCollisionWorld entries
738[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 463[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
739public static extern void UpdateSingleAabb2(IntPtr world, IntPtr obj); 464public static extern Vector3 AddObjectToWorld2(IntPtr world, IntPtr obj);
740 465
741[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 466[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
742public static extern void UpdateAabbs2(IntPtr world); 467public static extern Vector3 RemoveObjectFromWorld2(IntPtr world, IntPtr obj);
743
744[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
745public static extern bool GetForceUpdateAllAabbs2(IntPtr world);
746
747[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
748public static extern void SetForceUpdateAllAabbs2(IntPtr world, bool force);
749
750// =====================================================================================
751// btDynamicsWorld entries
752[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
753public static extern bool AddObjectToWorld2(IntPtr world, IntPtr obj);
754
755[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
756public static extern bool RemoveObjectFromWorld2(IntPtr world, IntPtr obj);
757
758[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
759public static extern bool AddConstraintToWorld2(IntPtr world, IntPtr constrain, bool disableCollisionsBetweenLinkedObjects);
760
761[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
762public static extern bool RemoveConstraintFromWorld2(IntPtr world, IntPtr constrain);
763// =====================================================================================
764// btCollisionObject entries
765[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
766public static extern Vector3 GetAnisotripicFriction2(IntPtr constrain);
767
768[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
769public static extern Vector3 SetAnisotripicFriction2(IntPtr constrain, Vector3 frict);
770
771[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
772public static extern bool HasAnisotripicFriction2(IntPtr constrain);
773
774[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
775public static extern void SetContactProcessingThreshold2(IntPtr obj, float val);
776
777[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
778public static extern float GetContactProcessingThreshold2(IntPtr obj);
779
780[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
781public static extern bool IsStaticObject2(IntPtr obj);
782
783[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
784public static extern bool IsKinematicObject2(IntPtr obj);
785
786[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
787public static extern bool IsStaticOrKinematicObject2(IntPtr obj);
788
789[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
790public static extern bool HasContactResponse2(IntPtr obj);
791
792[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
793public static extern void SetCollisionShape2(IntPtr sim, IntPtr obj, IntPtr shape);
794
795[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
796public static extern IntPtr GetCollisionShape2(IntPtr obj);
797
798[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
799public static extern int GetActivationState2(IntPtr obj);
800
801[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
802public static extern void SetActivationState2(IntPtr obj, int state);
803
804[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
805public static extern void SetDeactivationTime2(IntPtr obj, float dtime);
806
807[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
808public static extern float GetDeactivationTime2(IntPtr obj);
809
810[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
811public static extern void ForceActivationState2(IntPtr obj, ActivationState state);
812
813[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
814public static extern void Activate2(IntPtr obj, bool forceActivation);
815
816[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
817public static extern bool IsActive2(IntPtr obj);
818
819[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
820public static extern void SetRestitution2(IntPtr obj, float val);
821
822[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
823public static extern float GetRestitution2(IntPtr obj);
824
825[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
826public static extern void SetFriction2(IntPtr obj, float val);
827
828[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
829public static extern float GetFriction2(IntPtr obj);
830
831 /* Haven't defined the type 'Transform'
832[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
833public static extern Transform GetWorldTransform2(IntPtr obj);
834
835[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
836public static extern void setWorldTransform2(IntPtr obj, Transform trans);
837 */
838 468
839[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 469[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
840public static extern Vector3 GetPosition2(IntPtr obj); 470public static extern Vector3 GetPosition2(IntPtr obj);
@@ -843,290 +473,85 @@ public static extern Vector3 GetPosition2(IntPtr obj);
843public static extern Quaternion GetOrientation2(IntPtr obj); 473public static extern Quaternion GetOrientation2(IntPtr obj);
844 474
845[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 475[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
846public static extern void SetTranslation2(IntPtr obj, Vector3 position, Quaternion rotation); 476public static extern bool SetTranslation2(IntPtr obj, Vector3 position, Quaternion rotation);
847
848[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
849public static extern IntPtr GetBroadphaseHandle2(IntPtr obj);
850
851[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
852public static extern void SetBroadphaseHandle2(IntPtr obj, IntPtr handle);
853
854 /*
855[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
856public static extern Transform GetInterpolationWorldTransform2(IntPtr obj);
857
858[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
859public static extern void SetInterpolationWorldTransform2(IntPtr obj, Transform trans);
860 */
861
862[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
863public static extern void SetInterpolationLinearVelocity2(IntPtr obj, Vector3 vel);
864
865[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
866public static extern void SetInterpolationAngularVelocity2(IntPtr obj, Vector3 vel);
867
868[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
869public static extern void SetInterpolationVelocity2(IntPtr obj, Vector3 linearVel, Vector3 angularVel);
870
871[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
872public static extern float GetHitFraction2(IntPtr obj);
873
874[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
875public static extern void SetHitFraction2(IntPtr obj, float val);
876
877[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
878public static extern CollisionFlags GetCollisionFlags2(IntPtr obj);
879
880[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
881public static extern CollisionFlags SetCollisionFlags2(IntPtr obj, CollisionFlags flags);
882
883[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
884public static extern CollisionFlags AddToCollisionFlags2(IntPtr obj, CollisionFlags flags);
885
886[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
887public static extern CollisionFlags RemoveFromCollisionFlags2(IntPtr obj, CollisionFlags flags);
888
889[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
890public static extern float GetCcdMotionThreshold2(IntPtr obj);
891
892[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
893public static extern void SetCcdMotionThreshold2(IntPtr obj, float val);
894
895[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
896public static extern float GetCcdSweptSphereRadius2(IntPtr obj);
897
898[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
899public static extern void SetCcdSweptSphereRadius2(IntPtr obj, float val);
900
901[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
902public static extern IntPtr GetUserPointer2(IntPtr obj);
903
904[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
905public static extern void SetUserPointer2(IntPtr obj, IntPtr val);
906
907// =====================================================================================
908// btRigidBody entries
909[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
910public static extern void ApplyGravity2(IntPtr obj);
911
912[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
913public static extern void SetGravity2(IntPtr obj, Vector3 val);
914
915[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
916public static extern Vector3 GetGravity2(IntPtr obj);
917
918[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
919public static extern void SetDamping2(IntPtr obj, float lin_damping, float ang_damping);
920
921[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
922public static extern float GetLinearDamping2(IntPtr obj);
923
924[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
925public static extern float GetAngularDamping2(IntPtr obj);
926
927[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
928public static extern float GetLinearSleepingThreshold2(IntPtr obj);
929
930[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
931public static extern float GetAngularSleepingThreshold2(IntPtr obj);
932
933[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
934public static extern void ApplyDamping2(IntPtr obj, float timeStep);
935
936[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
937public static extern void SetMassProps2(IntPtr obj, float mass, Vector3 inertia);
938
939[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
940public static extern Vector3 GetLinearFactor2(IntPtr obj);
941
942[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
943public static extern void SetLinearFactor2(IntPtr obj, Vector3 factor);
944
945 /*
946[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
947public static extern void SetCenterOfMassTransform2(IntPtr obj, Transform trans);
948 */
949
950[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
951public static extern void SetCenterOfMassByPosRot2(IntPtr obj, Vector3 pos, Quaternion rot);
952
953// Add a force to the object as if its mass is one.
954[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
955public static extern void ApplyCentralForce2(IntPtr obj, Vector3 force);
956
957// Set the force being applied to the object as if its mass is one.
958[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
959public static extern void SetObjectForce2(IntPtr obj, Vector3 force);
960
961[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
962public static extern Vector3 GetTotalForce2(IntPtr obj);
963
964[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
965public static extern Vector3 GetTotalTorque2(IntPtr obj);
966
967[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
968public static extern Vector3 GetInvInertiaDiagLocal2(IntPtr obj);
969
970[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
971public static extern void SetInvInertiaDiagLocal2(IntPtr obj, Vector3 inert);
972
973[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
974public static extern void SetSleepingThresholds2(IntPtr obj, float lin_threshold, float ang_threshold);
975
976[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
977public static extern void ApplyTorque2(IntPtr obj, Vector3 torque);
978 477
979// Apply force at the given point. Will add torque to the object.
980[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 478[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
981public static extern void ApplyForce2(IntPtr obj, Vector3 force, Vector3 pos); 479public static extern bool SetVelocity2(IntPtr obj, Vector3 velocity);
982 480
983// Apply impulse to the object. Same as "ApplycentralForce" but force scaled by object's mass.
984[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 481[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
985public static extern void ApplyCentralImpulse2(IntPtr obj, Vector3 imp); 482public static extern bool SetAngularVelocity2(IntPtr obj, Vector3 angularVelocity);
986 483
987// Apply impulse to the object's torque. Force is scaled by object's mass.
988[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 484[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
989public static extern void ApplyTorqueImpulse2(IntPtr obj, Vector3 imp); 485public static extern bool SetObjectForce2(IntPtr obj, Vector3 force);
990 486
991// Apply impulse at the point given. For is scaled by object's mass and effects both linear and angular forces.
992[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 487[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
993public static extern void ApplyImpulse2(IntPtr obj, Vector3 imp, Vector3 pos); 488public static extern bool AddObjectForce2(IntPtr obj, Vector3 force);
994 489
995[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 490[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
996public static extern void ClearForces2(IntPtr obj); 491public static extern bool SetCcdMotionThreshold2(IntPtr obj, float val);
997 492
998[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 493[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
999public static extern void ClearAllForces2(IntPtr obj); 494public static extern bool SetCcdSweepSphereRadius2(IntPtr obj, float val);
1000 495
1001[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 496[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1002public static extern void UpdateInertiaTensor2(IntPtr obj); 497public static extern bool SetDamping2(IntPtr obj, float lin_damping, float ang_damping);
1003 498
1004[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 499[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1005public static extern Vector3 GetCenterOfMassPosition2(IntPtr obj); 500public static extern bool SetDeactivationTime2(IntPtr obj, float val);
1006 501
1007 /*
1008[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 502[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1009public static extern Transform GetCenterOfMassTransform2(IntPtr obj); 503public static extern bool SetSleepingThresholds2(IntPtr obj, float lin_threshold, float ang_threshold);
1010 */
1011 504
1012[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 505[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1013public static extern Vector3 GetLinearVelocity2(IntPtr obj); 506public static extern bool SetContactProcessingThreshold2(IntPtr obj, float val);
1014 507
1015[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 508[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1016public static extern Vector3 GetAngularVelocity2(IntPtr obj); 509public static extern bool SetFriction2(IntPtr obj, float val);
1017 510
1018[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 511[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1019public static extern void SetLinearVelocity2(IntPtr obj, Vector3 val); 512public static extern bool SetRestitution2(IntPtr obj, float val);
1020 513
1021[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 514[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1022public static extern void SetAngularVelocity2(IntPtr obj, Vector3 angularVelocity); 515public static extern bool SetLinearVelocity2(IntPtr obj, Vector3 val);
1023 516
1024[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 517[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1025public static extern Vector3 GetVelocityInLocalPoint2(IntPtr obj, Vector3 pos); 518public static extern bool SetInterpolation2(IntPtr obj, Vector3 lin, Vector3 ang);
1026 519
1027[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 520[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1028public static extern void Translate2(IntPtr obj, Vector3 trans); 521public static extern CollisionFlags GetCollisionFlags2(IntPtr obj);
1029
1030[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1031public static extern void UpdateDeactivation2(IntPtr obj, float timeStep);
1032
1033[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1034public static extern bool WantsSleeping2(IntPtr obj);
1035
1036[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1037public static extern void SetAngularFactor2(IntPtr obj, float factor);
1038
1039[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1040public static extern void SetAngularFactorV2(IntPtr obj, Vector3 factor);
1041
1042[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1043public static extern Vector3 GetAngularFactor2(IntPtr obj);
1044
1045[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1046public static extern bool IsInWorld2(IntPtr obj);
1047
1048[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1049public static extern void AddConstraintRef2(IntPtr obj, IntPtr constrain);
1050
1051[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1052public static extern void RemoveConstraintRef2(IntPtr obj, IntPtr constrain);
1053
1054[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1055public static extern IntPtr GetConstraintRef2(IntPtr obj, int index);
1056
1057[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1058public static extern int GetNumConstraintRefs2(IntPtr obj);
1059
1060[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1061public static extern void SetCollisionFilterMask2(IntPtr body, uint filter, uint mask);
1062
1063// =====================================================================================
1064// btCollisionShape entries
1065
1066[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1067public static extern float GetAngularMotionDisc2(IntPtr shape);
1068
1069[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1070public static extern float GetContactBreakingThreshold2(IntPtr shape, float defaultFactor);
1071
1072[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1073public static extern bool IsPolyhedral2(IntPtr shape);
1074
1075[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1076public static extern bool IsConvex2d2(IntPtr shape);
1077
1078[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1079public static extern bool IsConvex2(IntPtr shape);
1080
1081[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1082public static extern bool IsNonMoving2(IntPtr shape);
1083
1084[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1085public static extern bool IsConcave2(IntPtr shape);
1086
1087[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1088public static extern bool IsCompound2(IntPtr shape);
1089
1090[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1091public static extern bool IsSoftBody2(IntPtr shape);
1092
1093[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1094public static extern bool IsInfinite2(IntPtr shape);
1095 522
1096[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 523[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1097public static extern void SetLocalScaling2(IntPtr shape, Vector3 scale); 524public static extern IntPtr SetCollisionFlags2(IntPtr obj, CollisionFlags flags);
1098 525
1099[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 526[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1100public static extern Vector3 GetLocalScaling2(IntPtr shape); 527public static extern IntPtr AddToCollisionFlags2(IntPtr obj, CollisionFlags flags);
1101 528
1102[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 529[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1103public static extern Vector3 CalculateLocalInertia2(IntPtr shape, float mass); 530public static extern IntPtr RemoveFromCollisionFlags2(IntPtr obj, CollisionFlags flags);
1104 531
1105[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 532[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1106public static extern int GetShapeType2(IntPtr shape); 533public static extern bool SetMassProps2(IntPtr obj, float mass, Vector3 inertia);
1107 534
1108[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 535[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1109public static extern void SetMargin2(IntPtr shape, float val); 536public static extern bool UpdateInertiaTensor2(IntPtr obj);
1110 537
1111[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 538[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1112public static extern float GetMargin2(IntPtr shape); 539public static extern bool SetGravity2(IntPtr obj, Vector3 val);
1113 540
1114// =====================================================================================
1115// Debugging
1116[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 541[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1117public static extern void DumpRigidBody2(IntPtr sim, IntPtr collisionObject); 542public static extern IntPtr ClearForces2(IntPtr obj);
1118 543
1119[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 544[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1120public static extern void DumpCollisionShape2(IntPtr sim, IntPtr collisionShape); 545public static extern IntPtr ClearAllForces2(IntPtr obj);
1121 546
1122[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 547[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1123public static extern void DumpConstraint2(IntPtr sim, IntPtr constrain); 548public static extern bool SetMargin2(IntPtr obj, float val);
1124 549
1125[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 550[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1126public static extern void DumpAllInfo2(IntPtr sim); 551public static extern bool UpdateSingleAabb2(IntPtr world, IntPtr obj);
1127 552
1128[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 553[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1129public static extern void DumpMapInfo2(IntPtr sim, IntPtr manInfo); 554public static extern bool DestroyObject2(IntPtr world, uint id);
1130 555
1131[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 556[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1132public static extern void DumpPhysicsStatistics2(IntPtr sim); 557public static extern void DumpPhysicsStatistics2(IntPtr sim);
diff --git a/OpenSim/Region/Physics/Manager/PhysicsActor.cs b/OpenSim/Region/Physics/Manager/PhysicsActor.cs
index 5af6373..14f65b8 100644
--- a/OpenSim/Region/Physics/Manager/PhysicsActor.cs
+++ b/OpenSim/Region/Physics/Manager/PhysicsActor.cs
@@ -340,12 +340,6 @@ namespace OpenSim.Region.Physics.Manager
340 /// Getting this returns the velocity calculated by physics scene updates, using factors such as target velocity, 340 /// Getting this returns the velocity calculated by physics scene updates, using factors such as target velocity,
341 /// time to accelerate and collisions. 341 /// time to accelerate and collisions.
342 /// </remarks> 342 /// </remarks>
343 public virtual Vector3 TargetVelocity
344 {
345 get { return Velocity; }
346 set { Velocity = value; }
347 }
348
349 public abstract Vector3 Velocity { get; set; } 343 public abstract Vector3 Velocity { get; set; }
350 344
351 public abstract Vector3 Torque { get; set; } 345 public abstract Vector3 Torque { get; set; }
diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
index c736557..f3b0630 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
@@ -100,7 +100,7 @@ namespace OpenSim.Region.Physics.OdePlugin
100 private bool m_hackSentFly = false; 100 private bool m_hackSentFly = false;
101 private int m_requestedUpdateFrequency = 0; 101 private int m_requestedUpdateFrequency = 0;
102 private Vector3 m_taintPosition; 102 private Vector3 m_taintPosition;
103 internal bool m_avatarplanted = false; 103
104 /// <summary> 104 /// <summary>
105 /// Hold set forces so we can process them outside physics calculations. This prevents race conditions if we set force 105 /// Hold set forces so we can process them outside physics calculations. This prevents race conditions if we set force
106 /// while calculatios are going on 106 /// while calculatios are going on
@@ -413,7 +413,7 @@ namespace OpenSim.Region.Physics.OdePlugin
413 set 413 set
414 { 414 {
415 m_iscollidingObj = value; 415 m_iscollidingObj = value;
416 if (value && !m_avatarplanted) 416 if (value)
417 m_pidControllerActive = false; 417 m_pidControllerActive = false;
418 else 418 else
419 m_pidControllerActive = true; 419 m_pidControllerActive = true;
diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
index a59f63f..2e78de5 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
@@ -67,14 +67,6 @@ namespace OpenSim.Region.Physics.OdePlugin
67 private int m_expectedCollisionContacts = 0; 67 private int m_expectedCollisionContacts = 0;
68 68
69 /// <summary> 69 /// <summary>
70 /// Gets collide bits so that we can still perform land collisions if a mesh fails to load.
71 /// </summary>
72 private int BadMeshAssetCollideBits
73 {
74 get { return m_isphysical ? (int)CollisionCategories.Land : 0; }
75 }
76
77 /// <summary>
78 /// Is this prim subject to physics? Even if not, it's still solid for collision purposes. 70 /// Is this prim subject to physics? Even if not, it's still solid for collision purposes.
79 /// </summary> 71 /// </summary>
80 public override bool IsPhysical 72 public override bool IsPhysical
@@ -164,7 +156,7 @@ namespace OpenSim.Region.Physics.OdePlugin
164 156
165 private PrimitiveBaseShape _pbs; 157 private PrimitiveBaseShape _pbs;
166 private OdeScene _parent_scene; 158 private OdeScene _parent_scene;
167 159
168 /// <summary> 160 /// <summary>
169 /// The physics space which contains prim geometries 161 /// The physics space which contains prim geometries
170 /// </summary> 162 /// </summary>
@@ -3341,6 +3333,7 @@ Console.WriteLine(" JointCreateFixed");
3341 m_material = pMaterial; 3333 m_material = pMaterial;
3342 } 3334 }
3343 3335
3336
3344 private void CheckMeshAsset() 3337 private void CheckMeshAsset()
3345 { 3338 {
3346 if (_pbs.SculptEntry && !m_assetFailed && _pbs.SculptTexture != UUID.Zero) 3339 if (_pbs.SculptEntry && !m_assetFailed && _pbs.SculptTexture != UUID.Zero)
@@ -3350,14 +3343,14 @@ Console.WriteLine(" JointCreateFixed");
3350 { 3343 {
3351 RequestAssetDelegate assetProvider = _parent_scene.RequestAssetMethod; 3344 RequestAssetDelegate assetProvider = _parent_scene.RequestAssetMethod;
3352 if (assetProvider != null) 3345 if (assetProvider != null)
3353 assetProvider(_pbs.SculptTexture, MeshAssetReceived); 3346 assetProvider(_pbs.SculptTexture, MeshAssetReveived);
3354 }); 3347 });
3355 } 3348 }
3356 } 3349 }
3357 3350
3358 private void MeshAssetReceived(AssetBase asset) 3351 void MeshAssetReveived(AssetBase asset)
3359 { 3352 {
3360 if (asset != null && asset.Data != null && asset.Data.Length > 0) 3353 if (asset.Data != null && asset.Data.Length > 0)
3361 { 3354 {
3362 if (!_pbs.SculptEntry) 3355 if (!_pbs.SculptEntry)
3363 return; 3356 return;
@@ -3370,12 +3363,6 @@ Console.WriteLine(" JointCreateFixed");
3370 m_taintshape = true; 3363 m_taintshape = true;
3371 _parent_scene.AddPhysicsActorTaint(this); 3364 _parent_scene.AddPhysicsActorTaint(this);
3372 } 3365 }
3373 else
3374 {
3375 m_log.WarnFormat(
3376 "[ODE PRIM]: Could not get mesh/sculpt asset {0} for {1} at {2} in {3}",
3377 _pbs.SculptTexture, Name, _position, _parent_scene.Name);
3378 }
3379 } 3366 }
3380 } 3367 }
3381} 3368} \ No newline at end of file
diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
index d53bd90..7a50c4c 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
@@ -501,8 +501,6 @@ namespace OpenSim.Region.Physics.OdePlugin
501 public int physics_logging_interval = 0; 501 public int physics_logging_interval = 0;
502 public bool physics_logging_append_existing_logfile = false; 502 public bool physics_logging_append_existing_logfile = false;
503 503
504 private bool avplanted = false;
505 private bool av_av_collisions_off = false;
506 504
507 public d.Vector3 xyz = new d.Vector3(128.1640f, 128.3079f, 25.7600f); 505 public d.Vector3 xyz = new d.Vector3(128.1640f, 128.3079f, 25.7600f);
508 public d.Vector3 hpr = new d.Vector3(125.5000f, -17.0000f, 0.0000f); 506 public d.Vector3 hpr = new d.Vector3(125.5000f, -17.0000f, 0.0000f);
@@ -646,9 +644,6 @@ namespace OpenSim.Region.Physics.OdePlugin
646 avMovementDivisorWalk = physicsconfig.GetFloat("av_movement_divisor_walk", 1.3f); 644 avMovementDivisorWalk = physicsconfig.GetFloat("av_movement_divisor_walk", 1.3f);
647 avMovementDivisorRun = physicsconfig.GetFloat("av_movement_divisor_run", 0.8f); 645 avMovementDivisorRun = physicsconfig.GetFloat("av_movement_divisor_run", 0.8f);
648 avCapRadius = physicsconfig.GetFloat("av_capsule_radius", 0.37f); 646 avCapRadius = physicsconfig.GetFloat("av_capsule_radius", 0.37f);
649 avplanted = physicsconfig.GetBoolean("av_planted", false);
650 av_av_collisions_off = physicsconfig.GetBoolean("av_av_collisions_off", false);
651
652 IsAvCapsuleTilted = physicsconfig.GetBoolean("av_capsule_tilted", false); 647 IsAvCapsuleTilted = physicsconfig.GetBoolean("av_capsule_tilted", false);
653 648
654 contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", 80); 649 contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", 80);
@@ -668,8 +663,6 @@ namespace OpenSim.Region.Physics.OdePlugin
668 meshSculptLOD = physicsconfig.GetFloat("mesh_lod", 32f); 663 meshSculptLOD = physicsconfig.GetFloat("mesh_lod", 32f);
669 MeshSculptphysicalLOD = physicsconfig.GetFloat("mesh_physical_lod", 16f); 664 MeshSculptphysicalLOD = physicsconfig.GetFloat("mesh_physical_lod", 16f);
670 m_filterCollisions = physicsconfig.GetBoolean("filter_collisions", false); 665 m_filterCollisions = physicsconfig.GetBoolean("filter_collisions", false);
671
672
673 666
674 if (Environment.OSVersion.Platform == PlatformID.Unix) 667 if (Environment.OSVersion.Platform == PlatformID.Unix)
675 { 668 {
@@ -1316,10 +1309,6 @@ namespace OpenSim.Region.Physics.OdePlugin
1316 if ((p1 is OdePrim) && (((OdePrim)p1).m_isVolumeDetect)) 1309 if ((p1 is OdePrim) && (((OdePrim)p1).m_isVolumeDetect))
1317 skipThisContact = true; // No collision on volume detect prims 1310 skipThisContact = true; // No collision on volume detect prims
1318 1311
1319 if (av_av_collisions_off)
1320 if ((p1 is OdeCharacter) && (p2 is OdeCharacter))
1321 skipThisContact = true;
1322
1323 if (!skipThisContact && (p2 is OdePrim) && (((OdePrim)p2).m_isVolumeDetect)) 1312 if (!skipThisContact && (p2 is OdePrim) && (((OdePrim)p2).m_isVolumeDetect))
1324 skipThisContact = true; // No collision on volume detect prims 1313 skipThisContact = true; // No collision on volume detect prims
1325 1314
@@ -1983,8 +1972,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1983 1972
1984 newAv.Flying = isFlying; 1973 newAv.Flying = isFlying;
1985 newAv.MinimumGroundFlightOffset = minimumGroundFlightOffset; 1974 newAv.MinimumGroundFlightOffset = minimumGroundFlightOffset;
1986 newAv.m_avatarplanted = avplanted; 1975
1987
1988 return newAv; 1976 return newAv;
1989 } 1977 }
1990 1978
@@ -1999,7 +1987,6 @@ namespace OpenSim.Region.Physics.OdePlugin
1999 1987
2000 internal void AddCharacter(OdeCharacter chr) 1988 internal void AddCharacter(OdeCharacter chr)
2001 { 1989 {
2002 chr.m_avatarplanted = avplanted;
2003 if (!_characters.Contains(chr)) 1990 if (!_characters.Contains(chr))
2004 { 1991 {
2005 _characters.Add(chr); 1992 _characters.Add(chr);
@@ -4320,4 +4307,4 @@ namespace OpenSim.Region.Physics.OdePlugin
4320 m_stats[ODEPrimUpdateFrameMsStatName] = 0; 4307 m_stats[ODEPrimUpdateFrameMsStatName] = 0;
4321 } 4308 }
4322 } 4309 }
4323} 4310} \ No newline at end of file
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
index 905540d..3144d76 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
+++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
@@ -39,8 +39,11 @@ using OpenSim.Framework.Console;
39using OpenSim.Region.Physics.Manager; 39using OpenSim.Region.Physics.Manager;
40using Mono.Addins; 40using Mono.Addins;
41 41
42[assembly: Addin("RegionCombinerModule", "0.1")]
43[assembly: AddinDependency("OpenSim", "0.5")]
42namespace OpenSim.Region.RegionCombinerModule 44namespace OpenSim.Region.RegionCombinerModule
43{ 45{
46 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
44 public class RegionCombinerModule : ISharedRegionModule, IRegionCombinerModule 47 public class RegionCombinerModule : ISharedRegionModule, IRegionCombinerModule
45 { 48 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -719,21 +722,21 @@ namespace OpenSim.Region.RegionCombinerModule
719 rootConn.ClientEventForwarder = new RegionCombinerClientEventForwarder(rootConn); 722 rootConn.ClientEventForwarder = new RegionCombinerClientEventForwarder(rootConn);
720 723
721 // Sets up the CoarseLocationUpdate forwarder for this root region 724 // Sets up the CoarseLocationUpdate forwarder for this root region
722 scene.EventManager.OnNewPresence += SetCoarseLocationDelegate; 725 scene.EventManager.OnNewPresence += SetCourseLocationDelegate;
723 726
724 // Adds this root region to a dictionary of regions that are connectable 727 // Adds this root region to a dictionary of regions that are connectable
725 m_regions.Add(scene.RegionInfo.originRegionID, rootConn); 728 m_regions.Add(scene.RegionInfo.originRegionID, rootConn);
726 } 729 }
727 } 730 }
728 731
729 private void SetCoarseLocationDelegate(ScenePresence presence) 732 private void SetCourseLocationDelegate(ScenePresence presence)
730 { 733 {
731 presence.SetSendCoarseLocationMethod(SendCoarseLocationUpdates); 734 presence.SetSendCourseLocationMethod(SendCourseLocationUpdates);
732 } 735 }
733 736
734 // This delegate was refactored for non-combined regions. 737 // This delegate was refactored for non-combined regions.
735 // This combined region version will not use the pre-compiled lists of locations and ids 738 // This combined region version will not use the pre-compiled lists of locations and ids
736 private void SendCoarseLocationUpdates(UUID sceneId, ScenePresence presence, List<Vector3> coarseLocations, List<UUID> avatarUUIDs) 739 private void SendCourseLocationUpdates(UUID sceneId, ScenePresence presence, List<Vector3> coarseLocations, List<UUID> avatarUUIDs)
737 { 740 {
738 RegionConnections connectiondata = null; 741 RegionConnections connectiondata = null;
739 lock (m_regions) 742 lock (m_regions)
@@ -756,18 +759,18 @@ namespace OpenSim.Region.RegionCombinerModule
756 } 759 }
757 }); 760 });
758 761
759 DistributeCoarseLocationUpdates(CoarseLocations, AvatarUUIDs, connectiondata, presence); 762 DistributeCourseLocationUpdates(CoarseLocations, AvatarUUIDs, connectiondata, presence);
760 } 763 }
761 764
762 private void DistributeCoarseLocationUpdates(List<Vector3> locations, List<UUID> uuids, 765 private void DistributeCourseLocationUpdates(List<Vector3> locations, List<UUID> uuids,
763 RegionConnections connectiondata, ScenePresence rootPresence) 766 RegionConnections connectiondata, ScenePresence rootPresence)
764 { 767 {
765 RegionData[] rdata = connectiondata.ConnectedRegions.ToArray(); 768 RegionData[] rdata = connectiondata.ConnectedRegions.ToArray();
766 //List<IClientAPI> clients = new List<IClientAPI>(); 769 //List<IClientAPI> clients = new List<IClientAPI>();
767 Dictionary<Vector2, RegionCoarseLocationStruct> updates = new Dictionary<Vector2, RegionCoarseLocationStruct>(); 770 Dictionary<Vector2, RegionCourseLocationStruct> updates = new Dictionary<Vector2, RegionCourseLocationStruct>();
768 771
769 // Root Region entry 772 // Root Region entry
770 RegionCoarseLocationStruct rootupdatedata = new RegionCoarseLocationStruct(); 773 RegionCourseLocationStruct rootupdatedata = new RegionCourseLocationStruct();
771 rootupdatedata.Locations = new List<Vector3>(); 774 rootupdatedata.Locations = new List<Vector3>();
772 rootupdatedata.Uuids = new List<UUID>(); 775 rootupdatedata.Uuids = new List<UUID>();
773 rootupdatedata.Offset = Vector2.Zero; 776 rootupdatedata.Offset = Vector2.Zero;
@@ -781,7 +784,7 @@ namespace OpenSim.Region.RegionCombinerModule
781 foreach (RegionData regiondata in rdata) 784 foreach (RegionData regiondata in rdata)
782 { 785 {
783 Vector2 offset = new Vector2(regiondata.Offset.X, regiondata.Offset.Y); 786 Vector2 offset = new Vector2(regiondata.Offset.X, regiondata.Offset.Y);
784 RegionCoarseLocationStruct updatedata = new RegionCoarseLocationStruct(); 787 RegionCourseLocationStruct updatedata = new RegionCourseLocationStruct();
785 updatedata.Locations = new List<Vector3>(); 788 updatedata.Locations = new List<Vector3>();
786 updatedata.Uuids = new List<UUID>(); 789 updatedata.Uuids = new List<UUID>();
787 updatedata.Offset = offset; 790 updatedata.Offset = offset;
@@ -807,7 +810,7 @@ namespace OpenSim.Region.RegionCombinerModule
807 if (!updates.ContainsKey(offset)) 810 if (!updates.ContainsKey(offset))
808 { 811 {
809 // This shouldn't happen 812 // This shouldn't happen
810 RegionCoarseLocationStruct updatedata = new RegionCoarseLocationStruct(); 813 RegionCourseLocationStruct updatedata = new RegionCourseLocationStruct();
811 updatedata.Locations = new List<Vector3>(); 814 updatedata.Locations = new List<Vector3>();
812 updatedata.Uuids = new List<UUID>(); 815 updatedata.Uuids = new List<UUID>();
813 updatedata.Offset = offset; 816 updatedata.Offset = offset;
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCourseLocation.cs b/OpenSim/Region/RegionCombinerModule/RegionCourseLocation.cs
index 224ac99..53a678f 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionCourseLocation.cs
+++ b/OpenSim/Region/RegionCombinerModule/RegionCourseLocation.cs
@@ -33,7 +33,7 @@ using OpenSim.Framework;
33namespace OpenSim.Region.RegionCombinerModule 33namespace OpenSim.Region.RegionCombinerModule
34{ 34{
35 35
36 struct RegionCoarseLocationStruct 36 struct RegionCourseLocationStruct
37 { 37 {
38 public List<Vector3> Locations; 38 public List<Vector3> Locations;
39 public List<UUID> Uuids; 39 public List<UUID> Uuids;
diff --git a/OpenSim/Region/RegionCombinerModule/Resources/RegionCombinerModule.addin.xml b/OpenSim/Region/RegionCombinerModule/Resources/RegionCombinerModule.addin.xml
deleted file mode 100644
index 13cb8b6..0000000
--- a/OpenSim/Region/RegionCombinerModule/Resources/RegionCombinerModule.addin.xml
+++ /dev/null
@@ -1,14 +0,0 @@
1<Addin id="OpenSim.RegionModules.RegionCombinerModule" version="0.3">
2 <Runtime>
3 <Import assembly="OpenSim.Region.RegionCombinerModule.dll"/>
4 </Runtime>
5
6 <Dependencies>
7 <Addin id="OpenSim" version="0.5" />
8 </Dependencies>
9
10 <Extension path = "/OpenSim/RegionModules">
11 <RegionModule id="RegionCombinerModule" type="OpenSim.Region.RegionCombinerModule.RegionCombinerModule" />
12 </Extension>
13
14</Addin>
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 3bbdbe8..82de06f 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -59,7 +59,6 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
59using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; 59using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
60using PrimType = OpenSim.Region.Framework.Scenes.PrimType; 60using PrimType = OpenSim.Region.Framework.Scenes.PrimType;
61using AssetLandmark = OpenSim.Framework.AssetLandmark; 61using AssetLandmark = OpenSim.Framework.AssetLandmark;
62using RegionFlags = OpenSim.Framework.RegionFlags;
63 62
64using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; 63using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
65using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; 64using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
@@ -113,7 +112,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
113 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache = 112 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache =
114 new Dictionary<UUID, UserInfoCacheEntry>(); 113 new Dictionary<UUID, UserInfoCacheEntry>();
115 protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp. 114 protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp.
116 protected ISoundModule m_SoundModule = null;
117 115
118// protected Timer m_ShoutSayTimer; 116// protected Timer m_ShoutSayTimer;
119 protected int m_SayShoutCount = 0; 117 protected int m_SayShoutCount = 0;
@@ -161,7 +159,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
161 m_TransferModule = 159 m_TransferModule =
162 m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>(); 160 m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>();
163 m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>(); 161 m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>();
164 m_SoundModule = m_ScriptEngine.World.RequestModuleInterface<ISoundModule>();
165 162
166 AsyncCommands = new AsyncCommandManager(ScriptEngine); 163 AsyncCommands = new AsyncCommandManager(ScriptEngine);
167 } 164 }
@@ -344,7 +341,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
344 return GetLinkParts(m_host, linkType); 341 return GetLinkParts(m_host, linkType);
345 } 342 }
346 343
347 public static List<SceneObjectPart> GetLinkParts(SceneObjectPart part, int linkType) 344 private List<SceneObjectPart> GetLinkParts(SceneObjectPart part, int linkType)
348 { 345 {
349 List<SceneObjectPart> ret = new List<SceneObjectPart>(); 346 List<SceneObjectPart> ret = new List<SceneObjectPart>();
350 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) 347 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
@@ -429,40 +426,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
429 return key; 426 return key;
430 } 427 }
431 428
432 /// <summary> 429 // convert a LSL_Rotation to a Quaternion
433 /// Return the UUID of the asset matching the specified key or name 430 public static Quaternion Rot2Quaternion(LSL_Rotation r)
434 /// and asset type.
435 /// </summary>
436 /// <param name="k"></param>
437 /// <param name="type"></param>
438 /// <returns></returns>
439 protected UUID KeyOrName(string k, AssetType type)
440 { 431 {
441 UUID key; 432 Quaternion q = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s);
442 433 q.Normalize();
443 if (!UUID.TryParse(k, out key)) 434 return q;
444 {
445 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(k);
446 if (item != null && item.Type == (int)type)
447 key = item.AssetID;
448 }
449 else
450 {
451 lock (m_host.TaskInventory)
452 {
453 foreach (KeyValuePair<UUID, TaskInventoryItem> item in m_host.TaskInventory)
454 {
455 if (item.Value.Type == (int)type && item.Value.Name == k)
456 {
457 key = item.Value.ItemID;
458 break;
459 }
460 }
461 }
462 }
463
464
465 return key;
466 } 435 }
467 436
468 //These are the implementations of the various ll-functions used by the LSL scripts. 437 //These are the implementations of the various ll-functions used by the LSL scripts.
@@ -1271,7 +1240,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1271 public LSL_Float llGround(LSL_Vector offset) 1240 public LSL_Float llGround(LSL_Vector offset)
1272 { 1241 {
1273 m_host.AddScriptLPS(1); 1242 m_host.AddScriptLPS(1);
1274 Vector3 pos = m_host.GetWorldPosition() + (Vector3)offset; 1243 Vector3 pos = m_host.GetWorldPosition() + new Vector3((float)offset.x,
1244 (float)offset.y,
1245 (float)offset.z);
1275 1246
1276 //Get the slope normal. This gives us the equation of the plane tangent to the slope. 1247 //Get the slope normal. This gives us the equation of the plane tangent to the slope.
1277 LSL_Vector vsn = llGroundNormal(offset); 1248 LSL_Vector vsn = llGroundNormal(offset);
@@ -1521,22 +1492,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1521 if (part == null || part.ParentGroup.IsDeleted) 1492 if (part == null || part.ParentGroup.IsDeleted)
1522 return; 1493 return;
1523 1494
1524 // First we need to check whether or not we need to clamp the size of a physics-enabled prim 1495 if (scale.x < 0.01)
1496 scale.x = 0.01;
1497 if (scale.y < 0.01)
1498 scale.y = 0.01;
1499 if (scale.z < 0.01)
1500 scale.z = 0.01;
1501
1525 PhysicsActor pa = part.ParentGroup.RootPart.PhysActor; 1502 PhysicsActor pa = part.ParentGroup.RootPart.PhysActor;
1503
1526 if (pa != null && pa.IsPhysical) 1504 if (pa != null && pa.IsPhysical)
1527 { 1505 {
1528 scale.x = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.x)); 1506 if (scale.x > World.m_maxPhys)
1529 scale.y = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.y)); 1507 scale.x = World.m_maxPhys;
1530 scale.z = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.z)); 1508 if (scale.y > World.m_maxPhys)
1531 } 1509 scale.y = World.m_maxPhys;
1532 else 1510 if (scale.z > World.m_maxPhys)
1533 { 1511 scale.z = World.m_maxPhys;
1534 // If not physical, then we clamp the scale to the non-physical min/max
1535 scale.x = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.x));
1536 scale.y = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.y));
1537 scale.z = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.z));
1538 } 1512 }
1539 1513
1514 if (scale.x > World.m_maxNonphys)
1515 scale.x = World.m_maxNonphys;
1516 if (scale.y > World.m_maxNonphys)
1517 scale.y = World.m_maxNonphys;
1518 if (scale.z > World.m_maxNonphys)
1519 scale.z = World.m_maxNonphys;
1520
1540 Vector3 tmp = part.Scale; 1521 Vector3 tmp = part.Scale;
1541 tmp.X = (float)scale.x; 1522 tmp.X = (float)scale.x;
1542 tmp.Y = (float)scale.y; 1523 tmp.Y = (float)scale.y;
@@ -1609,7 +1590,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1609 if (face == ScriptBaseClass.ALL_SIDES) 1590 if (face == ScriptBaseClass.ALL_SIDES)
1610 face = SceneObjectPart.ALL_SIDES; 1591 face = SceneObjectPart.ALL_SIDES;
1611 1592
1612 m_host.SetFaceColorAlpha(face, color, null); 1593 m_host.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face);
1613 } 1594 }
1614 1595
1615 public void SetTexGen(SceneObjectPart part, int face,int style) 1596 public void SetTexGen(SceneObjectPart part, int face,int style)
@@ -2221,7 +2202,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2221 pos.x > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a east-adjacent region. 2202 pos.x > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a east-adjacent region.
2222 pos.y < -10.0 || // return FALSE if more than 10 meters into a south-adjacent region. 2203 pos.y < -10.0 || // return FALSE if more than 10 meters into a south-adjacent region.
2223 pos.y > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a north-adjacent region. 2204 pos.y > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a north-adjacent region.
2224 pos.z > Constants.RegionHeight // return FALSE if altitude than 4096m 2205 pos.z > 4096 // return FALSE if altitude than 4096m
2225 ) 2206 )
2226 ) 2207 )
2227 { 2208 {
@@ -2232,15 +2213,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2232 // this could possibly be done in the above else-if block, but we're doing the check here to keep the code easier to read. 2213 // this could possibly be done in the above else-if block, but we're doing the check here to keep the code easier to read.
2233 2214
2234 Vector3 objectPos = m_host.ParentGroup.RootPart.AbsolutePosition; 2215 Vector3 objectPos = m_host.ParentGroup.RootPart.AbsolutePosition;
2235 LandData here = World.GetLandData(objectPos); 2216 LandData here = World.GetLandData((float)objectPos.X, (float)objectPos.Y);
2236 LandData there = World.GetLandData(pos); 2217 LandData there = World.GetLandData((float)pos.x, (float)pos.y);
2237 2218
2238 // we're only checking prim limits if it's moving to a different parcel under the assumption that if the object got onto the parcel without exceeding the prim limits. 2219 // we're only checking prim limits if it's moving to a different parcel under the assumption that if the object got onto the parcel without exceeding the prim limits.
2239 2220
2240 bool sameParcel = here.GlobalID == there.GlobalID; 2221 bool sameParcel = here.GlobalID == there.GlobalID;
2241 2222
2242 if (!sameParcel && !World.Permissions.CanRezObject( 2223 if (!sameParcel && !World.Permissions.CanObjectEntry(m_host.UUID, false, new Vector3((float)pos.x, (float)pos.y, (float)pos.z)))
2243 m_host.ParentGroup.PrimCount, m_host.ParentGroup.OwnerID, pos))
2244 { 2224 {
2245 return 0; 2225 return 0;
2246 } 2226 }
@@ -2299,15 +2279,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2299 if (part.ParentGroup.RootPart == part) 2279 if (part.ParentGroup.RootPart == part)
2300 { 2280 {
2301 SceneObjectGroup parent = part.ParentGroup; 2281 SceneObjectGroup parent = part.ParentGroup;
2302 if (!World.Permissions.CanObjectEntry(parent.UUID, false, (Vector3)toPos)) 2282 Vector3 dest = new Vector3((float)toPos.x, (float)toPos.y, (float)toPos.z);
2283 if (!World.Permissions.CanObjectEntry(parent.UUID, false, dest))
2303 return; 2284 return;
2304 Util.FireAndForget(delegate(object x) { 2285 Util.FireAndForget(delegate(object x) {
2305 parent.UpdateGroupPosition((Vector3)toPos); 2286 parent.UpdateGroupPosition(dest);
2306 }); 2287 });
2307 } 2288 }
2308 else 2289 else
2309 { 2290 {
2310 part.OffsetPosition = (Vector3)toPos; 2291 part.OffsetPosition = new Vector3((float)toPos.x, (float)toPos.y, (float)toPos.z);
2311 SceneObjectGroup parent = part.ParentGroup; 2292 SceneObjectGroup parent = part.ParentGroup;
2312 parent.HasGroupChanged = true; 2293 parent.HasGroupChanged = true;
2313 parent.ScheduleGroupForTerseUpdate(); 2294 parent.ScheduleGroupForTerseUpdate();
@@ -2317,7 +2298,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2317 public LSL_Vector llGetPos() 2298 public LSL_Vector llGetPos()
2318 { 2299 {
2319 m_host.AddScriptLPS(1); 2300 m_host.AddScriptLPS(1);
2320 return m_host.GetWorldPosition(); 2301 Vector3 pos = m_host.GetWorldPosition();
2302 return new LSL_Vector(pos.X, pos.Y, pos.Z);
2321 } 2303 }
2322 2304
2323 public LSL_Vector llGetLocalPos() 2305 public LSL_Vector llGetLocalPos()
@@ -2344,9 +2326,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2344 pos = part.AbsolutePosition; 2326 pos = part.AbsolutePosition;
2345 } 2327 }
2346 2328
2347// m_log.DebugFormat("[LSL API]: Returning {0} in GetPartLocalPos()", pos); 2329 return new LSL_Vector(pos.X, pos.Y, pos.Z);
2348
2349 return new LSL_Vector(pos);
2350 } 2330 }
2351 2331
2352 public void llSetRot(LSL_Rotation rot) 2332 public void llSetRot(LSL_Rotation rot)
@@ -2354,18 +2334,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2354 m_host.AddScriptLPS(1); 2334 m_host.AddScriptLPS(1);
2355 2335
2356 // try to let this work as in SL... 2336 // try to let this work as in SL...
2357 if (m_host.ParentID == 0) 2337 if (m_host.LinkNum < 2)
2358 { 2338 {
2359 // special case: If we are root, rotate complete SOG to new rotation 2339 // Special case: If we are root, rotate complete SOG to new
2360 SetRot(m_host, rot); 2340 // rotation.
2341 // We are root if the link number is 0 (single prim) or 1
2342 // (root prim). ParentID may be nonzero in attachments and
2343 // using it would cause attachments and HUDs to rotate
2344 // to the wrong positions.
2345
2346 SetRot(m_host, Rot2Quaternion(rot));
2361 } 2347 }
2362 else 2348 else
2363 { 2349 {
2364 // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask. 2350 // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask.
2365 SceneObjectPart rootPart = m_host.ParentGroup.RootPart; 2351 SceneObjectPart rootPart;
2366 if (rootPart != null) // better safe than sorry 2352 if (m_host.ParentGroup != null) // better safe than sorry
2367 { 2353 {
2368 SetRot(m_host, rootPart.RotationOffset * (Quaternion)rot); 2354 rootPart = m_host.ParentGroup.RootPart;
2355 if (rootPart != null)
2356 SetRot(m_host, rootPart.RotationOffset * Rot2Quaternion(rot));
2369 } 2357 }
2370 } 2358 }
2371 2359
@@ -2375,7 +2363,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2375 public void llSetLocalRot(LSL_Rotation rot) 2363 public void llSetLocalRot(LSL_Rotation rot)
2376 { 2364 {
2377 m_host.AddScriptLPS(1); 2365 m_host.AddScriptLPS(1);
2378 SetRot(m_host, rot); 2366
2367 SetRot(m_host, Rot2Quaternion(rot));
2379 ScriptSleep(200); 2368 ScriptSleep(200);
2380 } 2369 }
2381 2370
@@ -2487,7 +2476,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2487 if (local != 0) 2476 if (local != 0)
2488 force *= llGetRot(); 2477 force *= llGetRot();
2489 2478
2490 m_host.ParentGroup.RootPart.SetForce(force); 2479 m_host.ParentGroup.RootPart.SetForce(new Vector3((float)force.x, (float)force.y, (float)force.z));
2491 } 2480 }
2492 } 2481 }
2493 2482
@@ -2499,7 +2488,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2499 2488
2500 if (!m_host.ParentGroup.IsDeleted) 2489 if (!m_host.ParentGroup.IsDeleted)
2501 { 2490 {
2502 force = m_host.ParentGroup.RootPart.GetForce(); 2491 Vector3 tmpForce = m_host.ParentGroup.RootPart.GetForce();
2492 force.x = tmpForce.X;
2493 force.y = tmpForce.Y;
2494 force.z = tmpForce.Z;
2503 } 2495 }
2504 2496
2505 return force; 2497 return force;
@@ -2508,8 +2500,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2508 public LSL_Integer llTarget(LSL_Vector position, double range) 2500 public LSL_Integer llTarget(LSL_Vector position, double range)
2509 { 2501 {
2510 m_host.AddScriptLPS(1); 2502 m_host.AddScriptLPS(1);
2511 return m_host.ParentGroup.registerTargetWaypoint(position, 2503 return m_host.ParentGroup.registerTargetWaypoint(
2512 (float)range); 2504 new Vector3((float)position.x, (float)position.y, (float)position.z), (float)range);
2513 } 2505 }
2514 2506
2515 public void llTargetRemove(int number) 2507 public void llTargetRemove(int number)
@@ -2521,7 +2513,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2521 public LSL_Integer llRotTarget(LSL_Rotation rot, double error) 2513 public LSL_Integer llRotTarget(LSL_Rotation rot, double error)
2522 { 2514 {
2523 m_host.AddScriptLPS(1); 2515 m_host.AddScriptLPS(1);
2524 return m_host.ParentGroup.registerRotTargetWaypoint(rot, (float)error); 2516 return m_host.ParentGroup.registerRotTargetWaypoint(
2517 new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s), (float)error);
2525 } 2518 }
2526 2519
2527 public void llRotTargetRemove(int number) 2520 public void llRotTargetRemove(int number)
@@ -2533,7 +2526,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2533 public void llMoveToTarget(LSL_Vector target, double tau) 2526 public void llMoveToTarget(LSL_Vector target, double tau)
2534 { 2527 {
2535 m_host.AddScriptLPS(1); 2528 m_host.AddScriptLPS(1);
2536 m_host.MoveToTarget(target, (float)tau); 2529 m_host.MoveToTarget(new Vector3((float)target.x, (float)target.y, (float)target.z), (float)tau);
2537 } 2530 }
2538 2531
2539 public void llStopMoveToTarget() 2532 public void llStopMoveToTarget()
@@ -2546,7 +2539,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2546 { 2539 {
2547 m_host.AddScriptLPS(1); 2540 m_host.AddScriptLPS(1);
2548 //No energy force yet 2541 //No energy force yet
2549 Vector3 v = force; 2542 Vector3 v = new Vector3((float)force.x, (float)force.y, (float)force.z);
2550 if (v.Length() > 20000.0f) 2543 if (v.Length() > 20000.0f)
2551 { 2544 {
2552 v.Normalize(); 2545 v.Normalize();
@@ -2559,13 +2552,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2559 public void llApplyRotationalImpulse(LSL_Vector force, int local) 2552 public void llApplyRotationalImpulse(LSL_Vector force, int local)
2560 { 2553 {
2561 m_host.AddScriptLPS(1); 2554 m_host.AddScriptLPS(1);
2562 m_host.ParentGroup.RootPart.ApplyAngularImpulse(force, local != 0); 2555 m_host.ParentGroup.RootPart.ApplyAngularImpulse(new Vector3((float)force.x, (float)force.y, (float)force.z), local != 0);
2563 } 2556 }
2564 2557
2565 public void llSetTorque(LSL_Vector torque, int local) 2558 public void llSetTorque(LSL_Vector torque, int local)
2566 { 2559 {
2567 m_host.AddScriptLPS(1); 2560 m_host.AddScriptLPS(1);
2568 m_host.ParentGroup.RootPart.SetAngularImpulse(torque, local != 0); 2561 m_host.ParentGroup.RootPart.SetAngularImpulse(new Vector3((float)torque.x, (float)torque.y, (float)torque.z), local != 0);
2569 } 2562 }
2570 2563
2571 public LSL_Vector llGetTorque() 2564 public LSL_Vector llGetTorque()
@@ -2675,32 +2668,63 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2675 m_host.AddScriptLPS(1); 2668 m_host.AddScriptLPS(1);
2676 2669
2677 // send the sound, once, to all clients in range 2670 // send the sound, once, to all clients in range
2678 if (m_SoundModule != null) 2671 m_host.SendSound(KeyOrName(sound).ToString(), volume, false, 0, 0, false, false);
2679 {
2680 m_SoundModule.SendSound(m_host.UUID,
2681 KeyOrName(sound, AssetType.Sound), volume, false, 0,
2682 0, false, false);
2683 }
2684 } 2672 }
2685 2673
2674 // Xantor 20080528 we should do this differently.
2675 // 1) apply the sound to the object
2676 // 2) schedule full update
2677 // just sending the sound out once doesn't work so well when other avatars come in view later on
2678 // or when the prim gets moved, changed, sat on, whatever
2679 // see large number of mantises (mantes?)
2680 // 20080530 Updated to remove code duplication
2681 // 20080530 Stop sound if there is one, otherwise volume only changes don't work
2686 public void llLoopSound(string sound, double volume) 2682 public void llLoopSound(string sound, double volume)
2687 { 2683 {
2688 m_host.AddScriptLPS(1); 2684 m_host.AddScriptLPS(1);
2689 if (m_SoundModule != null) 2685
2690 { 2686 if (m_host.Sound != UUID.Zero)
2691 m_SoundModule.LoopSound(m_host.UUID, KeyOrName(sound), 2687 llStopSound();
2692 volume, 20, false); 2688
2693 } 2689 m_host.Sound = KeyOrName(sound);
2690 m_host.SoundGain = volume;
2691 m_host.SoundFlags = 1; // looping
2692 m_host.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable?
2693
2694 m_host.ScheduleFullUpdate();
2695 m_host.SendFullUpdateToAllClients();
2694 } 2696 }
2695 2697
2696 public void llLoopSoundMaster(string sound, double volume) 2698 public void llLoopSoundMaster(string sound, double volume)
2697 { 2699 {
2698 m_host.AddScriptLPS(1); 2700 m_host.AddScriptLPS(1);
2699 if (m_SoundModule != null) 2701 m_host.ParentGroup.LoopSoundMasterPrim = m_host;
2702 lock (m_host.ParentGroup.LoopSoundSlavePrims)
2700 { 2703 {
2701 m_SoundModule.LoopSound(m_host.UUID, KeyOrName(sound), 2704 foreach (SceneObjectPart prim in m_host.ParentGroup.LoopSoundSlavePrims)
2702 volume, 20, true); 2705 {
2706 if (prim.Sound != UUID.Zero)
2707 llStopSound();
2708
2709 prim.Sound = KeyOrName(sound);
2710 prim.SoundGain = volume;
2711 prim.SoundFlags = 1; // looping
2712 prim.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable?
2713
2714 prim.ScheduleFullUpdate();
2715 prim.SendFullUpdateToAllClients();
2716 }
2703 } 2717 }
2718 if (m_host.Sound != UUID.Zero)
2719 llStopSound();
2720
2721 m_host.Sound = KeyOrName(sound);
2722 m_host.SoundGain = volume;
2723 m_host.SoundFlags = 1; // looping
2724 m_host.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable?
2725
2726 m_host.ScheduleFullUpdate();
2727 m_host.SendFullUpdateToAllClients();
2704 } 2728 }
2705 2729
2706 public void llLoopSoundSlave(string sound, double volume) 2730 public void llLoopSoundSlave(string sound, double volume)
@@ -2717,39 +2741,61 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2717 m_host.AddScriptLPS(1); 2741 m_host.AddScriptLPS(1);
2718 2742
2719 // send the sound, once, to all clients in range 2743 // send the sound, once, to all clients in range
2720 if (m_SoundModule != null) 2744 m_host.SendSound(KeyOrName(sound).ToString(), volume, false, 0, 0, true, false);
2721 {
2722 m_SoundModule.SendSound(m_host.UUID,
2723 KeyOrName(sound, AssetType.Sound), volume, false, 0,
2724 0, true, false);
2725 }
2726 } 2745 }
2727 2746
2728 public void llTriggerSound(string sound, double volume) 2747 public void llTriggerSound(string sound, double volume)
2729 { 2748 {
2730 m_host.AddScriptLPS(1); 2749 m_host.AddScriptLPS(1);
2731 // send the sound, once, to all clients in rangeTrigger or play an attached sound in this part's inventory. 2750 // send the sound, once, to all clients in range
2732 if (m_SoundModule != null) 2751 m_host.SendSound(KeyOrName(sound).ToString(), volume, true, 0, 0, false, false);
2733 {
2734 m_SoundModule.SendSound(m_host.UUID,
2735 KeyOrName(sound, AssetType.Sound), volume, true, 0, 0,
2736 false, false);
2737 }
2738 } 2752 }
2739 2753
2754 // Xantor 20080528: Clear prim data of sound instead
2740 public void llStopSound() 2755 public void llStopSound()
2741 { 2756 {
2742 m_host.AddScriptLPS(1); 2757 m_host.AddScriptLPS(1);
2743 2758 if (m_host.ParentGroup.LoopSoundSlavePrims.Contains(m_host))
2744 if (m_SoundModule != null) 2759 {
2745 m_SoundModule.StopSound(m_host.UUID); 2760 if (m_host.ParentGroup.LoopSoundMasterPrim == m_host)
2761 {
2762 foreach (SceneObjectPart part in m_host.ParentGroup.LoopSoundSlavePrims)
2763 {
2764 part.Sound = UUID.Zero;
2765 part.SoundGain = 0;
2766 part.SoundFlags = 0;
2767 part.SoundRadius = 0;
2768 part.ScheduleFullUpdate();
2769 part.SendFullUpdateToAllClients();
2770 }
2771 m_host.ParentGroup.LoopSoundMasterPrim = null;
2772 m_host.ParentGroup.LoopSoundSlavePrims.Clear();
2773 }
2774 else
2775 {
2776 m_host.Sound = UUID.Zero;
2777 m_host.SoundGain = 0;
2778 m_host.SoundFlags = 0;
2779 m_host.SoundRadius = 0;
2780 m_host.ScheduleFullUpdate();
2781 m_host.SendFullUpdateToAllClients();
2782 }
2783 }
2784 else
2785 {
2786 m_host.Sound = UUID.Zero;
2787 m_host.SoundGain = 0;
2788 m_host.SoundFlags = 0;
2789 m_host.SoundRadius = 0;
2790 m_host.ScheduleFullUpdate();
2791 m_host.SendFullUpdateToAllClients();
2792 }
2746 } 2793 }
2747 2794
2748 public void llPreloadSound(string sound) 2795 public void llPreloadSound(string sound)
2749 { 2796 {
2750 m_host.AddScriptLPS(1); 2797 m_host.AddScriptLPS(1);
2751 if (m_SoundModule != null) 2798 m_host.PreloadSound(sound);
2752 m_SoundModule.PreloadSound(m_host.UUID, KeyOrName(sound), 0);
2753 ScriptSleep(1000); 2799 ScriptSleep(1000);
2754 } 2800 }
2755 2801
@@ -3077,10 +3123,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3077 return; 3123 return;
3078 } 3124 }
3079 3125
3126 Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
3127 Vector3 llvel = new Vector3((float)vel.x, (float)vel.y, (float)vel.z);
3128
3080 // need the magnitude later 3129 // need the magnitude later
3081 // float velmag = (float)Util.GetMagnitude(llvel); 3130 // float velmag = (float)Util.GetMagnitude(llvel);
3082 3131
3083 SceneObjectGroup new_group = World.RezObject(m_host, item, pos, rot, vel, param); 3132 SceneObjectGroup new_group = World.RezObject(m_host, item, llpos, Rot2Quaternion(rot), llvel, param);
3084 3133
3085 // If either of these are null, then there was an unknown error. 3134 // If either of these are null, then there was an unknown error.
3086 if (new_group == null) 3135 if (new_group == null)
@@ -3107,11 +3156,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3107 3156
3108 PhysicsActor pa = new_group.RootPart.PhysActor; 3157 PhysicsActor pa = new_group.RootPart.PhysActor;
3109 3158
3110 if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero) 3159 if (pa != null && pa.IsPhysical && llvel != Vector3.Zero)
3111 { 3160 {
3112 float groupmass = new_group.GetMass(); 3161 float groupmass = new_group.GetMass();
3113 vel *= -groupmass; 3162 llvel *= -groupmass;
3114 llApplyImpulse(vel, 0); 3163 llApplyImpulse(new LSL_Vector(llvel.X, llvel.Y,llvel.Z), 0);
3115 } 3164 }
3116 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay) 3165 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
3117 return; 3166 return;
@@ -3162,7 +3211,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3162 return; 3211 return;
3163 } 3212 }
3164 3213
3165 m_host.StartLookAt((Quaternion)(r3 * r2 * r1), (float)strength, (float)damping); 3214 m_host.StartLookAt(Rot2Quaternion(r3 * r2 * r1), (float)strength, (float)damping);
3166 } 3215 }
3167 } 3216 }
3168 3217
@@ -3588,7 +3637,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3588 } 3637 }
3589 else 3638 else
3590 { 3639 {
3591 m_host.RotLookAt(target, (float)strength, (float)damping); 3640 m_host.RotLookAt(Rot2Quaternion(target), (float)strength, (float)damping);
3592 } 3641 }
3593 } 3642 }
3594 3643
@@ -3669,7 +3718,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3669 3718
3670 protected void TargetOmega(SceneObjectPart part, LSL_Vector axis, double spinrate, double gain) 3719 protected void TargetOmega(SceneObjectPart part, LSL_Vector axis, double spinrate, double gain)
3671 { 3720 {
3672 part.UpdateAngularVelocity(axis * spinrate); 3721 part.UpdateAngularVelocity(new Vector3((float)(axis.x * spinrate), (float)(axis.y * spinrate), (float)(axis.z * spinrate)));
3673 } 3722 }
3674 3723
3675 public LSL_Integer llGetStartParameter() 3724 public LSL_Integer llGetStartParameter()
@@ -3883,7 +3932,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3883 try 3932 try
3884 { 3933 {
3885 foreach (SceneObjectPart part in parts) 3934 foreach (SceneObjectPart part in parts)
3886 part.SetFaceColorAlpha(face, color, null); 3935 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face);
3887 } 3936 }
3888 finally 3937 finally
3889 { 3938 {
@@ -4109,16 +4158,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4109 } 4158 }
4110 4159
4111 /// <summary> 4160 /// <summary>
4112 /// Returns the name of the child prim or seated avatar matching the
4113 /// specified link number.
4114 /// </summary>
4115 /// <param name="linknum">
4116 /// The number of a link in the linkset or a link-related constant.
4117 /// </param>
4118 /// <returns>
4119 /// The name determined to match the specified link number.
4120 /// </returns>
4121 /// <remarks>
4122 /// The rules governing the returned name are not simple. The only 4161 /// The rules governing the returned name are not simple. The only
4123 /// time a blank name is returned is if the target prim has a blank 4162 /// time a blank name is returned is if the target prim has a blank
4124 /// name. If no prim with the given link number can be found then 4163 /// name. If no prim with the given link number can be found then
@@ -4146,14 +4185,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4146 /// Mentions NULL_KEY being returned 4185 /// Mentions NULL_KEY being returned
4147 /// http://wiki.secondlife.com/wiki/LlGetLinkName 4186 /// http://wiki.secondlife.com/wiki/LlGetLinkName
4148 /// Mentions using the LINK_* constants, some of which are negative 4187 /// Mentions using the LINK_* constants, some of which are negative
4149 /// </remarks> 4188 /// </summary>
4150 public LSL_String llGetLinkName(int linknum) 4189 public LSL_String llGetLinkName(int linknum)
4151 { 4190 {
4152 m_host.AddScriptLPS(1); 4191 m_host.AddScriptLPS(1);
4153 // simplest case, this prims link number
4154 if (linknum == m_host.LinkNum || linknum == ScriptBaseClass.LINK_THIS)
4155 return m_host.Name;
4156
4157 // parse for sitting avatare-names 4192 // parse for sitting avatare-names
4158 List<String> nametable = new List<String>(); 4193 List<String> nametable = new List<String>();
4159 World.ForEachRootScenePresence(delegate(ScenePresence presence) 4194 World.ForEachRootScenePresence(delegate(ScenePresence presence)
@@ -4177,6 +4212,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4177 return nametable[totalprims - linknum]; 4212 return nametable[totalprims - linknum];
4178 } 4213 }
4179 4214
4215 // simplest case, this prims link number
4216 if (m_host.LinkNum == linknum)
4217 return m_host.Name;
4218
4180 // Single prim 4219 // Single prim
4181 if (m_host.LinkNum == 0) 4220 if (m_host.LinkNum == 0)
4182 { 4221 {
@@ -4325,7 +4364,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4325 World.RegionInfo.RegionName+" "+ 4364 World.RegionInfo.RegionName+" "+
4326 m_host.AbsolutePosition.ToString(), 4365 m_host.AbsolutePosition.ToString(),
4327 agentItem.ID, true, m_host.AbsolutePosition, 4366 agentItem.ID, true, m_host.AbsolutePosition,
4328 bucket, true); 4367 bucket);
4329 4368
4330 ScenePresence sp; 4369 ScenePresence sp;
4331 4370
@@ -4363,7 +4402,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4363 public void llSetText(string text, LSL_Vector color, double alpha) 4402 public void llSetText(string text, LSL_Vector color, double alpha)
4364 { 4403 {
4365 m_host.AddScriptLPS(1); 4404 m_host.AddScriptLPS(1);
4366 Vector3 av3 = Util.Clip(color, 0.0f, 1.0f); 4405 Vector3 av3 = new Vector3(Util.Clip((float)color.x, 0.0f, 1.0f),
4406 Util.Clip((float)color.y, 0.0f, 1.0f),
4407 Util.Clip((float)color.z, 0.0f, 1.0f));
4367 if (text.Length > 254) 4408 if (text.Length > 254)
4368 text = text.Remove(254); 4409 text = text.Remove(254);
4369 4410
@@ -4590,11 +4631,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4590 ScriptSleep(5000); 4631 ScriptSleep(5000);
4591 } 4632 }
4592 4633
4593 public void llTeleportAgent(string agent, string destination, LSL_Vector targetPos, LSL_Vector targetLookAt) 4634 public void llTeleportAgent(string agent, string destination, LSL_Vector pos, LSL_Vector lookAt)
4594 { 4635 {
4595 m_host.AddScriptLPS(1); 4636 m_host.AddScriptLPS(1);
4596 UUID agentId = new UUID(); 4637 UUID agentId = new UUID();
4597 4638
4639 Vector3 targetPos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
4640 Vector3 targetLookAt = new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z);
4641
4598 if (UUID.TryParse(agent, out agentId)) 4642 if (UUID.TryParse(agent, out agentId))
4599 { 4643 {
4600 ScenePresence presence = World.GetScenePresence(agentId); 4644 ScenePresence presence = World.GetScenePresence(agentId);
@@ -4623,13 +4667,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4623 } 4667 }
4624 } 4668 }
4625 4669
4626 public void llTeleportAgentGlobalCoords(string agent, LSL_Vector global_coords, LSL_Vector targetPos, LSL_Vector targetLookAt) 4670 public void llTeleportAgentGlobalCoords(string agent, LSL_Vector global_coords, LSL_Vector pos, LSL_Vector lookAt)
4627 { 4671 {
4628 m_host.AddScriptLPS(1); 4672 m_host.AddScriptLPS(1);
4629 UUID agentId = new UUID(); 4673 UUID agentId = new UUID();
4630 4674
4631 ulong regionHandle = Utils.UIntsToLong((uint)global_coords.x, (uint)global_coords.y); 4675 ulong regionHandle = Utils.UIntsToLong((uint)global_coords.x, (uint)global_coords.y);
4632 4676
4677 Vector3 targetPos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z);
4678 Vector3 targetLookAt = new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z);
4633 if (UUID.TryParse(agent, out agentId)) 4679 if (UUID.TryParse(agent, out agentId))
4634 { 4680 {
4635 ScenePresence presence = World.GetScenePresence(agentId); 4681 ScenePresence presence = World.GetScenePresence(agentId);
@@ -4731,7 +4777,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4731 return; 4777 return;
4732 } 4778 }
4733 // TODO: Parameter check logic required. 4779 // TODO: Parameter check logic required.
4734 m_host.CollisionSound = KeyOrName(impact_sound, AssetType.Sound); 4780 UUID soundId = UUID.Zero;
4781 if (!UUID.TryParse(impact_sound, out soundId))
4782 {
4783 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(impact_sound);
4784
4785 if (item != null && item.Type == (int)AssetType.Sound)
4786 soundId = item.AssetID;
4787 }
4788
4789 m_host.CollisionSound = soundId;
4735 m_host.CollisionSoundVolume = (float)impact_volume; 4790 m_host.CollisionSoundVolume = (float)impact_volume;
4736 m_host.CollisionSoundType = 1; 4791 m_host.CollisionSoundType = 1;
4737 } 4792 }
@@ -4917,7 +4972,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4917 distance_attenuation = 1f / normalized_units; 4972 distance_attenuation = 1f / normalized_units;
4918 } 4973 }
4919 4974
4920 Vector3 applied_linear_impulse = impulse; 4975 Vector3 applied_linear_impulse = new Vector3((float)impulse.x, (float)impulse.y, (float)impulse.z);
4921 { 4976 {
4922 float impulse_length = applied_linear_impulse.Length(); 4977 float impulse_length = applied_linear_impulse.Length();
4923 4978
@@ -5565,15 +5620,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5565 /// separated list. There is a space after 5620 /// separated list. There is a space after
5566 /// each comma. 5621 /// each comma.
5567 /// </summary> 5622 /// </summary>
5623
5568 public LSL_String llList2CSV(LSL_List src) 5624 public LSL_String llList2CSV(LSL_List src)
5569 { 5625 {
5626
5627 string ret = String.Empty;
5628 int x = 0;
5629
5570 m_host.AddScriptLPS(1); 5630 m_host.AddScriptLPS(1);
5571 5631
5572 return string.Join(", ", 5632 if (src.Data.Length > 0)
5573 (new List<object>(src.Data)).ConvertAll<string>(o => 5633 {
5574 { 5634 ret = src.Data[x++].ToString();
5575 return o.ToString(); 5635 for (; x < src.Data.Length; x++)
5576 }).ToArray()); 5636 {
5637 ret += ", "+src.Data[x].ToString();
5638 }
5639 }
5640
5641 return ret;
5577 } 5642 }
5578 5643
5579 /// <summary> 5644 /// <summary>
@@ -5872,36 +5937,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5872 /// Returns the index of the first occurrence of test 5937 /// Returns the index of the first occurrence of test
5873 /// in src. 5938 /// in src.
5874 /// </summary> 5939 /// </summary>
5875 /// <param name="src">Source list</param> 5940
5876 /// <param name="test">List to search for</param>
5877 /// <returns>
5878 /// The index number of the point in src where test was found if it was found.
5879 /// Otherwise returns -1
5880 /// </returns>
5881 public LSL_Integer llListFindList(LSL_List src, LSL_List test) 5941 public LSL_Integer llListFindList(LSL_List src, LSL_List test)
5882 { 5942 {
5943
5883 int index = -1; 5944 int index = -1;
5884 int length = src.Length - test.Length + 1; 5945 int length = src.Length - test.Length + 1;
5885 5946
5886 m_host.AddScriptLPS(1); 5947 m_host.AddScriptLPS(1);
5887 5948
5888 // If either list is empty, do not match 5949 // If either list is empty, do not match
5950
5889 if (src.Length != 0 && test.Length != 0) 5951 if (src.Length != 0 && test.Length != 0)
5890 { 5952 {
5891 for (int i = 0; i < length; i++) 5953 for (int i = 0; i < length; i++)
5892 { 5954 {
5893 // Why this piece of insanity? This is because most script constants are C# value types (e.g. int) 5955 if (src.Data[i].Equals(test.Data[0]))
5894 // rather than wrapped LSL types. Such a script constant does not have int.Equal(LSL_Integer) code
5895 // and so the comparison fails even if the LSL_Integer conceptually has the same value.
5896 // Therefore, here we test Equals on both the source and destination objects.
5897 // However, a future better approach may be use LSL struct script constants (e.g. LSL_Integer(1)).
5898 if (src.Data[i].Equals(test.Data[0]) || test.Data[0].Equals(src.Data[i]))
5899 { 5956 {
5900 int j; 5957 int j;
5901 for (j = 1; j < test.Length; j++) 5958 for (j = 1; j < test.Length; j++)
5902 if (!(src.Data[i+j].Equals(test.Data[j]) || test.Data[j].Equals(src.Data[i+j]))) 5959 if (!src.Data[i+j].Equals(test.Data[j]))
5903 break; 5960 break;
5904
5905 if (j == test.Length) 5961 if (j == test.Length)
5906 { 5962 {
5907 index = i; 5963 index = i;
@@ -5912,18 +5968,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5912 } 5968 }
5913 5969
5914 return index; 5970 return index;
5971
5915 } 5972 }
5916 5973
5917 public LSL_String llGetObjectName() 5974 public LSL_String llGetObjectName()
5918 { 5975 {
5919 m_host.AddScriptLPS(1); 5976 m_host.AddScriptLPS(1);
5920 return m_host.Name !=null ? m_host.Name : String.Empty; 5977 return m_host.Name!=null?m_host.Name:String.Empty;
5921 } 5978 }
5922 5979
5923 public void llSetObjectName(string name) 5980 public void llSetObjectName(string name)
5924 { 5981 {
5925 m_host.AddScriptLPS(1); 5982 m_host.AddScriptLPS(1);
5926 m_host.Name = name != null ? name : String.Empty; 5983 m_host.Name = name!=null?name:String.Empty;
5927 } 5984 }
5928 5985
5929 public LSL_String llGetDate() 5986 public LSL_String llGetDate()
@@ -6097,7 +6154,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6097 flags |= ScriptBaseClass.AGENT_SITTING; 6154 flags |= ScriptBaseClass.AGENT_SITTING;
6098 } 6155 }
6099 6156
6100 if (agent.Animator.Animations.ImplicitDefaultAnimation.AnimID 6157 if (agent.Animator.Animations.DefaultAnimation.AnimID
6101 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) 6158 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
6102 { 6159 {
6103 flags |= ScriptBaseClass.AGENT_SITTING; 6160 flags |= ScriptBaseClass.AGENT_SITTING;
@@ -6254,17 +6311,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6254 m_host.AddScriptLPS(1); 6311 m_host.AddScriptLPS(1);
6255 6312
6256 List<SceneObjectPart> parts = GetLinkParts(linknumber); 6313 List<SceneObjectPart> parts = GetLinkParts(linknumber);
6257 6314 if (parts.Count > 0)
6258 try
6259 { 6315 {
6260 foreach (SceneObjectPart part in parts) 6316 try
6317 {
6318 foreach (var part in parts)
6319 {
6320 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
6321 }
6322 }
6323 finally
6261 { 6324 {
6262 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
6263 } 6325 }
6264 } 6326 }
6265 finally
6266 {
6267 }
6268 } 6327 }
6269 6328
6270 private void SetTextureAnim(SceneObjectPart part, int mode, int face, int sizex, int sizey, double start, double length, double rate) 6329 private void SetTextureAnim(SceneObjectPart part, int mode, int face, int sizex, int sizey, double start, double length, double rate)
@@ -6293,12 +6352,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6293 LSL_Vector bottom_south_west) 6352 LSL_Vector bottom_south_west)
6294 { 6353 {
6295 m_host.AddScriptLPS(1); 6354 m_host.AddScriptLPS(1);
6296 if (m_SoundModule != null) 6355 float radius1 = (float)llVecDist(llGetPos(), top_north_east);
6297 { 6356 float radius2 = (float)llVecDist(llGetPos(), bottom_south_west);
6298 m_SoundModule.TriggerSoundLimited(m_host.UUID, 6357 float radius = Math.Abs(radius1 - radius2);
6299 KeyOrName(sound, AssetType.Sound), volume, 6358 m_host.SendSound(KeyOrName(sound).ToString(), volume, true, 0, radius, false, false);
6300 bottom_south_west, top_north_east);
6301 }
6302 } 6359 }
6303 6360
6304 public void llEjectFromLand(string pest) 6361 public void llEjectFromLand(string pest)
@@ -6484,7 +6541,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6484 6541
6485 //Plug the x,y coordinates of the slope normal into the equation of the plane to get 6542 //Plug the x,y coordinates of the slope normal into the equation of the plane to get
6486 //the height of that point on the plane. The resulting vector gives the slope. 6543 //the height of that point on the plane. The resulting vector gives the slope.
6487 Vector3 vsl = vsn; 6544 Vector3 vsl = new Vector3();
6545 vsl.X = (float)vsn.x;
6546 vsl.Y = (float)vsn.y;
6488 vsl.Z = (float)(((vsn.x * vsn.x) + (vsn.y * vsn.y)) / (-1 * vsn.z)); 6547 vsl.Z = (float)(((vsn.x * vsn.x) + (vsn.y * vsn.y)) / (-1 * vsn.z));
6489 vsl.Normalize(); 6548 vsl.Normalize();
6490 //Normalization might be overkill here 6549 //Normalization might be overkill here
@@ -6495,7 +6554,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6495 public LSL_Vector llGroundNormal(LSL_Vector offset) 6554 public LSL_Vector llGroundNormal(LSL_Vector offset)
6496 { 6555 {
6497 m_host.AddScriptLPS(1); 6556 m_host.AddScriptLPS(1);
6498 Vector3 pos = m_host.GetWorldPosition() + (Vector3)offset; 6557 Vector3 pos = m_host.GetWorldPosition() + new Vector3((float)offset.x,
6558 (float)offset.y,
6559 (float)offset.z);
6499 // Clamp to valid position 6560 // Clamp to valid position
6500 if (pos.X < 0) 6561 if (pos.X < 0)
6501 pos.X = 0; 6562 pos.X = 0;
@@ -6660,7 +6721,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6660 6721
6661 List<SceneObjectPart> parts = GetLinkParts(linknumber); 6722 List<SceneObjectPart> parts = GetLinkParts(linknumber);
6662 6723
6663 foreach (SceneObjectPart part in parts) 6724 foreach (var part in parts)
6664 { 6725 {
6665 SetParticleSystem(part, rules); 6726 SetParticleSystem(part, rules);
6666 } 6727 }
@@ -6904,17 +6965,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6904 if (m_TransferModule != null) 6965 if (m_TransferModule != null)
6905 { 6966 {
6906 byte[] bucket = new byte[] { (byte)AssetType.Folder }; 6967 byte[] bucket = new byte[] { (byte)AssetType.Folder };
6907 6968
6908 Vector3 pos = m_host.AbsolutePosition;
6909
6910 GridInstantMessage msg = new GridInstantMessage(World, 6969 GridInstantMessage msg = new GridInstantMessage(World,
6911 m_host.OwnerID, m_host.Name, destID, 6970 m_host.UUID, m_host.Name + ", an object owned by " +
6971 resolveName(m_host.OwnerID) + ",", destID,
6912 (byte)InstantMessageDialog.TaskInventoryOffered, 6972 (byte)InstantMessageDialog.TaskInventoryOffered,
6913 false, string.Format("'{0}'", category), 6973 false, category + "\n" + m_host.Name + " is located at " +
6914// We won't go so far as to add a SLURL, but this is the format used by LL as of 2012-10-06 6974 World.RegionInfo.RegionName + " " +
6915// false, string.Format("'{0}' ( http://slurl.com/secondlife/{1}/{2}/{3}/{4} )", category, World.Name, (int)pos.X, (int)pos.Y, (int)pos.Z), 6975 m_host.AbsolutePosition.ToString(),
6916 folderID, false, pos, 6976 folderID, true, m_host.AbsolutePosition,
6917 bucket, false); 6977 bucket);
6918 6978
6919 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); 6979 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
6920 } 6980 }
@@ -6950,7 +7010,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6950 7010
6951 if (!m_host.ParentGroup.IsDeleted) 7011 if (!m_host.ParentGroup.IsDeleted)
6952 { 7012 {
6953 m_host.ParentGroup.RootPart.SetVehicleVectorParam(param, vec); 7013 m_host.ParentGroup.RootPart.SetVehicleVectorParam(param,
7014 new Vector3((float)vec.x, (float)vec.y, (float)vec.z));
6954 } 7015 }
6955 } 7016 }
6956 7017
@@ -6962,7 +7023,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6962 7023
6963 if (!m_host.ParentGroup.IsDeleted) 7024 if (!m_host.ParentGroup.IsDeleted)
6964 { 7025 {
6965 m_host.ParentGroup.RootPart.SetVehicleRotationParam(param, rot); 7026 m_host.ParentGroup.RootPart.SetVehicleRotationParam(param, Rot2Quaternion(rot));
6966 } 7027 }
6967 } 7028 }
6968 7029
@@ -6992,8 +7053,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6992 if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0) 7053 if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0)
6993 rot.s = 1; // ZERO_ROTATION = 0,0,0,1 7054 rot.s = 1; // ZERO_ROTATION = 0,0,0,1
6994 7055
6995 part.SitTargetPosition = offset; 7056 part.SitTargetPosition = new Vector3((float)offset.x, (float)offset.y, (float)offset.z);
6996 part.SitTargetOrientation = rot; 7057 part.SitTargetOrientation = Rot2Quaternion(rot);
6997 part.ParentGroup.HasGroupChanged = true; 7058 part.ParentGroup.HasGroupChanged = true;
6998 } 7059 }
6999 7060
@@ -7096,13 +7157,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7096 public void llSetCameraEyeOffset(LSL_Vector offset) 7157 public void llSetCameraEyeOffset(LSL_Vector offset)
7097 { 7158 {
7098 m_host.AddScriptLPS(1); 7159 m_host.AddScriptLPS(1);
7099 m_host.SetCameraEyeOffset(offset); 7160 m_host.SetCameraEyeOffset(new Vector3((float)offset.x, (float)offset.y, (float)offset.z));
7100 } 7161 }
7101 7162
7102 public void llSetCameraAtOffset(LSL_Vector offset) 7163 public void llSetCameraAtOffset(LSL_Vector offset)
7103 { 7164 {
7104 m_host.AddScriptLPS(1); 7165 m_host.AddScriptLPS(1);
7105 m_host.SetCameraAtOffset(offset); 7166 m_host.SetCameraAtOffset(new Vector3((float)offset.x, (float)offset.y, (float)offset.z));
7106 } 7167 }
7107 7168
7108 public LSL_String llDumpList2String(LSL_List src, string seperator) 7169 public LSL_String llDumpList2String(LSL_List src, string seperator)
@@ -7124,7 +7185,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7124 public LSL_Integer llScriptDanger(LSL_Vector pos) 7185 public LSL_Integer llScriptDanger(LSL_Vector pos)
7125 { 7186 {
7126 m_host.AddScriptLPS(1); 7187 m_host.AddScriptLPS(1);
7127 bool result = World.ScriptDanger(m_host.LocalId, pos); 7188 bool result = World.ScriptDanger(m_host.LocalId, new Vector3((float)pos.x, (float)pos.y, (float)pos.z));
7128 if (result) 7189 if (result)
7129 { 7190 {
7130 return 1; 7191 return 1;
@@ -7706,7 +7767,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7706 { 7767 {
7707 m_host.AddScriptLPS(1); 7768 m_host.AddScriptLPS(1);
7708 7769
7709 setLinkPrimParams(ScriptBaseClass.LINK_THIS, rules, "llSetPrimitiveParams"); 7770 setLinkPrimParams(ScriptBaseClass.LINK_THIS, rules);
7710 7771
7711 ScriptSleep(200); 7772 ScriptSleep(200);
7712 } 7773 }
@@ -7715,12 +7776,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7715 { 7776 {
7716 m_host.AddScriptLPS(1); 7777 m_host.AddScriptLPS(1);
7717 7778
7718 setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParamsFast"); 7779 setLinkPrimParams(linknumber, rules);
7719
7720 ScriptSleep(200);
7721 } 7780 }
7722 7781
7723 private void setLinkPrimParams(int linknumber, LSL_List rules, string originFunc) 7782 private void setLinkPrimParams(int linknumber, LSL_List rules)
7724 { 7783 {
7725 List<object> parts = new List<object>(); 7784 List<object> parts = new List<object>();
7726 List<SceneObjectPart> prims = GetLinkParts(linknumber); 7785 List<SceneObjectPart> prims = GetLinkParts(linknumber);
@@ -7731,16 +7790,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7731 parts.Add(p); 7790 parts.Add(p);
7732 7791
7733 LSL_List remaining = null; 7792 LSL_List remaining = null;
7734 uint rulesParsed = 0;
7735 7793
7736 if (parts.Count > 0) 7794 if (parts.Count > 0)
7737 { 7795 {
7738 foreach (object part in parts) 7796 foreach (object part in parts)
7739 { 7797 {
7740 if (part is SceneObjectPart) 7798 if (part is SceneObjectPart)
7741 remaining = SetPrimParams((SceneObjectPart)part, rules, originFunc, ref rulesParsed); 7799 remaining = SetPrimParams((SceneObjectPart)part, rules);
7742 else 7800 else
7743 remaining = SetPrimParams((ScenePresence)part, rules, originFunc, ref rulesParsed); 7801 remaining = SetPrimParams((ScenePresence)part, rules);
7744 } 7802 }
7745 7803
7746 while ((object)remaining != null && remaining.Length > 2) 7804 while ((object)remaining != null && remaining.Length > 2)
@@ -7759,9 +7817,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7759 foreach (object part in parts) 7817 foreach (object part in parts)
7760 { 7818 {
7761 if (part is SceneObjectPart) 7819 if (part is SceneObjectPart)
7762 remaining = SetPrimParams((SceneObjectPart)part, rules, originFunc, ref rulesParsed); 7820 remaining = SetPrimParams((SceneObjectPart)part, rules);
7763 else 7821 else
7764 remaining = SetPrimParams((ScenePresence)part, rules, originFunc, ref rulesParsed); 7822 remaining = SetPrimParams((ScenePresence)part, rules);
7765 } 7823 }
7766 } 7824 }
7767 } 7825 }
@@ -7799,7 +7857,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7799 7857
7800 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) 7858 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
7801 { 7859 {
7802 setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParams");
7803 llSetLinkPrimitiveParamsFast(linknumber, rules); 7860 llSetLinkPrimitiveParamsFast(linknumber, rules);
7804 ScriptSleep(200); 7861 ScriptSleep(200);
7805 } 7862 }
@@ -7827,13 +7884,195 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7827 return new Vector3((float)x, (float)y, (float)z); 7884 return new Vector3((float)x, (float)y, (float)z);
7828 } 7885 }
7829 7886
7830 protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules, string originFunc, ref uint rulesParsed) 7887 protected LSL_List SetPrimParams(ScenePresence av, LSL_List rules)
7888 {
7889 //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset.
7890
7891 int idx = 0;
7892
7893 bool positionChanged = false;
7894 Vector3 finalPos = Vector3.Zero;
7895
7896 try
7897 {
7898 while (idx < rules.Length)
7899 {
7900 int code = rules.GetLSLIntegerItem(idx++);
7901
7902 int remain = rules.Length - idx;
7903
7904 switch (code)
7905 {
7906 case (int)ScriptBaseClass.PRIM_POSITION:
7907 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
7908 {
7909 if (remain < 1)
7910 return null;
7911
7912 LSL_Vector v;
7913 v = rules.GetVector3Item(idx++);
7914
7915 SceneObjectPart part = World.GetSceneObjectPart(av.ParentID);
7916 if (part == null)
7917 break;
7918
7919 LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION;
7920 LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR;
7921 if (part.LinkNum > 1)
7922 {
7923 localRot = GetPartLocalRot(part);
7924 localPos = GetPartLocalPos(part);
7925 }
7926
7927 v -= localPos;
7928 v /= localRot;
7929
7930 LSL_Vector sitOffset = (llRot2Up(new LSL_Rotation(av.Rotation.X, av.Rotation.Y, av.Rotation.Z, av.Rotation.W)) * av.Appearance.AvatarHeight * 0.02638f);
7931
7932 v = v + 2 * sitOffset;
7933
7934 av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z);
7935 av.SendAvatarDataToAllAgents();
7936
7937 }
7938 break;
7939
7940 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
7941 case (int)ScriptBaseClass.PRIM_ROTATION:
7942 {
7943 if (remain < 1)
7944 return null;
7945
7946 LSL_Rotation r;
7947 r = rules.GetQuaternionItem(idx++);
7948
7949 SceneObjectPart part = World.GetSceneObjectPart(av.ParentID);
7950 if (part == null)
7951 break;
7952
7953 LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION;
7954 LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR;
7955
7956 if (part.LinkNum > 1)
7957 localRot = GetPartLocalRot(part);
7958
7959 r = r * llGetRootRotation() / localRot;
7960 av.Rotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s);
7961 av.SendAvatarDataToAllAgents();
7962 }
7963 break;
7964
7965 // parse rest doing nothing but number of parameters error check
7966 case (int)ScriptBaseClass.PRIM_SIZE:
7967 case (int)ScriptBaseClass.PRIM_MATERIAL:
7968 case (int)ScriptBaseClass.PRIM_PHANTOM:
7969 case (int)ScriptBaseClass.PRIM_PHYSICS:
7970 case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE:
7971 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
7972 case (int)ScriptBaseClass.PRIM_NAME:
7973 case (int)ScriptBaseClass.PRIM_DESC:
7974 if (remain < 1)
7975 return null;
7976 idx++;
7977 break;
7978
7979 case (int)ScriptBaseClass.PRIM_GLOW:
7980 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
7981 case (int)ScriptBaseClass.PRIM_TEXGEN:
7982 if (remain < 2)
7983 return null;
7984 idx += 2;
7985 break;
7986
7987 case (int)ScriptBaseClass.PRIM_TYPE:
7988 if (remain < 3)
7989 return null;
7990 code = (int)rules.GetLSLIntegerItem(idx++);
7991 remain = rules.Length - idx;
7992 switch (code)
7993 {
7994 case (int)ScriptBaseClass.PRIM_TYPE_BOX:
7995 case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER:
7996 case (int)ScriptBaseClass.PRIM_TYPE_PRISM:
7997 if (remain < 6)
7998 return null;
7999 idx += 6;
8000 break;
8001
8002 case (int)ScriptBaseClass.PRIM_TYPE_SPHERE:
8003 if (remain < 5)
8004 return null;
8005 idx += 5;
8006 break;
8007
8008 case (int)ScriptBaseClass.PRIM_TYPE_TORUS:
8009 case (int)ScriptBaseClass.PRIM_TYPE_TUBE:
8010 case (int)ScriptBaseClass.PRIM_TYPE_RING:
8011 if (remain < 11)
8012 return null;
8013 idx += 11;
8014 break;
8015
8016 case (int)ScriptBaseClass.PRIM_TYPE_SCULPT:
8017 if (remain < 2)
8018 return null;
8019 idx += 2;
8020 break;
8021 }
8022 break;
8023
8024 case (int)ScriptBaseClass.PRIM_COLOR:
8025 case (int)ScriptBaseClass.PRIM_TEXT:
8026 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
8027 case (int)ScriptBaseClass.PRIM_OMEGA:
8028 if (remain < 3)
8029 return null;
8030 idx += 3;
8031 break;
8032
8033 case (int)ScriptBaseClass.PRIM_TEXTURE:
8034 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
8035 case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL:
8036 if (remain < 5)
8037 return null;
8038 idx += 5;
8039 break;
8040
8041 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
8042 if (remain < 7)
8043 return null;
8044
8045 idx += 7;
8046 break;
8047
8048 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
8049 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
8050 return null;
8051
8052 return rules.GetSublist(idx, -1);
8053 }
8054 }
8055 }
8056
8057 finally
8058 {
8059 if (positionChanged)
8060 {
8061 av.OffsetPosition = finalPos;
8062// av.SendAvatarDataToAllAgents();
8063 av.SendTerseUpdateToAllClients();
8064 positionChanged = false;
8065 }
8066 }
8067 return null;
8068 }
8069
8070 protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules)
7831 { 8071 {
7832 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) 8072 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7833 return null; 8073 return null;
7834 8074
7835 int idx = 0; 8075 int idx = 0;
7836 int idxStart = 0;
7837 8076
7838 SceneObjectGroup parentgrp = part.ParentGroup; 8077 SceneObjectGroup parentgrp = part.ParentGroup;
7839 8078
@@ -7844,11 +8083,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7844 { 8083 {
7845 while (idx < rules.Length) 8084 while (idx < rules.Length)
7846 { 8085 {
7847 ++rulesParsed;
7848 int code = rules.GetLSLIntegerItem(idx++); 8086 int code = rules.GetLSLIntegerItem(idx++);
7849 8087
7850 int remain = rules.Length - idx; 8088 int remain = rules.Length - idx;
7851 idxStart = idx;
7852 8089
7853 int face; 8090 int face;
7854 LSL_Vector v; 8091 LSL_Vector v;
@@ -7878,17 +8115,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7878 return null; 8115 return null;
7879 8116
7880 LSL_Rotation q = rules.GetQuaternionItem(idx++); 8117 LSL_Rotation q = rules.GetQuaternionItem(idx++);
8118 SceneObjectPart rootPart = parentgrp.RootPart;
7881 // try to let this work as in SL... 8119 // try to let this work as in SL...
7882 if (part.ParentID == 0) 8120 if (rootPart == part)
7883 { 8121 {
7884 // special case: If we are root, rotate complete SOG to new rotation 8122 // special case: If we are root, rotate complete SOG to new rotation
7885 SetRot(part, q); 8123 SetRot(part, Rot2Quaternion(q));
7886 } 8124 }
7887 else 8125 else
7888 { 8126 {
7889 // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask. 8127 // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask.
7890 SceneObjectPart rootPart = part.ParentGroup.RootPart; 8128 // sounds like sl bug that we need to replicate
7891 SetRot(part, rootPart.RotationOffset * (Quaternion)q); 8129 SetRot(part, rootPart.RotationOffset * Rot2Quaternion(q));
7892 } 8130 }
7893 8131
7894 break; 8132 break;
@@ -8062,7 +8300,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8062 LSL_Vector color=rules.GetVector3Item(idx++); 8300 LSL_Vector color=rules.GetVector3Item(idx++);
8063 double alpha=(double)rules.GetLSLFloatItem(idx++); 8301 double alpha=(double)rules.GetLSLFloatItem(idx++);
8064 8302
8065 part.SetFaceColorAlpha(face, color, alpha); 8303 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face);
8304 SetAlpha(part, alpha, face);
8066 8305
8067 break; 8306 break;
8068 8307
@@ -8210,7 +8449,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8210 string primText = rules.GetLSLStringItem(idx++); 8449 string primText = rules.GetLSLStringItem(idx++);
8211 LSL_Vector primTextColor = rules.GetVector3Item(idx++); 8450 LSL_Vector primTextColor = rules.GetVector3Item(idx++);
8212 LSL_Float primTextAlpha = rules.GetLSLFloatItem(idx++); 8451 LSL_Float primTextAlpha = rules.GetLSLFloatItem(idx++);
8213 Vector3 av3 = Util.Clip(primTextColor, 0.0f, 1.0f); 8452 Vector3 av3 = new Vector3(Util.Clip((float)primTextColor.x, 0.0f, 1.0f),
8453 Util.Clip((float)primTextColor.y, 0.0f, 1.0f),
8454 Util.Clip((float)primTextColor.z, 0.0f, 1.0f));
8214 part.SetText(primText, av3, Util.Clip((float)primTextAlpha, 0.0f, 1.0f)); 8455 part.SetText(primText, av3, Util.Clip((float)primTextAlpha, 0.0f, 1.0f));
8215 8456
8216 break; 8457 break;
@@ -8229,7 +8470,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8229 case (int)ScriptBaseClass.PRIM_ROT_LOCAL: 8470 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
8230 if (remain < 1) 8471 if (remain < 1)
8231 return null; 8472 return null;
8232 SetRot(part, rules.GetQuaternionItem(idx++)); 8473 LSL_Rotation lr = rules.GetQuaternionItem(idx++);
8474 SetRot(part, Rot2Quaternion(lr));
8233 break; 8475 break;
8234 case (int)ScriptBaseClass.PRIM_OMEGA: 8476 case (int)ScriptBaseClass.PRIM_OMEGA:
8235 if (remain < 3) 8477 if (remain < 3)
@@ -8239,12 +8481,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8239 LSL_Float gain = rules.GetLSLFloatItem(idx++); 8481 LSL_Float gain = rules.GetLSLFloatItem(idx++);
8240 TargetOmega(part, axis, (double)spinrate, (double)gain); 8482 TargetOmega(part, axis, (double)spinrate, (double)gain);
8241 break; 8483 break;
8242 case (int)ScriptBaseClass.PRIM_SLICE: 8484
8243 if (remain < 1)
8244 return null;
8245 LSL_Vector slice = rules.GetVector3Item(idx++);
8246 part.UpdateSlice((float)slice.x, (float)slice.y);
8247 break;
8248 case (int)ScriptBaseClass.PRIM_LINK_TARGET: 8485 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
8249 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. 8486 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
8250 return null; 8487 return null;
@@ -8253,12 +8490,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8253 } 8490 }
8254 } 8491 }
8255 } 8492 }
8256 catch (InvalidCastException e)
8257 {
8258 ShoutError(string.Format(
8259 "{0} error running rule #{1}: arg #{2} ",
8260 originFunc, rulesParsed, idx - idxStart) + e.Message);
8261 }
8262 finally 8493 finally
8263 { 8494 {
8264 if (positionChanged) 8495 if (positionChanged)
@@ -8267,12 +8498,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8267 { 8498 {
8268 SceneObjectGroup parent = part.ParentGroup; 8499 SceneObjectGroup parent = part.ParentGroup;
8269 Util.FireAndForget(delegate(object x) { 8500 Util.FireAndForget(delegate(object x) {
8270 parent.UpdateGroupPosition(currentPosition); 8501 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z));
8271 }); 8502 });
8272 } 8503 }
8273 else 8504 else
8274 { 8505 {
8275 part.OffsetPosition = currentPosition; 8506 part.OffsetPosition = new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z);
8276 SceneObjectGroup parent = part.ParentGroup; 8507 SceneObjectGroup parent = part.ParentGroup;
8277 parent.HasGroupChanged = true; 8508 parent.HasGroupChanged = true;
8278 parent.ScheduleGroupForTerseUpdate(); 8509 parent.ScheduleGroupForTerseUpdate();
@@ -8561,7 +8792,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8561 // and standing avatar since server 1.36 8792 // and standing avatar since server 1.36
8562 LSL_Vector lower; 8793 LSL_Vector lower;
8563 LSL_Vector upper; 8794 LSL_Vector upper;
8564 if (presence.Animator.Animations.ImplicitDefaultAnimation.AnimID 8795 if (presence.Animator.Animations.DefaultAnimation.AnimID
8565 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) 8796 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
8566 { 8797 {
8567 // This is for ground sitting avatars 8798 // This is for ground sitting avatars
@@ -8650,22 +8881,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8650 public LSL_List llGetPrimitiveParams(LSL_List rules) 8881 public LSL_List llGetPrimitiveParams(LSL_List rules)
8651 { 8882 {
8652 m_host.AddScriptLPS(1); 8883 m_host.AddScriptLPS(1);
8653 8884 return GetLinkPrimitiveParams(m_host, rules);
8654 LSL_List result = new LSL_List();
8655
8656 LSL_List remaining = GetPrimParams(m_host, rules, ref result);
8657
8658 while (remaining != null && remaining.Length > 2)
8659 {
8660 int linknumber = remaining.GetLSLIntegerItem(0);
8661 rules = remaining.GetSublist(1, -1);
8662 List<SceneObjectPart> parts = GetLinkParts(linknumber);
8663
8664 foreach (SceneObjectPart part in parts)
8665 remaining = GetPrimParams(part, rules, ref result);
8666 }
8667
8668 return result;
8669 } 8885 }
8670 8886
8671 public LSL_List llGetLinkPrimitiveParams(int linknumber, LSL_List rules) 8887 public LSL_List llGetLinkPrimitiveParams(int linknumber, LSL_List rules)
@@ -8675,39 +8891,294 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8675 // acording to SL wiki this must indicate a single link number or link_root or link_this. 8891 // acording to SL wiki this must indicate a single link number or link_root or link_this.
8676 // keep other options as before 8892 // keep other options as before
8677 8893
8678 List<SceneObjectPart> parts; 8894 List<SceneObjectPart> parts = GetLinkParts(linknumber);
8679 List<ScenePresence> avatars; 8895 List<ScenePresence> avatars = GetLinkAvatars(linknumber);
8680 8896
8681 LSL_List res = new LSL_List(); 8897 LSL_List res = new LSL_List();
8682 LSL_List remaining = null;
8683 8898
8684 while (rules.Length > 0) 8899 if (parts.Count > 0)
8685 { 8900 {
8686 parts = GetLinkParts(linknumber); 8901 foreach (var part in parts)
8687 avatars = GetLinkAvatars(linknumber);
8688
8689 remaining = null;
8690 foreach (SceneObjectPart part in parts)
8691 { 8902 {
8692 remaining = GetPrimParams(part, rules, ref res); 8903 LSL_List partRes = GetLinkPrimitiveParams(part, rules);
8904 res += partRes;
8693 } 8905 }
8906 }
8907 if (avatars.Count > 0)
8908 {
8694 foreach (ScenePresence avatar in avatars) 8909 foreach (ScenePresence avatar in avatars)
8695 { 8910 {
8696 remaining = GetPrimParams(avatar, rules, ref res); 8911 LSL_List avaRes = GetLinkPrimitiveParams(avatar, rules);
8912 res += avaRes;
8697 } 8913 }
8914 }
8915 return res;
8916 }
8917
8918 public LSL_List GetLinkPrimitiveParams(ScenePresence avatar, LSL_List rules)
8919 {
8920 // avatars case
8921 // replies as SL wiki
8698 8922
8699 if (remaining != null && remaining.Length > 0) 8923 LSL_List res = new LSL_List();
8924// SceneObjectPart sitPart = avatar.ParentPart; // most likelly it will be needed
8925 SceneObjectPart sitPart = World.GetSceneObjectPart(avatar.ParentID); // maybe better do this expensive search for it in case it's gone??
8926
8927 int idx = 0;
8928 while (idx < rules.Length)
8929 {
8930 int code = (int)rules.GetLSLIntegerItem(idx++);
8931 int remain = rules.Length - idx;
8932
8933 switch (code)
8700 { 8934 {
8701 linknumber = remaining.GetLSLIntegerItem(0); 8935 case (int)ScriptBaseClass.PRIM_MATERIAL:
8702 rules = remaining.GetSublist(1, -1); 8936 res.Add(new LSL_Integer((int)SOPMaterialData.SopMaterial.Flesh));
8937 break;
8938
8939 case (int)ScriptBaseClass.PRIM_PHYSICS:
8940 res.Add(new LSL_Integer(0));
8941 break;
8942
8943 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
8944 res.Add(new LSL_Integer(0));
8945 break;
8946
8947 case (int)ScriptBaseClass.PRIM_PHANTOM:
8948 res.Add(new LSL_Integer(0));
8949 break;
8950
8951 case (int)ScriptBaseClass.PRIM_POSITION:
8952
8953 Vector3 pos = avatar.OffsetPosition;
8954
8955 Vector3 sitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f *2.0f);
8956 pos -= sitOffset;
8957
8958 if( sitPart != null)
8959 pos = sitPart.GetWorldPosition() + pos * sitPart.GetWorldRotation();
8960
8961 res.Add(new LSL_Vector(pos.X,pos.Y,pos.Z));
8962 break;
8963
8964 case (int)ScriptBaseClass.PRIM_SIZE:
8965 // as in llGetAgentSize above
8966 res.Add(new LSL_Vector(0.45f, 0.6f, avatar.Appearance.AvatarHeight));
8967 break;
8968
8969 case (int)ScriptBaseClass.PRIM_ROTATION:
8970 Quaternion rot = avatar.Rotation;
8971 if (sitPart != null)
8972 {
8973 rot = sitPart.GetWorldRotation() * rot; // apply sit part world rotation
8974 }
8975
8976 res.Add(new LSL_Rotation (rot.X, rot.Y, rot.Z, rot.W));
8977 break;
8978
8979 case (int)ScriptBaseClass.PRIM_TYPE:
8980 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TYPE_BOX));
8981 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_HOLE_DEFAULT));
8982 res.Add(new LSL_Vector(0f,1.0f,0f));
8983 res.Add(new LSL_Float(0.0f));
8984 res.Add(new LSL_Vector(0, 0, 0));
8985 res.Add(new LSL_Vector(1.0f,1.0f,0f));
8986 res.Add(new LSL_Vector(0, 0, 0));
8987 break;
8988
8989 case (int)ScriptBaseClass.PRIM_TEXTURE:
8990 if (remain < 1)
8991 return res;
8992
8993 int face = (int)rules.GetLSLIntegerItem(idx++);
8994 if (face == ScriptBaseClass.ALL_SIDES)
8995 {
8996 for (face = 0; face < 21; face++)
8997 {
8998 res.Add(new LSL_String(""));
8999 res.Add(new LSL_Vector(0,0,0));
9000 res.Add(new LSL_Vector(0,0,0));
9001 res.Add(new LSL_Float(0.0));
9002 }
9003 }
9004 else
9005 {
9006 if (face >= 0 && face < 21)
9007 {
9008 res.Add(new LSL_String(""));
9009 res.Add(new LSL_Vector(0,0,0));
9010 res.Add(new LSL_Vector(0,0,0));
9011 res.Add(new LSL_Float(0.0));
9012 }
9013 }
9014 break;
9015
9016 case (int)ScriptBaseClass.PRIM_COLOR:
9017 if (remain < 1)
9018 return res;
9019
9020 face = (int)rules.GetLSLIntegerItem(idx++);
9021
9022 if (face == ScriptBaseClass.ALL_SIDES)
9023 {
9024 for (face = 0; face < 21; face++)
9025 {
9026 res.Add(new LSL_Vector(0,0,0));
9027 res.Add(new LSL_Float(0));
9028 }
9029 }
9030 else
9031 {
9032 res.Add(new LSL_Vector(0,0,0));
9033 res.Add(new LSL_Float(0));
9034 }
9035 break;
9036
9037 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
9038 if (remain < 1)
9039 return res;
9040 face = (int)rules.GetLSLIntegerItem(idx++);
9041
9042 if (face == ScriptBaseClass.ALL_SIDES)
9043 {
9044 for (face = 0; face < 21; face++)
9045 {
9046 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE));
9047 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE));
9048 }
9049 }
9050 else
9051 {
9052 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE));
9053 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE));
9054 }
9055 break;
9056
9057 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
9058 if (remain < 1)
9059 return res;
9060 face = (int)rules.GetLSLIntegerItem(idx++);
9061
9062 if (face == ScriptBaseClass.ALL_SIDES)
9063 {
9064 for (face = 0; face < 21; face++)
9065 {
9066 res.Add(new LSL_Integer(ScriptBaseClass.FALSE));
9067 }
9068 }
9069 else
9070 {
9071 res.Add(new LSL_Integer(ScriptBaseClass.FALSE));
9072 }
9073 break;
9074
9075 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
9076 res.Add(new LSL_Integer(0));
9077 res.Add(new LSL_Integer(0));// softness
9078 res.Add(new LSL_Float(0.0f)); // gravity
9079 res.Add(new LSL_Float(0.0f)); // friction
9080 res.Add(new LSL_Float(0.0f)); // wind
9081 res.Add(new LSL_Float(0.0f)); // tension
9082 res.Add(new LSL_Vector(0f,0f,0f));
9083 break;
9084
9085 case (int)ScriptBaseClass.PRIM_TEXGEN:
9086 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
9087 if (remain < 1)
9088 return res;
9089 face = (int)rules.GetLSLIntegerItem(idx++);
9090
9091 if (face == ScriptBaseClass.ALL_SIDES)
9092 {
9093 for (face = 0; face < 21; face++)
9094 {
9095 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
9096 }
9097 }
9098 else
9099 {
9100 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
9101 }
9102 break;
9103
9104 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
9105 res.Add(new LSL_Integer(0));
9106 res.Add(new LSL_Vector(0f,0f,0f));
9107 res.Add(new LSL_Float(0f)); // intensity
9108 res.Add(new LSL_Float(0f)); // radius
9109 res.Add(new LSL_Float(0f)); // falloff
9110 break;
9111
9112 case (int)ScriptBaseClass.PRIM_GLOW:
9113 if (remain < 1)
9114 return res;
9115 face = (int)rules.GetLSLIntegerItem(idx++);
9116
9117 if (face == ScriptBaseClass.ALL_SIDES)
9118 {
9119 for (face = 0; face < 21; face++)
9120 {
9121 res.Add(new LSL_Float(0f));
9122 }
9123 }
9124 else
9125 {
9126 res.Add(new LSL_Float(0f));
9127 }
9128 break;
9129
9130 case (int)ScriptBaseClass.PRIM_TEXT:
9131 res.Add(new LSL_String(""));
9132 res.Add(new LSL_Vector(0f,0f,0f));
9133 res.Add(new LSL_Float(1.0f));
9134 break;
9135
9136 case (int)ScriptBaseClass.PRIM_NAME:
9137 res.Add(new LSL_String(avatar.Name));
9138 break;
9139
9140 case (int)ScriptBaseClass.PRIM_DESC:
9141 res.Add(new LSL_String(""));
9142 break;
9143
9144 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
9145 Quaternion lrot = avatar.Rotation;
9146
9147 if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart)
9148 {
9149 lrot = sitPart.RotationOffset * lrot; // apply sit part rotation offset
9150 }
9151 res.Add(new LSL_Rotation(lrot.X, lrot.Y, lrot.Z, lrot.W));
9152 break;
9153
9154 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
9155 Vector3 lpos = avatar.OffsetPosition; // pos relative to sit part
9156 Vector3 lsitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f * 2.0f);
9157 lpos -= lsitOffset;
9158
9159 if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart)
9160 {
9161 lpos = sitPart.OffsetPosition + (lpos * sitPart.RotationOffset); // make it relative to root prim
9162 }
9163 res.Add(new LSL_Vector(lpos.X,lpos.Y,lpos.Z));
9164 break;
9165
9166 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
9167 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
9168 return res;
9169 LSL_Integer new_linknumber = rules.GetLSLIntegerItem(idx++);
9170 LSL_List new_rules = rules.GetSublist(idx, -1);
9171
9172 res += llGetLinkPrimitiveParams((int)new_linknumber, new_rules);
9173 return res;
8703 } 9174 }
8704 } 9175 }
8705
8706 return res; 9176 return res;
8707 } 9177 }
8708 9178
8709 public LSL_List GetPrimParams(SceneObjectPart part, LSL_List rules, ref LSL_List res) 9179 public LSL_List GetLinkPrimitiveParams(SceneObjectPart part, LSL_List rules)
8710 { 9180 {
9181 LSL_List res = new LSL_List();
8711 int idx=0; 9182 int idx=0;
8712 while (idx < rules.Length) 9183 while (idx < rules.Length)
8713 { 9184 {
@@ -8845,7 +9316,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8845 9316
8846 case (int)ScriptBaseClass.PRIM_TEXTURE: 9317 case (int)ScriptBaseClass.PRIM_TEXTURE:
8847 if (remain < 1) 9318 if (remain < 1)
8848 return null; 9319 return res;
8849 9320
8850 int face = (int)rules.GetLSLIntegerItem(idx++); 9321 int face = (int)rules.GetLSLIntegerItem(idx++);
8851 Primitive.TextureEntry tex = part.Shape.Textures; 9322 Primitive.TextureEntry tex = part.Shape.Textures;
@@ -8885,7 +9356,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8885 9356
8886 case (int)ScriptBaseClass.PRIM_COLOR: 9357 case (int)ScriptBaseClass.PRIM_COLOR:
8887 if (remain < 1) 9358 if (remain < 1)
8888 return null; 9359 return res;
8889 9360
8890 face=(int)rules.GetLSLIntegerItem(idx++); 9361 face=(int)rules.GetLSLIntegerItem(idx++);
8891 9362
@@ -8914,8 +9385,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8914 9385
8915 case (int)ScriptBaseClass.PRIM_BUMP_SHINY: 9386 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
8916 if (remain < 1) 9387 if (remain < 1)
8917 return null; 9388 return res;
8918
8919 face = (int)rules.GetLSLIntegerItem(idx++); 9389 face = (int)rules.GetLSLIntegerItem(idx++);
8920 9390
8921 tex = part.Shape.Textures; 9391 tex = part.Shape.Textures;
@@ -8971,8 +9441,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8971 9441
8972 case (int)ScriptBaseClass.PRIM_FULLBRIGHT: 9442 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
8973 if (remain < 1) 9443 if (remain < 1)
8974 return null; 9444 return res;
8975
8976 face = (int)rules.GetLSLIntegerItem(idx++); 9445 face = (int)rules.GetLSLIntegerItem(idx++);
8977 9446
8978 tex = part.Shape.Textures; 9447 tex = part.Shape.Textures;
@@ -9026,8 +9495,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9026 case (int)ScriptBaseClass.PRIM_TEXGEN: 9495 case (int)ScriptBaseClass.PRIM_TEXGEN:
9027 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR) 9496 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
9028 if (remain < 1) 9497 if (remain < 1)
9029 return null; 9498 return res;
9030
9031 face = (int)rules.GetLSLIntegerItem(idx++); 9499 face = (int)rules.GetLSLIntegerItem(idx++);
9032 9500
9033 tex = part.Shape.Textures; 9501 tex = part.Shape.Textures;
@@ -9075,8 +9543,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9075 9543
9076 case (int)ScriptBaseClass.PRIM_GLOW: 9544 case (int)ScriptBaseClass.PRIM_GLOW:
9077 if (remain < 1) 9545 if (remain < 1)
9078 return null; 9546 return res;
9079
9080 face = (int)rules.GetLSLIntegerItem(idx++); 9547 face = (int)rules.GetLSLIntegerItem(idx++);
9081 9548
9082 tex = part.Shape.Textures; 9549 tex = part.Shape.Textures;
@@ -9120,24 +9587,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9120 case (int)ScriptBaseClass.PRIM_POS_LOCAL: 9587 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
9121 res.Add(new LSL_Vector(GetPartLocalPos(part))); 9588 res.Add(new LSL_Vector(GetPartLocalPos(part)));
9122 break; 9589 break;
9123 case (int)ScriptBaseClass.PRIM_SLICE:
9124 PrimType prim_type = part.GetPrimType();
9125 bool useProfileBeginEnd = (prim_type == PrimType.SPHERE || prim_type == PrimType.TORUS || prim_type == PrimType.TUBE || prim_type == PrimType.RING);
9126 res.Add(new LSL_Vector(
9127 (useProfileBeginEnd ? part.Shape.ProfileBegin : part.Shape.PathBegin) / 50000.0,
9128 1 - (useProfileBeginEnd ? part.Shape.ProfileEnd : part.Shape.PathEnd) / 50000.0,
9129 0
9130 ));
9131 break;
9132 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
9133 if(remain < 3)
9134 return null;
9135 9590
9136 return rules.GetSublist(idx, -1); 9591 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
9592 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
9593 return res;
9594 LSL_Integer new_linknumber = rules.GetLSLIntegerItem(idx++);
9595 LSL_List new_rules = rules.GetSublist(idx, -1);
9596 LSL_List tres = llGetLinkPrimitiveParams((int)new_linknumber, new_rules);
9597 res += tres;
9598 return res;
9137 } 9599 }
9138 } 9600 }
9139 9601 return res;
9140 return null;
9141 } 9602 }
9142 9603
9143 public LSL_List llGetPrimMediaParams(int face, LSL_List rules) 9604 public LSL_List llGetPrimMediaParams(int face, LSL_List rules)
@@ -10050,10 +10511,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10050 10511
10051 GridRegion info; 10512 GridRegion info;
10052 10513
10053 if (World.RegionInfo.RegionName == simulator) 10514 if (m_ScriptEngine.World.RegionInfo.RegionName == simulator) //Det data for this simulator?
10054 info = new GridRegion(World.RegionInfo); 10515
10516 info = new GridRegion(m_ScriptEngine.World.RegionInfo);
10055 else 10517 else
10056 info = World.GridService.GetRegionByName(m_ScriptEngine.World.RegionInfo.ScopeID, simulator); 10518 info = m_ScriptEngine.World.GridService.GetRegionByName(m_ScriptEngine.World.RegionInfo.ScopeID, simulator);
10057 10519
10058 switch (data) 10520 switch (data)
10059 { 10521 {
@@ -10063,24 +10525,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10063 ScriptSleep(1000); 10525 ScriptSleep(1000);
10064 return UUID.Zero.ToString(); 10526 return UUID.Zero.ToString();
10065 } 10527 }
10066 10528 if (m_ScriptEngine.World.RegionInfo.RegionName != simulator)
10067 bool isHypergridRegion = false;
10068
10069 if (World.RegionInfo.RegionName != simulator && info.RegionSecret != "")
10070 {
10071 // Hypergrid is currently placing real destination region co-ords into RegionSecret.
10072 // But other code can also use this field for a genuine RegionSecret! Therefore, if
10073 // anything is present we need to disambiguate.
10074 //
10075 // FIXME: Hypergrid should be storing this data in a different field.
10076 RegionFlags regionFlags
10077 = (RegionFlags)m_ScriptEngine.World.GridService.GetRegionFlags(
10078 info.ScopeID, info.RegionID);
10079 isHypergridRegion = (regionFlags & RegionFlags.Hyperlink) != 0;
10080 }
10081
10082 if (isHypergridRegion)
10083 { 10529 {
10530 //Hypergrid Region co-ordinates
10084 uint rx = 0, ry = 0; 10531 uint rx = 0, ry = 0;
10085 Utils.LongToUInts(Convert.ToUInt64(info.RegionSecret), out rx, out ry); 10532 Utils.LongToUInts(Convert.ToUInt64(info.RegionSecret), out rx, out ry);
10086 10533
@@ -10091,7 +10538,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10091 } 10538 }
10092 else 10539 else
10093 { 10540 {
10094 // Local grid co-oridnates 10541 //Local-cooridnates
10095 reply = new LSL_Vector( 10542 reply = new LSL_Vector(
10096 info.RegionLocX, 10543 info.RegionLocX,
10097 info.RegionLocY, 10544 info.RegionLocY,
@@ -10545,20 +10992,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10545 switch ((ParcelMediaCommandEnum) Convert.ToInt32(aList.Data[i].ToString())) 10992 switch ((ParcelMediaCommandEnum) Convert.ToInt32(aList.Data[i].ToString()))
10546 { 10993 {
10547 case ParcelMediaCommandEnum.Url: 10994 case ParcelMediaCommandEnum.Url:
10548 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaURL)); 10995 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL));
10549 break; 10996 break;
10550 case ParcelMediaCommandEnum.Desc: 10997 case ParcelMediaCommandEnum.Desc:
10551 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).Description)); 10998 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).Description));
10552 break; 10999 break;
10553 case ParcelMediaCommandEnum.Texture: 11000 case ParcelMediaCommandEnum.Texture:
10554 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaID.ToString())); 11001 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaID.ToString()));
10555 break; 11002 break;
10556 case ParcelMediaCommandEnum.Type: 11003 case ParcelMediaCommandEnum.Type:
10557 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaType)); 11004 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaType));
10558 break; 11005 break;
10559 case ParcelMediaCommandEnum.Size: 11006 case ParcelMediaCommandEnum.Size:
10560 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaWidth)); 11007 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaWidth));
10561 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaHeight)); 11008 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaHeight));
10562 break; 11009 break;
10563 default: 11010 default:
10564 ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url; 11011 ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url;
@@ -10728,8 +11175,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10728 ScenePresence avatar = World.GetScenePresence(detectedParams.Key); 11175 ScenePresence avatar = World.GetScenePresence(detectedParams.Key);
10729 if (avatar != null) 11176 if (avatar != null)
10730 { 11177 {
10731 avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name, 11178 avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name, simname,
10732 simname, pos, lookAt); 11179 new Vector3((float)pos.x, (float)pos.y, (float)pos.z),
11180 new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z));
10733 } 11181 }
10734 11182
10735 ScriptSleep(1000); 11183 ScriptSleep(1000);
@@ -10914,30 +11362,31 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10914 public LSL_Float llListStatistics(int operation, LSL_List src) 11362 public LSL_Float llListStatistics(int operation, LSL_List src)
10915 { 11363 {
10916 m_host.AddScriptLPS(1); 11364 m_host.AddScriptLPS(1);
11365 LSL_List nums = LSL_List.ToDoubleList(src);
10917 switch (operation) 11366 switch (operation)
10918 { 11367 {
10919 case ScriptBaseClass.LIST_STAT_RANGE: 11368 case ScriptBaseClass.LIST_STAT_RANGE:
10920 return src.Range(); 11369 return nums.Range();
10921 case ScriptBaseClass.LIST_STAT_MIN: 11370 case ScriptBaseClass.LIST_STAT_MIN:
10922 return src.Min(); 11371 return nums.Min();
10923 case ScriptBaseClass.LIST_STAT_MAX: 11372 case ScriptBaseClass.LIST_STAT_MAX:
10924 return src.Max(); 11373 return nums.Max();
10925 case ScriptBaseClass.LIST_STAT_MEAN: 11374 case ScriptBaseClass.LIST_STAT_MEAN:
10926 return src.Mean(); 11375 return nums.Mean();
10927 case ScriptBaseClass.LIST_STAT_MEDIAN: 11376 case ScriptBaseClass.LIST_STAT_MEDIAN:
10928 return LSL_List.ToDoubleList(src).Median(); 11377 return nums.Median();
10929 case ScriptBaseClass.LIST_STAT_NUM_COUNT: 11378 case ScriptBaseClass.LIST_STAT_NUM_COUNT:
10930 return src.NumericLength(); 11379 return nums.NumericLength();
10931 case ScriptBaseClass.LIST_STAT_STD_DEV: 11380 case ScriptBaseClass.LIST_STAT_STD_DEV:
10932 return src.StdDev(); 11381 return nums.StdDev();
10933 case ScriptBaseClass.LIST_STAT_SUM: 11382 case ScriptBaseClass.LIST_STAT_SUM:
10934 return src.Sum(); 11383 return nums.Sum();
10935 case ScriptBaseClass.LIST_STAT_SUM_SQUARES: 11384 case ScriptBaseClass.LIST_STAT_SUM_SQUARES:
10936 return src.SumSqrs(); 11385 return nums.SumSqrs();
10937 case ScriptBaseClass.LIST_STAT_GEOMETRIC_MEAN: 11386 case ScriptBaseClass.LIST_STAT_GEOMETRIC_MEAN:
10938 return src.GeometricMean(); 11387 return nums.GeometricMean();
10939 case ScriptBaseClass.LIST_STAT_HARMONIC_MEAN: 11388 case ScriptBaseClass.LIST_STAT_HARMONIC_MEAN:
10940 return src.HarmonicMean(); 11389 return nums.HarmonicMean();
10941 default: 11390 default:
10942 return 0.0; 11391 return 0.0;
10943 } 11392 }
@@ -11295,7 +11744,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11295 public LSL_List llGetParcelDetails(LSL_Vector pos, LSL_List param) 11744 public LSL_List llGetParcelDetails(LSL_Vector pos, LSL_List param)
11296 { 11745 {
11297 m_host.AddScriptLPS(1); 11746 m_host.AddScriptLPS(1);
11298 LandData land = World.GetLandData(pos); 11747 LandData land = World.GetLandData((float)pos.x, (float)pos.y);
11299 if (land == null) 11748 if (land == null)
11300 { 11749 {
11301 return new LSL_List(0); 11750 return new LSL_List(0);
@@ -11463,12 +11912,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11463 else 11912 else
11464 rot = obj.GetWorldRotation(); 11913 rot = obj.GetWorldRotation();
11465 11914
11466 LSL_Rotation objrot = new LSL_Rotation(rot); 11915 LSL_Rotation objrot = new LSL_Rotation(rot.X, rot.Y, rot.Z, rot.W);
11467 ret.Add(objrot); 11916 ret.Add(objrot);
11468 } 11917 }
11469 break; 11918 break;
11470 case ScriptBaseClass.OBJECT_VELOCITY: 11919 case ScriptBaseClass.OBJECT_VELOCITY:
11471 ret.Add(new LSL_Vector(obj.Velocity)); 11920 Vector3 ovel = obj.Velocity;
11921 ret.Add(new LSL_Vector(ovel.X, ovel.Y, ovel.Z));
11472 break; 11922 break;
11473 case ScriptBaseClass.OBJECT_OWNER: 11923 case ScriptBaseClass.OBJECT_OWNER:
11474 ret.Add(new LSL_String(obj.OwnerID.ToString())); 11924 ret.Add(new LSL_String(obj.OwnerID.ToString()));
@@ -11555,12 +12005,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11555 12005
11556 internal void Deprecated(string command) 12006 internal void Deprecated(string command)
11557 { 12007 {
11558 throw new ScriptException("Command deprecated: " + command); 12008 throw new Exception("Command deprecated: " + command);
11559 } 12009 }
11560 12010
11561 internal void LSLError(string msg) 12011 internal void LSLError(string msg)
11562 { 12012 {
11563 throw new ScriptException("LSL Runtime Error: " + msg); 12013 throw new Exception("LSL Runtime Error: " + msg);
11564 } 12014 }
11565 12015
11566 public delegate void AssetRequestCallback(UUID assetID, AssetBase asset); 12016 public delegate void AssetRequestCallback(UUID assetID, AssetBase asset);
@@ -11681,7 +12131,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11681 return tid.ToString(); 12131 return tid.ToString();
11682 } 12132 }
11683 12133
11684 public void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules, string originFunc) 12134 public void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules)
11685 { 12135 {
11686 SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim)); 12136 SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim));
11687 if (obj == null) 12137 if (obj == null)
@@ -11690,41 +12140,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11690 if (obj.OwnerID != m_host.OwnerID) 12140 if (obj.OwnerID != m_host.OwnerID)
11691 return; 12141 return;
11692 12142
11693 uint rulesParsed = 0; 12143 LSL_List remaining = SetPrimParams(obj, rules);
11694 LSL_List remaining = SetPrimParams(obj, rules, originFunc, ref rulesParsed);
11695 12144
11696 while ((object)remaining != null && remaining.Length > 2) 12145 while ((object)remaining != null && remaining.Length > 2)
11697 { 12146 {
11698 LSL_Integer newLink = remaining.GetLSLIntegerItem(0); 12147 LSL_Integer newLink = remaining.GetLSLIntegerItem(0);
11699 LSL_List newrules = remaining.GetSublist(1, -1); 12148 LSL_List newrules = remaining.GetSublist(1, -1);
11700 foreach(SceneObjectPart part in GetLinkParts(obj, newLink)){ 12149 foreach(SceneObjectPart part in GetLinkParts(obj, newLink)){
11701 remaining = SetPrimParams(part, newrules, originFunc, ref rulesParsed); 12150 remaining = SetPrimParams(part, newrules);
11702 } 12151 }
11703 } 12152 }
11704 } 12153 }
11705 12154
11706 public LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules) 12155 public LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules)
11707 { 12156 {
11708 SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim)); 12157 SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim));
12158 if (obj == null)
12159 return new LSL_List();
11709 12160
11710 LSL_List result = new LSL_List(); 12161 if (obj.OwnerID != m_host.OwnerID)
11711 12162 return new LSL_List();
11712 if (obj != null && obj.OwnerID != m_host.OwnerID)
11713 {
11714 LSL_List remaining = GetPrimParams(obj, rules, ref result);
11715
11716 while (remaining != null && remaining.Length > 2)
11717 {
11718 int linknumber = remaining.GetLSLIntegerItem(0);
11719 rules = remaining.GetSublist(1, -1);
11720 List<SceneObjectPart> parts = GetLinkParts(linknumber);
11721
11722 foreach (SceneObjectPart part in parts)
11723 remaining = GetPrimParams(part, rules, ref result);
11724 }
11725 }
11726 12163
11727 return result; 12164 return GetLinkPrimitiveParams(obj, rules);
11728 } 12165 }
11729 12166
11730 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link) 12167 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link)
@@ -12087,8 +12524,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12087 12524
12088 m_host.AddScriptLPS(1); 12525 m_host.AddScriptLPS(1);
12089 12526
12090 Vector3 rayStart = start; 12527 Vector3 rayStart = new Vector3((float)start.x, (float)start.y, (float)start.z);
12091 Vector3 rayEnd = end; 12528 Vector3 rayEnd = new Vector3((float)end.x, (float)end.y, (float)end.z);
12092 Vector3 dir = rayEnd - rayStart; 12529 Vector3 dir = rayEnd - rayStart;
12093 12530
12094 float dist = Vector3.Mag(dir); 12531 float dist = Vector3.Mag(dir);
@@ -12662,455 +13099,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12662 } 13099 }
12663 } 13100 }
12664 } 13101 }
12665
12666 protected LSL_List SetPrimParams(ScenePresence av, LSL_List rules, string originFunc, ref uint rulesParsed)
12667 {
12668 //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset.
12669
12670 int idx = 0;
12671 int idxStart = 0;
12672
12673 bool positionChanged = false;
12674 Vector3 finalPos = Vector3.Zero;
12675
12676 try
12677 {
12678 while (idx < rules.Length)
12679 {
12680 ++rulesParsed;
12681 int code = rules.GetLSLIntegerItem(idx++);
12682
12683 int remain = rules.Length - idx;
12684 idxStart = idx;
12685
12686 switch (code)
12687 {
12688 case (int)ScriptBaseClass.PRIM_POSITION:
12689 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
12690 {
12691 if (remain < 1)
12692 return null;
12693
12694 LSL_Vector v;
12695 v = rules.GetVector3Item(idx++);
12696
12697 SceneObjectPart part = World.GetSceneObjectPart(av.ParentID);
12698 if (part == null)
12699 break;
12700
12701 LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION;
12702 LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR;
12703 if (part.LinkNum > 1)
12704 {
12705 localRot = GetPartLocalRot(part);
12706 localPos = GetPartLocalPos(part);
12707 }
12708
12709 v -= localPos;
12710 v /= localRot;
12711
12712 LSL_Vector sitOffset = (llRot2Up(new LSL_Rotation(av.Rotation.X, av.Rotation.Y, av.Rotation.Z, av.Rotation.W)) * av.Appearance.AvatarHeight * 0.02638f);
12713
12714 v = v + 2 * sitOffset;
12715
12716 av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z);
12717 av.SendAvatarDataToAllAgents();
12718
12719 }
12720 break;
12721
12722 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
12723 case (int)ScriptBaseClass.PRIM_ROTATION:
12724 {
12725 if (remain < 1)
12726 return null;
12727
12728 LSL_Rotation r;
12729 r = rules.GetQuaternionItem(idx++);
12730
12731 SceneObjectPart part = World.GetSceneObjectPart(av.ParentID);
12732 if (part == null)
12733 break;
12734
12735 LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION;
12736 LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR;
12737
12738 if (part.LinkNum > 1)
12739 localRot = GetPartLocalRot(part);
12740
12741 r = r * llGetRootRotation() / localRot;
12742 av.Rotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s);
12743 av.SendAvatarDataToAllAgents();
12744 }
12745 break;
12746
12747 // parse rest doing nothing but number of parameters error check
12748 case (int)ScriptBaseClass.PRIM_SIZE:
12749 case (int)ScriptBaseClass.PRIM_MATERIAL:
12750 case (int)ScriptBaseClass.PRIM_PHANTOM:
12751 case (int)ScriptBaseClass.PRIM_PHYSICS:
12752 case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE:
12753 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
12754 case (int)ScriptBaseClass.PRIM_NAME:
12755 case (int)ScriptBaseClass.PRIM_DESC:
12756 if (remain < 1)
12757 return null;
12758 idx++;
12759 break;
12760
12761 case (int)ScriptBaseClass.PRIM_GLOW:
12762 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
12763 case (int)ScriptBaseClass.PRIM_TEXGEN:
12764 if (remain < 2)
12765 return null;
12766 idx += 2;
12767 break;
12768
12769 case (int)ScriptBaseClass.PRIM_TYPE:
12770 if (remain < 3)
12771 return null;
12772 code = (int)rules.GetLSLIntegerItem(idx++);
12773 remain = rules.Length - idx;
12774 switch (code)
12775 {
12776 case (int)ScriptBaseClass.PRIM_TYPE_BOX:
12777 case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER:
12778 case (int)ScriptBaseClass.PRIM_TYPE_PRISM:
12779 if (remain < 6)
12780 return null;
12781 idx += 6;
12782 break;
12783
12784 case (int)ScriptBaseClass.PRIM_TYPE_SPHERE:
12785 if (remain < 5)
12786 return null;
12787 idx += 5;
12788 break;
12789
12790 case (int)ScriptBaseClass.PRIM_TYPE_TORUS:
12791 case (int)ScriptBaseClass.PRIM_TYPE_TUBE:
12792 case (int)ScriptBaseClass.PRIM_TYPE_RING:
12793 if (remain < 11)
12794 return null;
12795 idx += 11;
12796 break;
12797
12798 case (int)ScriptBaseClass.PRIM_TYPE_SCULPT:
12799 if (remain < 2)
12800 return null;
12801 idx += 2;
12802 break;
12803 }
12804 break;
12805
12806 case (int)ScriptBaseClass.PRIM_COLOR:
12807 case (int)ScriptBaseClass.PRIM_TEXT:
12808 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
12809 case (int)ScriptBaseClass.PRIM_OMEGA:
12810 if (remain < 3)
12811 return null;
12812 idx += 3;
12813 break;
12814
12815 case (int)ScriptBaseClass.PRIM_TEXTURE:
12816 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
12817 case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL:
12818 if (remain < 5)
12819 return null;
12820 idx += 5;
12821 break;
12822
12823 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
12824 if (remain < 7)
12825 return null;
12826
12827 idx += 7;
12828 break;
12829
12830 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
12831 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
12832 return null;
12833
12834 return rules.GetSublist(idx, -1);
12835 }
12836 }
12837 }
12838 catch (InvalidCastException e)
12839 {
12840 ShoutError(string.Format(
12841 "{0} error running rule #{1}: arg #{2} ",
12842 originFunc, rulesParsed, idx - idxStart) + e.Message);
12843 }
12844 finally
12845 {
12846 if (positionChanged)
12847 {
12848 av.OffsetPosition = finalPos;
12849// av.SendAvatarDataToAllAgents();
12850 av.SendTerseUpdateToAllClients();
12851 positionChanged = false;
12852 }
12853 }
12854 return null;
12855 }
12856
12857 public LSL_List GetPrimParams(ScenePresence avatar, LSL_List rules, ref LSL_List res)
12858 {
12859 // avatars case
12860 // replies as SL wiki
12861
12862// SceneObjectPart sitPart = avatar.ParentPart; // most likelly it will be needed
12863 SceneObjectPart sitPart = World.GetSceneObjectPart(avatar.ParentID); // maybe better do this expensive search for it in case it's gone??
12864
12865 int idx = 0;
12866 while (idx < rules.Length)
12867 {
12868 int code = (int)rules.GetLSLIntegerItem(idx++);
12869 int remain = rules.Length - idx;
12870
12871 switch (code)
12872 {
12873 case (int)ScriptBaseClass.PRIM_MATERIAL:
12874 res.Add(new LSL_Integer((int)SOPMaterialData.SopMaterial.Flesh));
12875 break;
12876
12877 case (int)ScriptBaseClass.PRIM_PHYSICS:
12878 res.Add(new LSL_Integer(0));
12879 break;
12880
12881 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
12882 res.Add(new LSL_Integer(0));
12883 break;
12884
12885 case (int)ScriptBaseClass.PRIM_PHANTOM:
12886 res.Add(new LSL_Integer(0));
12887 break;
12888
12889 case (int)ScriptBaseClass.PRIM_POSITION:
12890
12891 Vector3 pos = avatar.OffsetPosition;
12892
12893 Vector3 sitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f *2.0f);
12894 pos -= sitOffset;
12895
12896 if( sitPart != null)
12897 pos = sitPart.GetWorldPosition() + pos * sitPart.GetWorldRotation();
12898
12899 res.Add(new LSL_Vector(pos.X,pos.Y,pos.Z));
12900 break;
12901
12902 case (int)ScriptBaseClass.PRIM_SIZE:
12903 // as in llGetAgentSize above
12904 res.Add(new LSL_Vector(0.45f, 0.6f, avatar.Appearance.AvatarHeight));
12905 break;
12906
12907 case (int)ScriptBaseClass.PRIM_ROTATION:
12908 Quaternion rot = avatar.Rotation;
12909 if (sitPart != null)
12910 {
12911 rot = sitPart.GetWorldRotation() * rot; // apply sit part world rotation
12912 }
12913
12914 res.Add(new LSL_Rotation (rot.X, rot.Y, rot.Z, rot.W));
12915 break;
12916
12917 case (int)ScriptBaseClass.PRIM_TYPE:
12918 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TYPE_BOX));
12919 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_HOLE_DEFAULT));
12920 res.Add(new LSL_Vector(0f,1.0f,0f));
12921 res.Add(new LSL_Float(0.0f));
12922 res.Add(new LSL_Vector(0, 0, 0));
12923 res.Add(new LSL_Vector(1.0f,1.0f,0f));
12924 res.Add(new LSL_Vector(0, 0, 0));
12925 break;
12926
12927 case (int)ScriptBaseClass.PRIM_TEXTURE:
12928 if (remain < 1)
12929 return null;
12930
12931 int face = (int)rules.GetLSLIntegerItem(idx++);
12932 if (face == ScriptBaseClass.ALL_SIDES)
12933 {
12934 for (face = 0; face < 21; face++)
12935 {
12936 res.Add(new LSL_String(""));
12937 res.Add(new LSL_Vector(0,0,0));
12938 res.Add(new LSL_Vector(0,0,0));
12939 res.Add(new LSL_Float(0.0));
12940 }
12941 }
12942 else
12943 {
12944 if (face >= 0 && face < 21)
12945 {
12946 res.Add(new LSL_String(""));
12947 res.Add(new LSL_Vector(0,0,0));
12948 res.Add(new LSL_Vector(0,0,0));
12949 res.Add(new LSL_Float(0.0));
12950 }
12951 }
12952 break;
12953
12954 case (int)ScriptBaseClass.PRIM_COLOR:
12955 if (remain < 1)
12956 return null;
12957
12958 face = (int)rules.GetLSLIntegerItem(idx++);
12959
12960 if (face == ScriptBaseClass.ALL_SIDES)
12961 {
12962 for (face = 0; face < 21; face++)
12963 {
12964 res.Add(new LSL_Vector(0,0,0));
12965 res.Add(new LSL_Float(0));
12966 }
12967 }
12968 else
12969 {
12970 res.Add(new LSL_Vector(0,0,0));
12971 res.Add(new LSL_Float(0));
12972 }
12973 break;
12974
12975 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
12976 if (remain < 1)
12977 return null;
12978 face = (int)rules.GetLSLIntegerItem(idx++);
12979
12980 if (face == ScriptBaseClass.ALL_SIDES)
12981 {
12982 for (face = 0; face < 21; face++)
12983 {
12984 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE));
12985 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE));
12986 }
12987 }
12988 else
12989 {
12990 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE));
12991 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE));
12992 }
12993 break;
12994
12995 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
12996 if (remain < 1)
12997 return null;
12998 face = (int)rules.GetLSLIntegerItem(idx++);
12999
13000 if (face == ScriptBaseClass.ALL_SIDES)
13001 {
13002 for (face = 0; face < 21; face++)
13003 {
13004 res.Add(new LSL_Integer(ScriptBaseClass.FALSE));
13005 }
13006 }
13007 else
13008 {
13009 res.Add(new LSL_Integer(ScriptBaseClass.FALSE));
13010 }
13011 break;
13012
13013 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
13014 res.Add(new LSL_Integer(0));
13015 res.Add(new LSL_Integer(0));// softness
13016 res.Add(new LSL_Float(0.0f)); // gravity
13017 res.Add(new LSL_Float(0.0f)); // friction
13018 res.Add(new LSL_Float(0.0f)); // wind
13019 res.Add(new LSL_Float(0.0f)); // tension
13020 res.Add(new LSL_Vector(0f,0f,0f));
13021 break;
13022
13023 case (int)ScriptBaseClass.PRIM_TEXGEN:
13024 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
13025 if (remain < 1)
13026 return null;
13027 face = (int)rules.GetLSLIntegerItem(idx++);
13028
13029 if (face == ScriptBaseClass.ALL_SIDES)
13030 {
13031 for (face = 0; face < 21; face++)
13032 {
13033 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
13034 }
13035 }
13036 else
13037 {
13038 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT));
13039 }
13040 break;
13041
13042 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
13043 res.Add(new LSL_Integer(0));
13044 res.Add(new LSL_Vector(0f,0f,0f));
13045 res.Add(new LSL_Float(0f)); // intensity
13046 res.Add(new LSL_Float(0f)); // radius
13047 res.Add(new LSL_Float(0f)); // falloff
13048 break;
13049
13050 case (int)ScriptBaseClass.PRIM_GLOW:
13051 if (remain < 1)
13052 return null;
13053 face = (int)rules.GetLSLIntegerItem(idx++);
13054
13055 if (face == ScriptBaseClass.ALL_SIDES)
13056 {
13057 for (face = 0; face < 21; face++)
13058 {
13059 res.Add(new LSL_Float(0f));
13060 }
13061 }
13062 else
13063 {
13064 res.Add(new LSL_Float(0f));
13065 }
13066 break;
13067
13068 case (int)ScriptBaseClass.PRIM_TEXT:
13069 res.Add(new LSL_String(""));
13070 res.Add(new LSL_Vector(0f,0f,0f));
13071 res.Add(new LSL_Float(1.0f));
13072 break;
13073
13074 case (int)ScriptBaseClass.PRIM_NAME:
13075 res.Add(new LSL_String(avatar.Name));
13076 break;
13077
13078 case (int)ScriptBaseClass.PRIM_DESC:
13079 res.Add(new LSL_String(""));
13080 break;
13081
13082 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
13083 Quaternion lrot = avatar.Rotation;
13084
13085 if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart)
13086 {
13087 lrot = sitPart.RotationOffset * lrot; // apply sit part rotation offset
13088 }
13089 res.Add(new LSL_Rotation(lrot.X, lrot.Y, lrot.Z, lrot.W));
13090 break;
13091
13092 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
13093 Vector3 lpos = avatar.OffsetPosition; // pos relative to sit part
13094 Vector3 lsitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f * 2.0f);
13095 lpos -= lsitOffset;
13096
13097 if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart)
13098 {
13099 lpos = sitPart.OffsetPosition + (lpos * sitPart.RotationOffset); // make it relative to root prim
13100 }
13101 res.Add(new LSL_Vector(lpos.X,lpos.Y,lpos.Z));
13102 break;
13103
13104 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
13105 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
13106 return null;
13107
13108 return rules.GetSublist(idx, -1);
13109 }
13110 }
13111
13112 return null;
13113 }
13114 } 13102 }
13115 13103
13116 public class NotecardCache 13104 public class NotecardCache
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs
index ceb4660..795de80 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs
@@ -304,7 +304,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
304 case (int)ScriptBaseClass.WL_CLOUD_DETAIL_XY_DENSITY: 304 case (int)ScriptBaseClass.WL_CLOUD_DETAIL_XY_DENSITY:
305 idx++; 305 idx++;
306 iV = rules.GetVector3Item(idx); 306 iV = rules.GetVector3Item(idx);
307 wl.cloudDetailXYDensity = iV; 307 wl.cloudDetailXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z);
308 break; 308 break;
309 case (int)ScriptBaseClass.WL_CLOUD_SCALE: 309 case (int)ScriptBaseClass.WL_CLOUD_SCALE:
310 idx++; 310 idx++;
@@ -329,7 +329,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
329 case (int)ScriptBaseClass.WL_CLOUD_XY_DENSITY: 329 case (int)ScriptBaseClass.WL_CLOUD_XY_DENSITY:
330 idx++; 330 idx++;
331 iV = rules.GetVector3Item(idx); 331 iV = rules.GetVector3Item(idx);
332 wl.cloudXYDensity = iV; 332 wl.cloudXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z);
333 break; 333 break;
334 case (int)ScriptBaseClass.WL_DENSITY_MULTIPLIER: 334 case (int)ScriptBaseClass.WL_DENSITY_MULTIPLIER:
335 idx++; 335 idx++;
@@ -384,7 +384,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
384 case (int)ScriptBaseClass.WL_REFLECTION_WAVELET_SCALE: 384 case (int)ScriptBaseClass.WL_REFLECTION_WAVELET_SCALE:
385 idx++; 385 idx++;
386 iV = rules.GetVector3Item(idx); 386 iV = rules.GetVector3Item(idx);
387 wl.reflectionWaveletScale = iV; 387 wl.reflectionWaveletScale = new Vector3((float)iV.x, (float)iV.y, (float)iV.z);
388 break; 388 break;
389 case (int)ScriptBaseClass.WL_REFRACT_SCALE_ABOVE: 389 case (int)ScriptBaseClass.WL_REFRACT_SCALE_ABOVE:
390 idx++; 390 idx++;
@@ -422,7 +422,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
422 case (int)ScriptBaseClass.WL_WATER_COLOR: 422 case (int)ScriptBaseClass.WL_WATER_COLOR:
423 idx++; 423 idx++;
424 iV = rules.GetVector3Item(idx); 424 iV = rules.GetVector3Item(idx);
425 wl.waterColor = iV; 425 wl.waterColor = new Vector3((float)iV.x, (float)iV.y, (float)iV.z);
426 break; 426 break;
427 case (int)ScriptBaseClass.WL_WATER_FOG_DENSITY_EXPONENT: 427 case (int)ScriptBaseClass.WL_WATER_FOG_DENSITY_EXPONENT:
428 idx++; 428 idx++;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
index 8f34833..7844c75 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
@@ -95,13 +95,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
95 95
96 internal void MODError(string msg) 96 internal void MODError(string msg)
97 { 97 {
98 throw new ScriptException("MOD Runtime Error: " + msg); 98 throw new Exception("MOD Runtime Error: " + msg);
99 } 99 }
100 100
101 /// <summary> 101 //
102 /// Dumps an error message on the debug console. 102 //Dumps an error message on the debug console.
103 /// </summary> 103 //
104 /// <param name='message'></param> 104
105 internal void MODShoutError(string message) 105 internal void MODShoutError(string message)
106 { 106 {
107 if (message.Length > 1023) 107 if (message.Length > 1023)
@@ -254,7 +254,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
254 254
255 object[] convertedParms = new object[parms.Length]; 255 object[] convertedParms = new object[parms.Length];
256 for (int i = 0; i < parms.Length; i++) 256 for (int i = 0; i < parms.Length; i++)
257 convertedParms[i] = ConvertFromLSL(parms[i],signature[i], fname); 257 convertedParms[i] = ConvertFromLSL(parms[i],signature[i]);
258 258
259 // now call the function, the contract with the function is that it will always return 259 // now call the function, the contract with the function is that it will always return
260 // non-null but don't trust it completely 260 // non-null but don't trust it completely
@@ -294,7 +294,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
294 294
295 /// <summary> 295 /// <summary>
296 /// </summary> 296 /// </summary>
297 protected object ConvertFromLSL(object lslparm, Type type, string fname) 297 protected object ConvertFromLSL(object lslparm, Type type)
298 { 298 {
299 // ---------- String ---------- 299 // ---------- String ----------
300 if (lslparm is LSL_String) 300 if (lslparm is LSL_String)
@@ -310,7 +310,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
310 // ---------- Integer ---------- 310 // ---------- Integer ----------
311 else if (lslparm is LSL_Integer) 311 else if (lslparm is LSL_Integer)
312 { 312 {
313 if (type == typeof(int) || type == typeof(float)) 313 if (type == typeof(int))
314 return (int)(LSL_Integer)lslparm; 314 return (int)(LSL_Integer)lslparm;
315 } 315 }
316 316
@@ -333,7 +333,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
333 { 333 {
334 if (type == typeof(OpenMetaverse.Quaternion)) 334 if (type == typeof(OpenMetaverse.Quaternion))
335 { 335 {
336 return (OpenMetaverse.Quaternion)((LSL_Rotation)lslparm); 336 LSL_Rotation rot = (LSL_Rotation)lslparm;
337 return new OpenMetaverse.Quaternion((float)rot.x,(float)rot.y,(float)rot.z,(float)rot.s);
337 } 338 }
338 } 339 }
339 340
@@ -342,7 +343,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
342 { 343 {
343 if (type == typeof(OpenMetaverse.Vector3)) 344 if (type == typeof(OpenMetaverse.Vector3))
344 { 345 {
345 return (OpenMetaverse.Vector3)((LSL_Vector)lslparm); 346 LSL_Vector vect = (LSL_Vector)lslparm;
347 return new OpenMetaverse.Vector3((float)vect.x,(float)vect.y,(float)vect.z);
346 } 348 }
347 } 349 }
348 350
@@ -359,27 +361,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
359 result[i] = (string)(LSL_String)plist[i]; 361 result[i] = (string)(LSL_String)plist[i];
360 else if (plist[i] is LSL_Integer) 362 else if (plist[i] is LSL_Integer)
361 result[i] = (int)(LSL_Integer)plist[i]; 363 result[i] = (int)(LSL_Integer)plist[i];
362 // The int check exists because of the many plain old int script constants in ScriptBase which
363 // are not LSL_Integers.
364 else if (plist[i] is int)
365 result[i] = plist[i];
366 else if (plist[i] is LSL_Float) 364 else if (plist[i] is LSL_Float)
367 result[i] = (float)(LSL_Float)plist[i]; 365 result[i] = (float)(LSL_Float)plist[i];
368 else if (plist[i] is LSL_Key) 366 else if (plist[i] is LSL_Key)
369 result[i] = new UUID((LSL_Key)plist[i]); 367 result[i] = new UUID((LSL_Key)plist[i]);
370 else if (plist[i] is LSL_Rotation) 368 else if (plist[i] is LSL_Rotation)
371 result[i] = (Quaternion)((LSL_Rotation)plist[i]); 369 {
370 LSL_Rotation rot = (LSL_Rotation)plist[i];
371 result[i] = new OpenMetaverse.Quaternion((float)rot.x,(float)rot.y,(float)rot.z,(float)rot.s);
372 }
372 else if (plist[i] is LSL_Vector) 373 else if (plist[i] is LSL_Vector)
373 result[i] = (Vector3)((LSL_Vector)plist[i]); 374 {
375 LSL_Vector vect = (LSL_Vector)plist[i];
376 result[i] = new OpenMetaverse.Vector3((float)vect.x,(float)vect.y,(float)vect.z);
377 }
374 else 378 else
375 MODError(String.Format("{0}: unknown LSL list element type", fname)); 379 MODError("unknown LSL list element type");
376 } 380 }
377 381
378 return result; 382 return result;
379 } 383 }
380 } 384 }
381 385
382 MODError(String.Format("{1}: parameter type mismatch; expecting {0}",type.Name, fname)); 386 MODError(String.Format("parameter type mismatch; expecting {0}",type.Name));
383 return null; 387 return null;
384 } 388 }
385 389
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 51c8c7e..80111f9 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -141,8 +141,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
141 internal bool m_debuggerSafe = false; 141 internal bool m_debuggerSafe = false;
142 internal Dictionary<string, FunctionPerms > m_FunctionPerms = new Dictionary<string, FunctionPerms >(); 142 internal Dictionary<string, FunctionPerms > m_FunctionPerms = new Dictionary<string, FunctionPerms >();
143 143
144 protected IUrlModule m_UrlModule = null;
145
146 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) 144 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item)
147 { 145 {
148 m_ScriptEngine = ScriptEngine; 146 m_ScriptEngine = ScriptEngine;
@@ -150,8 +148,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
150 m_item = item; 148 m_item = item;
151 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false); 149 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false);
152 150
153 m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>();
154
155 if (m_ScriptEngine.Config.GetBoolean("AllowOSFunctions", false)) 151 if (m_ScriptEngine.Config.GetBoolean("AllowOSFunctions", false))
156 m_OSFunctionsEnabled = true; 152 m_OSFunctionsEnabled = true;
157 153
@@ -218,7 +214,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
218 } 214 }
219 else 215 else
220 { 216 {
221 throw new ScriptException("OSSL Runtime Error: " + msg); 217 throw new Exception("OSSL Runtime Error: " + msg);
222 } 218 }
223 } 219 }
224 220
@@ -786,9 +782,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
786 782
787 // We will launch the teleport on a new thread so that when the script threads are terminated 783 // We will launch the teleport on a new thread so that when the script threads are terminated
788 // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting. 784 // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting.
789 Util.FireAndForget(o => World.RequestTeleportLocation( 785 Util.FireAndForget(
790 presence.ControllingClient, regionName, position, 786 o => World.RequestTeleportLocation(presence.ControllingClient, regionName,
791 lookat, (uint)TPFlags.ViaLocation)); 787 new Vector3((float)position.x, (float)position.y, (float)position.z),
788 new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation));
792 789
793 ScriptSleep(5000); 790 ScriptSleep(5000);
794 791
@@ -831,9 +828,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
831 828
832 // We will launch the teleport on a new thread so that when the script threads are terminated 829 // We will launch the teleport on a new thread so that when the script threads are terminated
833 // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting. 830 // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting.
834 Util.FireAndForget(o => World.RequestTeleportLocation( 831 Util.FireAndForget(
835 presence.ControllingClient, regionHandle, 832 o => World.RequestTeleportLocation(presence.ControllingClient, regionHandle,
836 position, lookat, (uint)TPFlags.ViaLocation)); 833 new Vector3((float)position.x, (float)position.y, (float)position.z),
834 new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation));
837 835
838 ScriptSleep(5000); 836 ScriptSleep(5000);
839 837
@@ -1682,11 +1680,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1682 return; 1680 return;
1683 } 1681 }
1684 1682
1685 MessageObject(objUUID, message);
1686 }
1687
1688 private void MessageObject(UUID objUUID, string message)
1689 {
1690 object[] resobj = new object[] { new LSL_Types.LSLString(m_host.UUID.ToString()), new LSL_Types.LSLString(message) }; 1683 object[] resobj = new object[] { new LSL_Types.LSLString(m_host.UUID.ToString()), new LSL_Types.LSLString(message) };
1691 1684
1692 SceneObjectPart sceneOP = World.GetSceneObjectPart(objUUID); 1685 SceneObjectPart sceneOP = World.GetSceneObjectPart(objUUID);
@@ -1789,24 +1782,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1789 protected string LoadNotecard(string notecardNameOrUuid) 1782 protected string LoadNotecard(string notecardNameOrUuid)
1790 { 1783 {
1791 UUID assetID = CacheNotecard(notecardNameOrUuid); 1784 UUID assetID = CacheNotecard(notecardNameOrUuid);
1785 StringBuilder notecardData = new StringBuilder();
1792 1786
1793 if (assetID != UUID.Zero) 1787 for (int count = 0; count < NotecardCache.GetLines(assetID); count++)
1794 { 1788 {
1795 StringBuilder notecardData = new StringBuilder(); 1789 string line = NotecardCache.GetLine(assetID, count) + "\n";
1796 1790
1797 for (int count = 0; count < NotecardCache.GetLines(assetID); count++) 1791// m_log.DebugFormat("[OSSL]: From notecard {0} loading line {1}", notecardNameOrUuid, line);
1798 { 1792
1799 string line = NotecardCache.GetLine(assetID, count) + "\n"; 1793 notecardData.Append(line);
1800
1801 // m_log.DebugFormat("[OSSL]: From notecard {0} loading line {1}", notecardNameOrUuid, line);
1802
1803 notecardData.Append(line);
1804 }
1805
1806 return notecardData.ToString();
1807 } 1794 }
1808 1795
1809 return null; 1796 return notecardData.ToString();
1810 } 1797 }
1811 1798
1812 /// <summary> 1799 /// <summary>
@@ -2272,25 +2259,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2272 CheckThreatLevel(ThreatLevel.High, "osGetLinkPrimitiveParams"); 2259 CheckThreatLevel(ThreatLevel.High, "osGetLinkPrimitiveParams");
2273 m_host.AddScriptLPS(1); 2260 m_host.AddScriptLPS(1);
2274 InitLSL(); 2261 InitLSL();
2275 // One needs to cast m_LSL_Api because we're using functions not
2276 // on the ILSL_Api interface.
2277 LSL_Api LSL_Api = (LSL_Api)m_LSL_Api;
2278 LSL_List retVal = new LSL_List(); 2262 LSL_List retVal = new LSL_List();
2279 LSL_List remaining = null; 2263 List<SceneObjectPart> parts = ((LSL_Api)m_LSL_Api).GetLinkParts(linknumber);
2280 List<SceneObjectPart> parts = LSL_Api.GetLinkParts(linknumber);
2281 foreach (SceneObjectPart part in parts) 2264 foreach (SceneObjectPart part in parts)
2282 { 2265 {
2283 remaining = LSL_Api.GetPrimParams(part, rules, ref retVal); 2266 retVal += ((LSL_Api)m_LSL_Api).GetLinkPrimitiveParams(part, rules);
2284 }
2285
2286 while (remaining != null && remaining.Length > 2)
2287 {
2288 linknumber = remaining.GetLSLIntegerItem(0);
2289 rules = remaining.GetSublist(1, -1);
2290 parts = LSL_Api.GetLinkParts(linknumber);
2291
2292 foreach (SceneObjectPart part in parts)
2293 remaining = LSL_Api.GetPrimParams(part, rules, ref retVal);
2294 } 2267 }
2295 return retVal; 2268 return retVal;
2296 } 2269 }
@@ -2379,18 +2352,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2379 return UUID.Zero.ToString(); 2352 return UUID.Zero.ToString();
2380 } 2353 }
2381 } 2354 }
2382 else
2383 {
2384 OSSLError(string.Format("osNpcCreate: Notecard reference '{0}' not found.", notecard));
2385 }
2386 } 2355 }
2387 2356
2357 if (appearance == null)
2358 return new LSL_Key(UUID.Zero.ToString());
2359
2388 UUID ownerID = UUID.Zero; 2360 UUID ownerID = UUID.Zero;
2389 if (owned) 2361 if (owned)
2390 ownerID = m_host.OwnerID; 2362 ownerID = m_host.OwnerID;
2391 UUID x = module.CreateNPC(firstname, 2363 UUID x = module.CreateNPC(firstname,
2392 lastname, 2364 lastname,
2393 position, 2365 new Vector3((float) position.x, (float) position.y, (float) position.z),
2394 ownerID, 2366 ownerID,
2395 senseAsAgent, 2367 senseAsAgent,
2396 World, 2368 World,
@@ -2453,10 +2425,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2453 return; 2425 return;
2454 2426
2455 string appearanceSerialized = LoadNotecard(notecard); 2427 string appearanceSerialized = LoadNotecard(notecard);
2456
2457 if (appearanceSerialized == null)
2458 OSSLError(string.Format("osNpcCreate: Notecard reference '{0}' not found.", notecard));
2459
2460 OSDMap appearanceOsd = (OSDMap)OSDParser.DeserializeLLSDXml(appearanceSerialized); 2428 OSDMap appearanceOsd = (OSDMap)OSDParser.DeserializeLLSDXml(appearanceSerialized);
2461// OSD a = OSDParser.DeserializeLLSDXml(appearanceSerialized); 2429// OSD a = OSDParser.DeserializeLLSDXml(appearanceSerialized);
2462// Console.WriteLine("appearanceSerialized {0}", appearanceSerialized); 2430// Console.WriteLine("appearanceSerialized {0}", appearanceSerialized);
@@ -2517,7 +2485,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2517 return new LSL_Vector(0, 0, 0); 2485 return new LSL_Vector(0, 0, 0);
2518 } 2486 }
2519 2487
2520 public void osNpcMoveTo(LSL_Key npc, LSL_Vector pos) 2488 public void osNpcMoveTo(LSL_Key npc, LSL_Vector position)
2521 { 2489 {
2522 CheckThreatLevel(ThreatLevel.High, "osNpcMoveTo"); 2490 CheckThreatLevel(ThreatLevel.High, "osNpcMoveTo");
2523 m_host.AddScriptLPS(1); 2491 m_host.AddScriptLPS(1);
@@ -2532,6 +2500,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2532 if (!module.CheckPermissions(npcId, m_host.OwnerID)) 2500 if (!module.CheckPermissions(npcId, m_host.OwnerID))
2533 return; 2501 return;
2534 2502
2503 Vector3 pos = new Vector3((float) position.x, (float) position.y, (float) position.z);
2535 module.MoveToTarget(npcId, World, pos, false, true, false); 2504 module.MoveToTarget(npcId, World, pos, false, true, false);
2536 } 2505 }
2537 } 2506 }
@@ -2551,10 +2520,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2551 if (!module.CheckPermissions(npcId, m_host.OwnerID)) 2520 if (!module.CheckPermissions(npcId, m_host.OwnerID))
2552 return; 2521 return;
2553 2522
2523 Vector3 pos = new Vector3((float)target.x, (float)target.y, (float)target.z);
2554 module.MoveToTarget( 2524 module.MoveToTarget(
2555 new UUID(npc.m_string), 2525 new UUID(npc.m_string),
2556 World, 2526 World,
2557 target, 2527 pos,
2558 (options & ScriptBaseClass.OS_NPC_NO_FLY) != 0, 2528 (options & ScriptBaseClass.OS_NPC_NO_FLY) != 0,
2559 (options & ScriptBaseClass.OS_NPC_LAND_AT_TARGET) != 0, 2529 (options & ScriptBaseClass.OS_NPC_LAND_AT_TARGET) != 0,
2560 (options & ScriptBaseClass.OS_NPC_RUNNING) != 0); 2530 (options & ScriptBaseClass.OS_NPC_RUNNING) != 0);
@@ -2606,7 +2576,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2606 ScenePresence sp = World.GetScenePresence(npcId); 2576 ScenePresence sp = World.GetScenePresence(npcId);
2607 2577
2608 if (sp != null) 2578 if (sp != null)
2609 sp.Rotation = rotation; 2579 sp.Rotation = LSL_Api.Rot2Quaternion(rotation);
2610 } 2580 }
2611 } 2581 }
2612 2582
@@ -2966,7 +2936,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2966 avatar.SpeedModifier = (float)SpeedModifier; 2936 avatar.SpeedModifier = (float)SpeedModifier;
2967 } 2937 }
2968 2938
2969 public void osKickAvatar(string FirstName, string SurName, string alert) 2939 public void osKickAvatar(string FirstName,string SurName,string alert)
2970 { 2940 {
2971 CheckThreatLevel(ThreatLevel.Severe, "osKickAvatar"); 2941 CheckThreatLevel(ThreatLevel.Severe, "osKickAvatar");
2972 m_host.AddScriptLPS(1); 2942 m_host.AddScriptLPS(1);
@@ -2980,21 +2950,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2980 sp.ControllingClient.Kick(alert); 2950 sp.ControllingClient.Kick(alert);
2981 2951
2982 // ...and close on our side 2952 // ...and close on our side
2983 sp.Scene.IncomingCloseAgent(sp.UUID, false); 2953 sp.Scene.IncomingCloseAgent(sp.UUID);
2984 } 2954 }
2985 }); 2955 });
2986 } 2956 }
2987
2988 public LSL_Float osGetHealth(string avatar)
2989 {
2990 CheckThreatLevel(ThreatLevel.None, "osGetHealth");
2991 m_host.AddScriptLPS(1);
2992
2993 LSL_Float health = new LSL_Float(-1);
2994 ScenePresence presence = World.GetScenePresence(new UUID(avatar));
2995 if (presence != null) health = presence.Health;
2996 return health;
2997 }
2998 2957
2999 public void osCauseDamage(string avatar, double damage) 2958 public void osCauseDamage(string avatar, double damage)
3000 { 2959 {
@@ -3007,7 +2966,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3007 ScenePresence presence = World.GetScenePresence(avatarId); 2966 ScenePresence presence = World.GetScenePresence(avatarId);
3008 if (presence != null) 2967 if (presence != null)
3009 { 2968 {
3010 LandData land = World.GetLandData(pos); 2969 LandData land = World.GetLandData((float)pos.X, (float)pos.Y);
3011 if ((land.Flags & (uint)ParcelFlags.AllowDamage) == (uint)ParcelFlags.AllowDamage) 2970 if ((land.Flags & (uint)ParcelFlags.AllowDamage) == (uint)ParcelFlags.AllowDamage)
3012 { 2971 {
3013 float health = presence.Health; 2972 float health = presence.Health;
@@ -3054,7 +3013,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3054 m_host.AddScriptLPS(1); 3013 m_host.AddScriptLPS(1);
3055 InitLSL(); 3014 InitLSL();
3056 3015
3057 return m_LSL_Api.GetPrimitiveParamsEx(prim, rules); 3016 return m_LSL_Api.GetLinkPrimitiveParamsEx(prim, rules);
3058 } 3017 }
3059 3018
3060 public void osSetPrimitiveParams(LSL_Key prim, LSL_List rules) 3019 public void osSetPrimitiveParams(LSL_Key prim, LSL_List rules)
@@ -3063,7 +3022,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3063 m_host.AddScriptLPS(1); 3022 m_host.AddScriptLPS(1);
3064 InitLSL(); 3023 InitLSL();
3065 3024
3066 m_LSL_Api.SetPrimitiveParamsEx(prim, rules, "osSetPrimitiveParams"); 3025 m_LSL_Api.SetPrimitiveParamsEx(prim, rules);
3067 } 3026 }
3068 3027
3069 /// <summary> 3028 /// <summary>
@@ -3295,8 +3254,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3295 } 3254 }
3296 } 3255 }
3297 3256
3298 #region Attachment commands
3299
3300 public void osForceAttachToAvatar(int attachmentPoint) 3257 public void osForceAttachToAvatar(int attachmentPoint)
3301 { 3258 {
3302 CheckThreatLevel(ThreatLevel.High, "osForceAttachToAvatar"); 3259 CheckThreatLevel(ThreatLevel.High, "osForceAttachToAvatar");
@@ -3386,175 +3343,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3386 ((LSL_Api)m_LSL_Api).DetachFromAvatar(); 3343 ((LSL_Api)m_LSL_Api).DetachFromAvatar();
3387 } 3344 }
3388 3345
3389 public LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints)
3390 {
3391 CheckThreatLevel(ThreatLevel.Moderate, "osGetNumberOfAttachments");
3392
3393 m_host.AddScriptLPS(1);
3394
3395 UUID targetUUID;
3396 ScenePresence target;
3397 LSL_List resp = new LSL_List();
3398
3399 if (attachmentPoints.Length >= 1 && UUID.TryParse(avatar.ToString(), out targetUUID) && World.TryGetScenePresence(targetUUID, out target))
3400 {
3401 foreach (object point in attachmentPoints.Data)
3402 {
3403 LSL_Integer ipoint = new LSL_Integer(
3404 (point is LSL_Integer || point is int || point is uint) ?
3405 (int)point :
3406 0
3407 );
3408 resp.Add(ipoint);
3409 if (ipoint == 0)
3410 {
3411 // indicates zero attachments
3412 resp.Add(new LSL_Integer(0));
3413 }
3414 else
3415 {
3416 // gets the number of attachments on the attachment point
3417 resp.Add(new LSL_Integer(target.GetAttachments((uint)ipoint).Count));
3418 }
3419 }
3420 }
3421
3422 return resp;
3423 }
3424
3425 public void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int options)
3426 {
3427 CheckThreatLevel(ThreatLevel.Moderate, "osMessageAttachments");
3428 m_host.AddScriptLPS(1);
3429
3430 UUID targetUUID;
3431 ScenePresence target;
3432
3433 if (attachmentPoints.Length >= 1 && UUID.TryParse(avatar.ToString(), out targetUUID) && World.TryGetScenePresence(targetUUID, out target))
3434 {
3435 List<int> aps = new List<int>();
3436 foreach (object point in attachmentPoints.Data)
3437 {
3438 int ipoint;
3439 if (int.TryParse(point.ToString(), out ipoint))
3440 {
3441 aps.Add(ipoint);
3442 }
3443 }
3444
3445 List<SceneObjectGroup> attachments = new List<SceneObjectGroup>();
3446
3447 bool msgAll = aps.Contains(ScriptBaseClass.OS_ATTACH_MSG_ALL);
3448 bool invertPoints = (options & ScriptBaseClass.OS_ATTACH_MSG_INVERT_POINTS) != 0;
3449
3450 if (msgAll && invertPoints)
3451 {
3452 return;
3453 }
3454 else if (msgAll || invertPoints)
3455 {
3456 attachments = target.GetAttachments();
3457 }
3458 else
3459 {
3460 foreach (int point in aps)
3461 {
3462 if (point > 0)
3463 {
3464 attachments.AddRange(target.GetAttachments((uint)point));
3465 }
3466 }
3467 }
3468
3469 // if we have no attachments at this point, exit now
3470 if (attachments.Count == 0)
3471 {
3472 return;
3473 }
3474
3475 List<SceneObjectGroup> ignoreThese = new List<SceneObjectGroup>();
3476
3477 if (invertPoints)
3478 {
3479 foreach (SceneObjectGroup attachment in attachments)
3480 {
3481 if (aps.Contains((int)attachment.AttachmentPoint))
3482 {
3483 ignoreThese.Add(attachment);
3484 }
3485 }
3486 }
3487
3488 foreach (SceneObjectGroup attachment in ignoreThese)
3489 {
3490 attachments.Remove(attachment);
3491 }
3492 ignoreThese.Clear();
3493
3494 // if inverting removed all attachments to check, exit now
3495 if (attachments.Count < 1)
3496 {
3497 return;
3498 }
3499
3500 if ((options & ScriptBaseClass.OS_ATTACH_MSG_OBJECT_CREATOR) != 0)
3501 {
3502 foreach (SceneObjectGroup attachment in attachments)
3503 {
3504 if (attachment.RootPart.CreatorID != m_host.CreatorID)
3505 {
3506 ignoreThese.Add(attachment);
3507 }
3508 }
3509
3510 foreach (SceneObjectGroup attachment in ignoreThese)
3511 {
3512 attachments.Remove(attachment);
3513 }
3514 ignoreThese.Clear();
3515
3516 // if filtering by same object creator removed all
3517 // attachments to check, exit now
3518 if (attachments.Count == 0)
3519 {
3520 return;
3521 }
3522 }
3523
3524 if ((options & ScriptBaseClass.OS_ATTACH_MSG_SCRIPT_CREATOR) != 0)
3525 {
3526 foreach (SceneObjectGroup attachment in attachments)
3527 {
3528 if (attachment.RootPart.CreatorID != m_item.CreatorID)
3529 {
3530 ignoreThese.Add(attachment);
3531 }
3532 }
3533
3534 foreach (SceneObjectGroup attachment in ignoreThese)
3535 {
3536 attachments.Remove(attachment);
3537 }
3538 ignoreThese.Clear();
3539
3540 // if filtering by object creator must match originating
3541 // script creator removed all attachments to check,
3542 // exit now
3543 if (attachments.Count == 0)
3544 {
3545 return;
3546 }
3547 }
3548
3549 foreach (SceneObjectGroup attachment in attachments)
3550 {
3551 MessageObject(attachment.RootPart.UUID, message);
3552 }
3553 }
3554 }
3555
3556 #endregion
3557
3558 /// <summary> 3346 /// <summary>
3559 /// Checks if thing is a UUID. 3347 /// Checks if thing is a UUID.
3560 /// </summary> 3348 /// </summary>
@@ -3604,166 +3392,5 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3604 3392
3605 return new LSL_Key(m_host.ParentGroup.FromPartID.ToString()); 3393 return new LSL_Key(m_host.ParentGroup.FromPartID.ToString());
3606 } 3394 }
3607
3608 /// <summary>
3609 /// Sets the response type for an HTTP request/response
3610 /// </summary>
3611 /// <returns></returns>
3612 public void osSetContentType(LSL_Key id, string type)
3613 {
3614 CheckThreatLevel(ThreatLevel.High, "osSetContentType");
3615
3616 if (m_UrlModule != null)
3617 m_UrlModule.HttpContentType(new UUID(id),type);
3618 }
3619
3620 /// Shout an error if the object owner did not grant the script the specified permissions.
3621 /// </summary>
3622 /// <param name="perms"></param>
3623 /// <returns>boolean indicating whether an error was shouted.</returns>
3624 protected bool ShoutErrorOnLackingOwnerPerms(int perms, string errorPrefix)
3625 {
3626 m_host.AddScriptLPS(1);
3627 bool fail = false;
3628 if (m_item.PermsGranter != m_host.OwnerID)
3629 {
3630 fail = true;
3631 OSSLShoutError(string.Format("{0}. Permissions not granted to owner.", errorPrefix));
3632 }
3633 else if ((m_item.PermsMask & perms) == 0)
3634 {
3635 fail = true;
3636 OSSLShoutError(string.Format("{0}. Permissions not granted.", errorPrefix));
3637 }
3638
3639 return fail;
3640 }
3641
3642 protected void DropAttachment(bool checkPerms)
3643 {
3644 if (checkPerms && ShoutErrorOnLackingOwnerPerms(ScriptBaseClass.PERMISSION_ATTACH, "Cannot drop attachment"))
3645 {
3646 return;
3647 }
3648
3649 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule;
3650 ScenePresence sp = attachmentsModule == null ? null : m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.OwnerID);
3651
3652 if (attachmentsModule != null && sp != null)
3653 {
3654 attachmentsModule.DetachSingleAttachmentToGround(sp, m_host.ParentGroup.LocalId);
3655 }
3656 }
3657
3658 protected void DropAttachmentAt(bool checkPerms, LSL_Vector pos, LSL_Rotation rot)
3659 {
3660 if (checkPerms && ShoutErrorOnLackingOwnerPerms(ScriptBaseClass.PERMISSION_ATTACH, "Cannot drop attachment"))
3661 {
3662 return;
3663 }
3664
3665 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule;
3666 ScenePresence sp = attachmentsModule == null ? null : m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.OwnerID);
3667
3668 if (attachmentsModule != null && sp != null)
3669 {
3670 attachmentsModule.DetachSingleAttachmentToGround(sp, m_host.ParentGroup.LocalId, pos, rot);
3671 }
3672 }
3673
3674 public void osDropAttachment()
3675 {
3676 CheckThreatLevel(ThreatLevel.Moderate, "osDropAttachment");
3677 m_host.AddScriptLPS(1);
3678
3679 DropAttachment(true);
3680 }
3681
3682 public void osForceDropAttachment()
3683 {
3684 CheckThreatLevel(ThreatLevel.High, "osForceDropAttachment");
3685 m_host.AddScriptLPS(1);
3686
3687 DropAttachment(false);
3688 }
3689
3690 public void osDropAttachmentAt(LSL_Vector pos, LSL_Rotation rot)
3691 {
3692 CheckThreatLevel(ThreatLevel.Moderate, "osDropAttachmentAt");
3693 m_host.AddScriptLPS(1);
3694
3695 DropAttachmentAt(true, pos, rot);
3696 }
3697
3698 public void osForceDropAttachmentAt(LSL_Vector pos, LSL_Rotation rot)
3699 {
3700 CheckThreatLevel(ThreatLevel.High, "osForceDropAttachmentAt");
3701 m_host.AddScriptLPS(1);
3702
3703 DropAttachmentAt(false, pos, rot);
3704 }
3705
3706 public LSL_Integer osListenRegex(int channelID, string name, string ID, string msg, int regexBitfield)
3707 {
3708 CheckThreatLevel(ThreatLevel.Low, "osListenRegex");
3709 m_host.AddScriptLPS(1);
3710 UUID keyID;
3711 UUID.TryParse(ID, out keyID);
3712
3713 // if we want the name to be used as a regular expression, ensure it is valid first.
3714 if ((regexBitfield & ScriptBaseClass.OS_LISTEN_REGEX_NAME) == ScriptBaseClass.OS_LISTEN_REGEX_NAME)
3715 {
3716 try
3717 {
3718 Regex.IsMatch("", name);
3719 }
3720 catch (Exception)
3721 {
3722 OSSLShoutError("Name regex is invalid.");
3723 return -1;
3724 }
3725 }
3726
3727 // if we want the msg to be used as a regular expression, ensure it is valid first.
3728 if ((regexBitfield & ScriptBaseClass.OS_LISTEN_REGEX_MESSAGE) == ScriptBaseClass.OS_LISTEN_REGEX_MESSAGE)
3729 {
3730 try
3731 {
3732 Regex.IsMatch("", msg);
3733 }
3734 catch (Exception)
3735 {
3736 OSSLShoutError("Message regex is invalid.");
3737 return -1;
3738 }
3739 }
3740
3741 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
3742 return (wComm == null) ? -1 : wComm.Listen(
3743 m_host.LocalId,
3744 m_item.ItemID,
3745 m_host.UUID,
3746 channelID,
3747 name,
3748 keyID,
3749 msg,
3750 regexBitfield
3751 );
3752 }
3753
3754 public LSL_Integer osRegexIsMatch(string input, string pattern)
3755 {
3756 CheckThreatLevel(ThreatLevel.Low, "osRegexIsMatch");
3757 m_host.AddScriptLPS(1);
3758 try
3759 {
3760 return Regex.IsMatch(input, pattern) ? 1 : 0;
3761 }
3762 catch (Exception)
3763 {
3764 OSSLShoutError("Possible invalid regular expression detected.");
3765 return 0;
3766 }
3767 }
3768 } 3395 }
3769} 3396}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
index 4dd795d..678f9d5 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
@@ -352,7 +352,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
352 q = avatar.Rotation; 352 q = avatar.Rotation;
353 } 353 }
354 354
355 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q); 355 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W);
356 LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r); 356 LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r);
357 double mag_fwd = LSL_Types.Vector3.Mag(forward_dir); 357 double mag_fwd = LSL_Types.Vector3.Mag(forward_dir);
358 358
@@ -429,8 +429,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
429 try 429 try
430 { 430 {
431 Vector3 diff = toRegionPos - fromRegionPos; 431 Vector3 diff = toRegionPos - fromRegionPos;
432 double dot = LSL_Types.Vector3.Dot(forward_dir, diff); 432 LSL_Types.Vector3 obj_dir = new LSL_Types.Vector3(diff.X, diff.Y, diff.Z);
433 double mag_obj = LSL_Types.Vector3.Mag(diff); 433 double dot = LSL_Types.Vector3.Dot(forward_dir, obj_dir);
434 double mag_obj = LSL_Types.Vector3.Mag(obj_dir);
434 ang_obj = Math.Acos(dot / (mag_fwd * mag_obj)); 435 ang_obj = Math.Acos(dot / (mag_fwd * mag_obj));
435 } 436 }
436 catch 437 catch
@@ -482,7 +483,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
482 q = avatar.Rotation; 483 q = avatar.Rotation;
483 } 484 }
484 485
485 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q); 486 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W);
486 LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r); 487 LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r);
487 double mag_fwd = LSL_Types.Vector3.Mag(forward_dir); 488 double mag_fwd = LSL_Types.Vector3.Mag(forward_dir);
488 bool attached = (SensePoint.ParentGroup.AttachmentPoint != 0); 489 bool attached = (SensePoint.ParentGroup.AttachmentPoint != 0);
@@ -563,8 +564,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
563 double ang_obj = 0; 564 double ang_obj = 0;
564 try 565 try
565 { 566 {
566 LSL_Types.Vector3 obj_dir = new LSL_Types.Vector3( 567 Vector3 diff = toRegionPos - fromRegionPos;
567 toRegionPos - fromRegionPos); 568 LSL_Types.Vector3 obj_dir = new LSL_Types.Vector3(diff.X, diff.Y, diff.Z);
568 double dot = LSL_Types.Vector3.Dot(forward_dir, obj_dir); 569 double dot = LSL_Types.Vector3.Dot(forward_dir, obj_dir);
569 double mag_obj = LSL_Types.Vector3.Mag(obj_dir); 570 double mag_obj = LSL_Types.Vector3.Mag(obj_dir);
570 ang_obj = Math.Acos(dot / (mag_fwd * mag_obj)); 571 ang_obj = Math.Acos(dot / (mag_fwd * mag_obj));
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
index 05c20f9..af35258 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs
@@ -429,8 +429,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
429 LSL_Integer llGetLinkNumberOfSides(LSL_Integer link); 429 LSL_Integer llGetLinkNumberOfSides(LSL_Integer link);
430 void llSetPhysicsMaterial(int material_bits, float material_gravity_modifier, float material_restitution, float material_friction, float material_density); 430 void llSetPhysicsMaterial(int material_bits, float material_gravity_modifier, float material_restitution, float material_friction, float material_density);
431 431
432 void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules, string originFunc); 432 void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules);
433 LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules);
433 void llSetKeyframedMotion(LSL_List frames, LSL_List options); 434 void llSetKeyframedMotion(LSL_List frames, LSL_List options);
434 LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules);
435 } 435 }
436} 436}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
index c447d1f..8c34ed3 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
@@ -40,75 +40,16 @@ using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
40 40
41namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces 41namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
42{ 42{
43 /// <summary>
44 /// To permit region owners to enable the extended scripting functionality
45 /// of OSSL, without allowing malicious scripts to access potentially
46 /// troublesome functions, each OSSL function is assigned a threat level,
47 /// and access to the functions is granted or denied based on a default
48 /// threshold set in OpenSim.ini (which can be overridden for individual
49 /// functions on a case-by-case basis)
50 /// </summary>
51 public enum ThreatLevel 43 public enum ThreatLevel
52 { 44 {
53 // Not documented, presumably means permanently disabled ?
54 NoAccess = -1, 45 NoAccess = -1,
55
56 /// <summary>
57 /// Function is no threat at all. It doesn't constitute a threat to
58 /// either users or the system and has no known side effects.
59 /// </summary>
60 None = 0, 46 None = 0,
61
62 /// <summary>
63 /// Abuse of this command can cause a nuisance to the region operator,
64 /// such as log message spew.
65 /// </summary>
66 Nuisance = 1, 47 Nuisance = 1,
67
68 /// <summary>
69 /// Extreme levels of abuse of this function can cause impaired
70 /// functioning of the region, or very gullible users can be tricked
71 /// into experiencing harmless effects.
72 /// </summary>
73 VeryLow = 2, 48 VeryLow = 2,
74
75 /// <summary>
76 /// Intentional abuse can cause crashes or malfunction under certain
77 /// circumstances, which can be easily rectified; or certain users can
78 /// be tricked into certain situations in an avoidable manner.
79 /// </summary>
80 Low = 3, 49 Low = 3,
81
82 /// <summary>
83 /// Intentional abuse can cause denial of service and crashes with
84 /// potential of data or state loss; or trusting users can be tricked
85 /// into embarrassing or uncomfortable situations.
86 /// </summary>
87 Moderate = 4, 50 Moderate = 4,
88
89 /// <summary>
90 /// Casual abuse can cause impaired functionality or temporary denial
91 /// of service conditions. Intentional abuse can easily cause crashes
92 /// with potential data loss, or can be used to trick experienced and
93 /// cautious users into unwanted situations, or changes global data
94 /// permanently and without undo ability.
95 /// </summary>
96 High = 5, 51 High = 5,
97
98 /// <summary>
99 /// Even normal use may, depending on the number of instances, or
100 /// frequency of use, result in severe service impairment or crash
101 /// with loss of data, or can be used to cause unwanted or harmful
102 /// effects on users without giving the user a means to avoid it.
103 /// </summary>
104 VeryHigh = 6, 52 VeryHigh = 6,
105
106 /// <summary>
107 /// Even casual use is a danger to region stability, or function allows
108 /// console or OS command execution, or function allows taking money
109 /// without consent, or allows deletion or modification of user data,
110 /// or allows the compromise of sensitive data by design.
111 /// </summary>
112 Severe = 7 53 Severe = 7
113 }; 54 };
114 55
@@ -157,7 +98,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
157 void osAvatarPlayAnimation(string avatar, string animation); 98 void osAvatarPlayAnimation(string avatar, string animation);
158 void osAvatarStopAnimation(string avatar, string animation); 99 void osAvatarStopAnimation(string avatar, string animation);
159 100
160 #region Attachment commands 101 // Attachment commands
161 102
162 /// <summary> 103 /// <summary>
163 /// Attach the object containing this script to the avatar that owns it without asking for PERMISSION_ATTACH 104 /// Attach the object containing this script to the avatar that owns it without asking for PERMISSION_ATTACH
@@ -192,29 +133,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
192 /// <remarks>Nothing happens if the object is not attached.</remarks> 133 /// <remarks>Nothing happens if the object is not attached.</remarks>
193 void osForceDetachFromAvatar(); 134 void osForceDetachFromAvatar();
194 135
195 /// <summary>
196 /// Returns a strided list of the specified attachment points and the number of attachments on those points.
197 /// </summary>
198 /// <param name="avatar">avatar UUID</param>
199 /// <param name="attachmentPoints">list of ATTACH_* constants</param>
200 /// <returns></returns>
201 LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints);
202
203 /// <summary>
204 /// Sends a specified message to the specified avatar's attachments on
205 /// the specified attachment points.
206 /// </summary>
207 /// <remarks>
208 /// Behaves as osMessageObject(), without the sending script needing to know the attachment keys in advance.
209 /// </remarks>
210 /// <param name="avatar">avatar UUID</param>
211 /// <param name="message">message string</param>
212 /// <param name="attachmentPoints">list of ATTACH_* constants, or -1 for all attachments. If -1 is specified and OS_ATTACH_MSG_INVERT_POINTS is present in flags, no action is taken.</param>
213 /// <param name="flags">flags further constraining the attachments to deliver the message to.</param>
214 void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int flags);
215
216 #endregion
217
218 //texture draw functions 136 //texture draw functions
219 string osMovePen(string drawList, int x, int y); 137 string osMovePen(string drawList, int x, int y);
220 string osDrawLine(string drawList, int startX, int startY, int endX, int endY); 138 string osDrawLine(string drawList, int startX, int startY, int endX, int endY);
@@ -340,7 +258,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
340 int osGetSimulatorMemory(); 258 int osGetSimulatorMemory();
341 void osKickAvatar(string FirstName,string SurName,string alert); 259 void osKickAvatar(string FirstName,string SurName,string alert);
342 void osSetSpeed(string UUID, LSL_Float SpeedModifier); 260 void osSetSpeed(string UUID, LSL_Float SpeedModifier);
343 LSL_Float osGetHealth(string avatar);
344 void osCauseHealing(string avatar, double healing); 261 void osCauseHealing(string avatar, double healing);
345 void osCauseDamage(string avatar, double damage); 262 void osCauseDamage(string avatar, double damage);
346 LSL_List osGetPrimitiveParams(LSL_Key prim, LSL_List rules); 263 LSL_List osGetPrimitiveParams(LSL_Key prim, LSL_List rules);
@@ -388,59 +305,5 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
388 /// </summary> 305 /// </summary>
389 /// <returns>Rezzing object key or NULL_KEY if rezzed by agent or otherwise unknown.</returns> 306 /// <returns>Rezzing object key or NULL_KEY if rezzed by agent or otherwise unknown.</returns>
390 LSL_Key osGetRezzingObject(); 307 LSL_Key osGetRezzingObject();
391
392 /// <summary>
393 /// Sets the response type for an HTTP request/response
394 /// </summary>
395 /// <returns></returns>
396 void osSetContentType(LSL_Key id, string type);
397
398 /// <summary>
399 /// Attempts to drop an attachment to the ground
400 /// </summary>
401 void osDropAttachment();
402
403 /// <summary>
404 /// Attempts to drop an attachment to the ground while bypassing the script permissions
405 /// </summary>
406 void osForceDropAttachment();
407
408 /// <summary>
409 /// Attempts to drop an attachment at the specified coordinates.
410 /// </summary>
411 /// <param name="pos"></param>
412 /// <param name="rot"></param>
413 void osDropAttachmentAt(vector pos, rotation rot);
414
415 /// <summary>
416 /// Attempts to drop an attachment at the specified coordinates while bypassing the script permissions
417 /// </summary>
418 /// <param name="pos"></param>
419 /// <param name="rot"></param>
420 void osForceDropAttachmentAt(vector pos, rotation rot);
421
422 /// <summary>
423 /// Identical to llListen except for a bitfield which indicates which
424 /// string parameters should be parsed as regex patterns.
425 /// </summary>
426 /// <param name="channelID"></param>
427 /// <param name="name"></param>
428 /// <param name="ID"></param>
429 /// <param name="msg"></param>
430 /// <param name="regexBitfield">
431 /// OS_LISTEN_REGEX_NAME
432 /// OS_LISTEN_REGEX_MESSAGE
433 /// </param>
434 /// <returns></returns>
435 LSL_Integer osListenRegex(int channelID, string name, string ID,
436 string msg, int regexBitfield);
437
438 /// <summary>
439 /// Wraps to bool Regex.IsMatch(string input, string pattern)
440 /// </summary>
441 /// <param name="input">string to test for match</param>
442 /// <param name="regex">string to use as pattern</param>
443 /// <returns>boolean</returns>
444 LSL_Integer osRegexIsMatch(string input, string pattern);
445 } 308 }
446} 309}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
index 0dd5a57..f989cc6 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
@@ -237,58 +237,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
237 public const int ATTACH_HUD_BOTTOM = 37; 237 public const int ATTACH_HUD_BOTTOM = 37;
238 public const int ATTACH_HUD_BOTTOM_RIGHT = 38; 238 public const int ATTACH_HUD_BOTTOM_RIGHT = 38;
239 239
240 #region osMessageAttachments constants
241
242 /// <summary>
243 /// Instructs osMessageAttachements to send the message to attachments
244 /// on every point.
245 /// </summary>
246 /// <remarks>
247 /// One might expect this to be named OS_ATTACH_ALL, but then one might
248 /// also expect functions designed to attach or detach or get
249 /// attachments to work with it too. Attaching a no-copy item to
250 /// many attachments could be dangerous.
251 /// when combined with OS_ATTACH_MSG_INVERT_POINTS, will prevent the
252 /// message from being sent.
253 /// if combined with OS_ATTACH_MSG_OBJECT_CREATOR or
254 /// OS_ATTACH_MSG_SCRIPT_CREATOR, could result in no message being
255 /// sent- this is expected behaviour.
256 /// </remarks>
257 public const int OS_ATTACH_MSG_ALL = -65535;
258
259 /// <summary>
260 /// Instructs osMessageAttachements to invert how the attachment points
261 /// list should be treated (e.g. go from inclusive operation to
262 /// exclusive operation).
263 /// </summary>
264 /// <remarks>
265 /// This might be used if you want to deliver a message to one set of
266 /// attachments and a different message to everything else. With
267 /// this flag, you only need to build one explicit list for both calls.
268 /// </remarks>
269 public const int OS_ATTACH_MSG_INVERT_POINTS = 1;
270
271 /// <summary>
272 /// Instructs osMessageAttachments to only send the message to
273 /// attachments with a CreatorID that matches the host object CreatorID
274 /// </summary>
275 /// <remarks>
276 /// This would be used if distributed in an object vendor/updater server.
277 /// </remarks>
278 public const int OS_ATTACH_MSG_OBJECT_CREATOR = 2;
279
280 /// <summary>
281 /// Instructs osMessageAttachments to only send the message to
282 /// attachments with a CreatorID that matches the sending script CreatorID
283 /// </summary>
284 /// <remarks>
285 /// This might be used if the script is distributed independently of a
286 /// containing object.
287 /// </remarks>
288 public const int OS_ATTACH_MSG_SCRIPT_CREATOR = 4;
289
290 #endregion
291
292 public const int LAND_LEVEL = 0; 240 public const int LAND_LEVEL = 0;
293 public const int LAND_RAISE = 1; 241 public const int LAND_RAISE = 1;
294 public const int LAND_LOWER = 2; 242 public const int LAND_LOWER = 2;
@@ -381,7 +329,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
381 public const int PRIM_OMEGA = 32; 329 public const int PRIM_OMEGA = 32;
382 public const int PRIM_POS_LOCAL = 33; 330 public const int PRIM_POS_LOCAL = 33;
383 public const int PRIM_LINK_TARGET = 34; 331 public const int PRIM_LINK_TARGET = 34;
384 public const int PRIM_SLICE = 35;
385 public const int PRIM_TEXGEN_DEFAULT = 0; 332 public const int PRIM_TEXGEN_DEFAULT = 0;
386 public const int PRIM_TEXGEN_PLANAR = 1; 333 public const int PRIM_TEXGEN_PLANAR = 1;
387 334
@@ -613,7 +560,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
613 public const int CLICK_ACTION_OPEN = 4; 560 public const int CLICK_ACTION_OPEN = 4;
614 public const int CLICK_ACTION_PLAY = 5; 561 public const int CLICK_ACTION_PLAY = 5;
615 public const int CLICK_ACTION_OPEN_MEDIA = 6; 562 public const int CLICK_ACTION_OPEN_MEDIA = 6;
616 public const int CLICK_ACTION_ZOOM = 7;
617 563
618 // constants for the llDetectedTouch* functions 564 // constants for the llDetectedTouch* functions
619 public const int TOUCH_INVALID_FACE = -1; 565 public const int TOUCH_INVALID_FACE = -1;
@@ -741,15 +687,5 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
741 public const int KFM_CMD_PLAY = 0; 687 public const int KFM_CMD_PLAY = 0;
742 public const int KFM_CMD_STOP = 1; 688 public const int KFM_CMD_STOP = 1;
743 public const int KFM_CMD_PAUSE = 2; 689 public const int KFM_CMD_PAUSE = 2;
744
745 /// <summary>
746 /// process name parameter as regex
747 /// </summary>
748 public const int OS_LISTEN_REGEX_NAME = 0x1;
749
750 /// <summary>
751 /// process message parameter as regex
752 /// </summary>
753 public const int OS_LISTEN_REGEX_MESSAGE = 0x2;
754 } 690 }
755} 691}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
index afa9ae0..94405d2 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
@@ -289,7 +289,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
289 m_OSSL_Functions.osAvatarStopAnimation(avatar, animation); 289 m_OSSL_Functions.osAvatarStopAnimation(avatar, animation);
290 } 290 }
291 291
292 #region Attachment commands 292 // Avatar functions
293 293
294 public void osForceAttachToAvatar(int attachmentPoint) 294 public void osForceAttachToAvatar(int attachmentPoint)
295 { 295 {
@@ -311,18 +311,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
311 m_OSSL_Functions.osForceDetachFromAvatar(); 311 m_OSSL_Functions.osForceDetachFromAvatar();
312 } 312 }
313 313
314 public LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints)
315 {
316 return m_OSSL_Functions.osGetNumberOfAttachments(avatar, attachmentPoints);
317 }
318
319 public void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int flags)
320 {
321 m_OSSL_Functions.osMessageAttachments(avatar, message, attachmentPoints, flags);
322 }
323
324 #endregion
325
326 // Texture Draw functions 314 // Texture Draw functions
327 315
328 public string osMovePen(string drawList, int x, int y) 316 public string osMovePen(string drawList, int x, int y)
@@ -877,12 +865,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
877 { 865 {
878 m_OSSL_Functions.osSetSpeed(UUID, SpeedModifier); 866 m_OSSL_Functions.osSetSpeed(UUID, SpeedModifier);
879 } 867 }
880 868
881 public LSL_Float osGetHealth(string avatar)
882 {
883 return m_OSSL_Functions.osGetHealth(avatar);
884 }
885
886 public void osCauseDamage(string avatar, double damage) 869 public void osCauseDamage(string avatar, double damage)
887 { 870 {
888 m_OSSL_Functions.osCauseDamage(avatar, damage); 871 m_OSSL_Functions.osCauseDamage(avatar, damage);
@@ -967,40 +950,5 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
967 { 950 {
968 return m_OSSL_Functions.osGetRezzingObject(); 951 return m_OSSL_Functions.osGetRezzingObject();
969 } 952 }
970
971 public void osSetContentType(LSL_Key id, string type)
972 {
973 m_OSSL_Functions.osSetContentType(id,type);
974 }
975
976 public void osDropAttachment()
977 {
978 m_OSSL_Functions.osDropAttachment();
979 }
980
981 public void osForceDropAttachment()
982 {
983 m_OSSL_Functions.osForceDropAttachment();
984 }
985
986 public void osDropAttachmentAt(vector pos, rotation rot)
987 {
988 m_OSSL_Functions.osDropAttachmentAt(pos, rot);
989 }
990
991 public void osForceDropAttachmentAt(vector pos, rotation rot)
992 {
993 m_OSSL_Functions.osForceDropAttachmentAt(pos, rot);
994 }
995
996 public LSL_Integer osListenRegex(int channelID, string name, string ID, string msg, int regexBitfield)
997 {
998 return m_OSSL_Functions.osListenRegex(channelID, name, ID, msg, regexBitfield);
999 }
1000
1001 public LSL_Integer osRegexIsMatch(string input, string pattern)
1002 {
1003 return m_OSSL_Functions.osRegexIsMatch(input, pattern);
1004 }
1005 } 953 }
1006} 954}
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
index 03be2ab..17a0d69 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
@@ -546,8 +546,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
546 "OpenSim.Region.ScriptEngine.Shared.dll")); 546 "OpenSim.Region.ScriptEngine.Shared.dll"));
547 parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, 547 parameters.ReferencedAssemblies.Add(Path.Combine(rootPath,
548 "OpenSim.Region.ScriptEngine.Shared.Api.Runtime.dll")); 548 "OpenSim.Region.ScriptEngine.Shared.Api.Runtime.dll"));
549 parameters.ReferencedAssemblies.Add(Path.Combine(rootPath,
550 "OpenMetaverseTypes.dll"));
551 549
552 if (lang == enumCompileType.yp) 550 if (lang == enumCompileType.yp)
553 { 551 {
diff --git a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
index 22804f5..9e5fb24 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
@@ -164,11 +164,11 @@ namespace OpenSim.Region.ScriptEngine.Shared
164 else 164 else
165 { 165 {
166 // Set the values from the touch data provided by the client 166 // Set the values from the touch data provided by the client
167 touchST = new LSL_Types.Vector3(value.STCoord); 167 touchST = new LSL_Types.Vector3(value.STCoord.X, value.STCoord.Y, value.STCoord.Z);
168 touchUV = new LSL_Types.Vector3(value.UVCoord); 168 touchUV = new LSL_Types.Vector3(value.UVCoord.X, value.UVCoord.Y, value.UVCoord.Z);
169 touchNormal = new LSL_Types.Vector3(value.Normal); 169 touchNormal = new LSL_Types.Vector3(value.Normal.X, value.Normal.Y, value.Normal.Z);
170 touchBinormal = new LSL_Types.Vector3(value.Binormal); 170 touchBinormal = new LSL_Types.Vector3(value.Binormal.X, value.Binormal.Y, value.Binormal.Z);
171 touchPos = new LSL_Types.Vector3(value.Position); 171 touchPos = new LSL_Types.Vector3(value.Position.X, value.Position.Y, value.Position.Z);
172 touchFace = value.FaceIndex; 172 touchFace = value.FaceIndex;
173 } 173 }
174 } 174 }
@@ -189,13 +189,19 @@ namespace OpenSim.Region.ScriptEngine.Shared
189 Country = account.UserCountry; 189 Country = account.UserCountry;
190 190
191 Owner = Key; 191 Owner = Key;
192 Position = new LSL_Types.Vector3(presence.AbsolutePosition); 192 Position = new LSL_Types.Vector3(
193 presence.AbsolutePosition.X,
194 presence.AbsolutePosition.Y,
195 presence.AbsolutePosition.Z);
193 Rotation = new LSL_Types.Quaternion( 196 Rotation = new LSL_Types.Quaternion(
194 presence.Rotation.X, 197 presence.Rotation.X,
195 presence.Rotation.Y, 198 presence.Rotation.Y,
196 presence.Rotation.Z, 199 presence.Rotation.Z,
197 presence.Rotation.W); 200 presence.Rotation.W);
198 Velocity = new LSL_Types.Vector3(presence.Velocity); 201 Velocity = new LSL_Types.Vector3(
202 presence.Velocity.X,
203 presence.Velocity.Y,
204 presence.Velocity.Z);
199 205
200 Type = 0x01; // Avatar 206 Type = 0x01; // Avatar
201 if (presence.PresenceType == PresenceType.Npc) 207 if (presence.PresenceType == PresenceType.Npc)
@@ -248,12 +254,16 @@ namespace OpenSim.Region.ScriptEngine.Shared
248 } 254 }
249 } 255 }
250 256
251 Position = new LSL_Types.Vector3(part.AbsolutePosition); 257 Position = new LSL_Types.Vector3(part.AbsolutePosition.X,
258 part.AbsolutePosition.Y,
259 part.AbsolutePosition.Z);
252 260
253 Quaternion wr = part.ParentGroup.GroupRotation; 261 Quaternion wr = part.ParentGroup.GroupRotation;
254 Rotation = new LSL_Types.Quaternion(wr.X, wr.Y, wr.Z, wr.W); 262 Rotation = new LSL_Types.Quaternion(wr.X, wr.Y, wr.Z, wr.W);
255 263
256 Velocity = new LSL_Types.Vector3(part.Velocity); 264 Velocity = new LSL_Types.Vector3(part.Velocity.X,
265 part.Velocity.Y,
266 part.Velocity.Z);
257 } 267 }
258 } 268 }
259 269
diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
index c9c4753..8adf4c5 100644
--- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
@@ -31,11 +31,6 @@ using System.Globalization;
31using System.Text.RegularExpressions; 31using System.Text.RegularExpressions;
32using OpenSim.Framework; 32using OpenSim.Framework;
33 33
34using OpenMetaverse;
35using OMV_Vector3 = OpenMetaverse.Vector3;
36using OMV_Vector3d = OpenMetaverse.Vector3d;
37using OMV_Quaternion = OpenMetaverse.Quaternion;
38
39namespace OpenSim.Region.ScriptEngine.Shared 34namespace OpenSim.Region.ScriptEngine.Shared
40{ 35{
41 [Serializable] 36 [Serializable]
@@ -59,20 +54,6 @@ namespace OpenSim.Region.ScriptEngine.Shared
59 z = (float)vector.z; 54 z = (float)vector.z;
60 } 55 }
61 56
62 public Vector3(OMV_Vector3 vector)
63 {
64 x = vector.X;
65 y = vector.Y;
66 z = vector.Z;
67 }
68
69 public Vector3(OMV_Vector3d vector)
70 {
71 x = vector.X;
72 y = vector.Y;
73 z = vector.Z;
74 }
75
76 public Vector3(double X, double Y, double Z) 57 public Vector3(double X, double Y, double Z)
77 { 58 {
78 x = X; 59 x = X;
@@ -128,26 +109,6 @@ namespace OpenSim.Region.ScriptEngine.Shared
128 return new list(new object[] { vec }); 109 return new list(new object[] { vec });
129 } 110 }
130 111
131 public static implicit operator OMV_Vector3(Vector3 vec)
132 {
133 return new OMV_Vector3((float)vec.x, (float)vec.y, (float)vec.z);
134 }
135
136 public static implicit operator Vector3(OMV_Vector3 vec)
137 {
138 return new Vector3(vec);
139 }
140
141 public static implicit operator OMV_Vector3d(Vector3 vec)
142 {
143 return new OMV_Vector3d(vec.x, vec.y, vec.z);
144 }
145
146 public static implicit operator Vector3(OMV_Vector3d vec)
147 {
148 return new Vector3(vec);
149 }
150
151 public static bool operator ==(Vector3 lhs, Vector3 rhs) 112 public static bool operator ==(Vector3 lhs, Vector3 rhs)
152 { 113 {
153 return (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z); 114 return (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z);
@@ -361,14 +322,6 @@ namespace OpenSim.Region.ScriptEngine.Shared
361 s = 1; 322 s = 1;
362 } 323 }
363 324
364 public Quaternion(OMV_Quaternion rot)
365 {
366 x = rot.X;
367 y = rot.Y;
368 z = rot.Z;
369 s = rot.W;
370 }
371
372 #endregion 325 #endregion
373 326
374 #region Overriders 327 #region Overriders
@@ -415,21 +368,6 @@ namespace OpenSim.Region.ScriptEngine.Shared
415 return new list(new object[] { r }); 368 return new list(new object[] { r });
416 } 369 }
417 370
418 public static implicit operator OMV_Quaternion(Quaternion rot)
419 {
420 // LSL quaternions can normalize to 0, normal Quaternions can't.
421 if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0)
422 rot.z = 1; // ZERO_ROTATION = 0,0,0,1
423 OMV_Quaternion omvrot = new OMV_Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s);
424 omvrot.Normalize();
425 return omvrot;
426 }
427
428 public static implicit operator Quaternion(OMV_Quaternion rot)
429 {
430 return new Quaternion(rot);
431 }
432
433 public static bool operator ==(Quaternion lhs, Quaternion rhs) 371 public static bool operator ==(Quaternion lhs, Quaternion rhs)
434 { 372 {
435 // Return true if the fields match: 373 // Return true if the fields match:
@@ -624,23 +562,12 @@ namespace OpenSim.Region.ScriptEngine.Shared
624 else if (m_data[itemIndex] is LSL_Types.LSLString) 562 else if (m_data[itemIndex] is LSL_Types.LSLString)
625 return new LSLInteger(m_data[itemIndex].ToString()); 563 return new LSLInteger(m_data[itemIndex].ToString());
626 else 564 else
627 throw new InvalidCastException(string.Format( 565 throw new InvalidCastException();
628 "{0} expected but {1} given",
629 typeof(LSL_Types.LSLInteger).Name,
630 m_data[itemIndex] != null ?
631 m_data[itemIndex].GetType().Name : "null"));
632 } 566 }
633 567
634 public LSL_Types.Vector3 GetVector3Item(int itemIndex) 568 public LSL_Types.Vector3 GetVector3Item(int itemIndex)
635 { 569 {
636 if(m_data[itemIndex] is LSL_Types.Vector3) 570 return (LSL_Types.Vector3)m_data[itemIndex];
637 return (LSL_Types.Vector3)m_data[itemIndex];
638 else
639 throw new InvalidCastException(string.Format(
640 "{0} expected but {1} given",
641 typeof(LSL_Types.Vector3).Name,
642 m_data[itemIndex] != null ?
643 m_data[itemIndex].GetType().Name : "null"));
644 } 571 }
645 572
646 public LSL_Types.Quaternion GetQuaternionItem(int itemIndex) 573 public LSL_Types.Quaternion GetQuaternionItem(int itemIndex)
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs
deleted file mode 100644
index dd23be8..0000000
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs
+++ /dev/null
@@ -1,134 +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 NUnit.Framework;
31using OpenSim.Framework;
32using OpenSim.Tests.Common;
33using OpenSim.Region.ScriptEngine.Shared;
34using OpenSim.Region.Framework.Scenes;
35using Nini.Config;
36using OpenSim.Region.ScriptEngine.Shared.Api;
37using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
38using OpenMetaverse;
39using OpenSim.Tests.Common.Mock;
40
41using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
42using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
43using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
44using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
45
46namespace OpenSim.Region.ScriptEngine.Shared.Tests
47{
48 [TestFixture]
49 public class LSL_ApiListTests
50 {
51 private LSL_Api m_lslApi;
52
53 [SetUp]
54 public void SetUp()
55 {
56 IConfigSource initConfigSource = new IniConfigSource();
57 IConfig config = initConfigSource.AddConfig("XEngine");
58 config.Set("Enabled", "true");
59
60 Scene scene = new SceneHelpers().SetupScene();
61 SceneObjectPart part = SceneHelpers.AddSceneObject(scene).RootPart;
62
63 XEngine.XEngine engine = new XEngine.XEngine();
64 engine.Initialise(initConfigSource);
65 engine.AddRegion(scene);
66
67 m_lslApi = new LSL_Api();
68 m_lslApi.Initialize(engine, part, null);
69 }
70
71 [Test]
72 public void TestllListFindList()
73 {
74 TestHelpers.InMethod();
75
76 LSL_List src = new LSL_List(new LSL_Integer(1), new LSL_Integer(2), new LSL_Integer(3));
77
78 {
79 // Test for a single item that should be found
80 int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(4)));
81 Assert.That(result, Is.EqualTo(-1));
82 }
83
84 {
85 // Test for a single item that should be found
86 int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(2)));
87 Assert.That(result, Is.EqualTo(1));
88 }
89
90 {
91 // Test for a constant that should be found
92 int result = m_lslApi.llListFindList(src, new LSL_List(ScriptBaseClass.AGENT));
93 Assert.That(result, Is.EqualTo(0));
94 }
95
96 {
97 // Test for a list that should be found
98 int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(2), new LSL_Integer(3)));
99 Assert.That(result, Is.EqualTo(1));
100 }
101
102 {
103 // Test for a single item not in the list
104 int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(4)));
105 Assert.That(result, Is.EqualTo(-1));
106 }
107
108 {
109 // Test for something that should not be cast
110 int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_String("4")));
111 Assert.That(result, Is.EqualTo(-1));
112 }
113
114 {
115 // Test for a list not in the list
116 int result
117 = m_lslApi.llListFindList(
118 src, new LSL_List(new LSL_Integer(2), new LSL_Integer(3), new LSL_Integer(4)));
119 Assert.That(result, Is.EqualTo(-1));
120 }
121
122 {
123 LSL_List srcWithConstants
124 = new LSL_List(new LSL_Integer(3), ScriptBaseClass.AGENT, ScriptBaseClass.OS_NPC_LAND_AT_TARGET);
125
126 // Test for constants that appears in the source list that should be found
127 int result
128 = m_lslApi.llListFindList(srcWithConstants, new LSL_List(new LSL_Integer(1), new LSL_Integer(2)));
129
130 Assert.That(result, Is.EqualTo(1));
131 }
132 }
133 }
134 } \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs
index c401794..c8718d9 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs
@@ -75,6 +75,76 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
75 m_engine.AddRegion(m_scene); 75 m_engine.AddRegion(m_scene);
76 } 76 }
77 77
78 /// <summary>
79 /// Test creation of an NPC where the appearance data comes from a notecard
80 /// </summary>
81 [Test]
82 public void TestOsNpcCreateUsingAppearanceFromNotecard()
83 {
84 TestHelpers.InMethod();
85// log4net.Config.XmlConfigurator.Configure();
86
87 // Store an avatar with a different height from default in a notecard.
88 UUID userId = TestHelpers.ParseTail(0x1);
89 float newHeight = 1.9f;
90
91 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId);
92 sp.Appearance.AvatarHeight = newHeight;
93 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10);
94 SceneObjectPart part = so.RootPart;
95 m_scene.AddSceneObject(so);
96
97 OSSL_Api osslApi = new OSSL_Api();
98 osslApi.Initialize(m_engine, part, null);
99
100 string notecardName = "appearanceNc";
101 osslApi.osOwnerSaveAppearance(notecardName);
102
103 // Try creating a bot using the appearance in the notecard.
104 string npcRaw = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), notecardName);
105 Assert.That(npcRaw, Is.Not.Null);
106
107 UUID npcId = new UUID(npcRaw);
108 ScenePresence npc = m_scene.GetScenePresence(npcId);
109 Assert.That(npc, Is.Not.Null);
110 Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(newHeight));
111 }
112
113 /// <summary>
114 /// Test creation of an NPC where the appearance data comes from an avatar already in the region.
115 /// </summary>
116 [Test]
117 public void TestOsNpcCreateUsingAppearanceFromAvatar()
118 {
119 TestHelpers.InMethod();
120// TestHelpers.EnableLogging();
121
122 // Store an avatar with a different height from default in a notecard.
123 UUID userId = TestHelpers.ParseTail(0x1);
124 float newHeight = 1.9f;
125
126 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId);
127 sp.Appearance.AvatarHeight = newHeight;
128 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10);
129 SceneObjectPart part = so.RootPart;
130 m_scene.AddSceneObject(so);
131
132 OSSL_Api osslApi = new OSSL_Api();
133 osslApi.Initialize(m_engine, part, null);
134
135 string notecardName = "appearanceNc";
136 osslApi.osOwnerSaveAppearance(notecardName);
137
138 // Try creating a bot using the existing avatar's appearance
139 string npcRaw = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), sp.UUID.ToString());
140 Assert.That(npcRaw, Is.Not.Null);
141
142 UUID npcId = new UUID(npcRaw);
143 ScenePresence npc = m_scene.GetScenePresence(npcId);
144 Assert.That(npc, Is.Not.Null);
145 Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(newHeight));
146 }
147
78 [Test] 148 [Test]
79 public void TestOsOwnerSaveAppearance() 149 public void TestOsOwnerSaveAppearance()
80 { 150 {
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs
index b49bcc2..25679a6 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs
@@ -36,7 +36,6 @@ using OpenMetaverse;
36using OpenMetaverse.Assets; 36using OpenMetaverse.Assets;
37using OpenMetaverse.StructuredData; 37using OpenMetaverse.StructuredData;
38using OpenSim.Framework; 38using OpenSim.Framework;
39using OpenSim.Region.CoreModules.Avatar.Attachments;
40using OpenSim.Region.CoreModules.Avatar.AvatarFactory; 39using OpenSim.Region.CoreModules.Avatar.AvatarFactory;
41using OpenSim.Region.OptionalModules.World.NPC; 40using OpenSim.Region.OptionalModules.World.NPC;
42using OpenSim.Region.Framework.Scenes; 41using OpenSim.Region.Framework.Scenes;
@@ -72,8 +71,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
72 config.Set("Enabled", "true"); 71 config.Set("Enabled", "true");
73 72
74 m_scene = new SceneHelpers().SetupScene(); 73 m_scene = new SceneHelpers().SetupScene();
75 SceneHelpers.SetupSceneModules( 74 SceneHelpers.SetupSceneModules(m_scene, initConfigSource, new AvatarFactoryModule(), new NPCModule());
76 m_scene, initConfigSource, new AvatarFactoryModule(), new AttachmentsModule(), new NPCModule());
77 75
78 m_engine = new XEngine.XEngine(); 76 m_engine = new XEngine.XEngine();
79 m_engine.Initialise(initConfigSource); 77 m_engine.Initialise(initConfigSource);
@@ -81,191 +79,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
81 } 79 }
82 80
83 /// <summary> 81 /// <summary>
84 /// Test creation of an NPC where the appearance data comes from a notecard
85 /// </summary>
86 [Test]
87 public void TestOsNpcCreateUsingAppearanceFromNotecard()
88 {
89 TestHelpers.InMethod();
90
91 // Store an avatar with a different height from default in a notecard.
92 UUID userId = TestHelpers.ParseTail(0x1);
93 float newHeight = 1.9f;
94
95 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId);
96 sp.Appearance.AvatarHeight = newHeight;
97 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10);
98 SceneObjectPart part = so.RootPart;
99 m_scene.AddSceneObject(so);
100
101 OSSL_Api osslApi = new OSSL_Api();
102 osslApi.Initialize(m_engine, part, null);
103
104 string notecardName = "appearanceNc";
105 osslApi.osOwnerSaveAppearance(notecardName);
106
107 // Try creating a bot using the appearance in the notecard.
108 string npcRaw = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), notecardName);
109 Assert.That(npcRaw, Is.Not.Null);
110
111 UUID npcId = new UUID(npcRaw);
112 ScenePresence npc = m_scene.GetScenePresence(npcId);
113 Assert.That(npc, Is.Not.Null);
114 Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(newHeight));
115 }
116
117 [Test]
118 public void TestOsNpcCreateNotExistingNotecard()
119 {
120 TestHelpers.InMethod();
121
122 UUID userId = TestHelpers.ParseTail(0x1);
123
124 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10);
125 m_scene.AddSceneObject(so);
126
127 OSSL_Api osslApi = new OSSL_Api();
128 osslApi.Initialize(m_engine, so.RootPart, null);
129
130 string npcRaw;
131 bool gotExpectedException = false;
132 try
133 {
134 npcRaw
135 = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), "not existing notecard name");
136 }
137 catch (ScriptException)
138 {
139 gotExpectedException = true;
140 }
141
142 Assert.That(gotExpectedException, Is.True);
143 }
144
145 /// <summary>
146 /// Test creation of an NPC where the appearance data comes from an avatar already in the region.
147 /// </summary>
148 [Test]
149 public void TestOsNpcCreateUsingAppearanceFromAvatar()
150 {
151 TestHelpers.InMethod();
152// TestHelpers.EnableLogging();
153
154 // Store an avatar with a different height from default in a notecard.
155 UUID userId = TestHelpers.ParseTail(0x1);
156 float newHeight = 1.9f;
157
158 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId);
159 sp.Appearance.AvatarHeight = newHeight;
160 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10);
161 SceneObjectPart part = so.RootPart;
162 m_scene.AddSceneObject(so);
163
164 OSSL_Api osslApi = new OSSL_Api();
165 osslApi.Initialize(m_engine, part, null);
166
167 string notecardName = "appearanceNc";
168 osslApi.osOwnerSaveAppearance(notecardName);
169
170 // Try creating a bot using the existing avatar's appearance
171 string npcRaw = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), sp.UUID.ToString());
172 Assert.That(npcRaw, Is.Not.Null);
173
174 UUID npcId = new UUID(npcRaw);
175 ScenePresence npc = m_scene.GetScenePresence(npcId);
176 Assert.That(npc, Is.Not.Null);
177 Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(newHeight));
178 }
179
180 [Test]
181 public void TestOsNpcLoadAppearance()
182 {
183 TestHelpers.InMethod();
184
185 // Store an avatar with a different height from default in a notecard.
186 UUID userId = TestHelpers.ParseTail(0x1);
187 float firstHeight = 1.9f;
188 float secondHeight = 2.1f;
189 string firstAppearanceNcName = "appearanceNc1";
190 string secondAppearanceNcName = "appearanceNc2";
191
192 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId);
193 sp.Appearance.AvatarHeight = firstHeight;
194 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10);
195 SceneObjectPart part = so.RootPart;
196 m_scene.AddSceneObject(so);
197
198 OSSL_Api osslApi = new OSSL_Api();
199 osslApi.Initialize(m_engine, part, null);
200
201 osslApi.osOwnerSaveAppearance(firstAppearanceNcName);
202
203 string npcRaw
204 = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), firstAppearanceNcName);
205
206 // Create a second appearance notecard with a different height
207 sp.Appearance.AvatarHeight = secondHeight;
208 osslApi.osOwnerSaveAppearance(secondAppearanceNcName);
209
210 osslApi.osNpcLoadAppearance(npcRaw, secondAppearanceNcName);
211
212 UUID npcId = new UUID(npcRaw);
213 ScenePresence npc = m_scene.GetScenePresence(npcId);
214 Assert.That(npc, Is.Not.Null);
215 Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(secondHeight));
216 }
217
218 [Test]
219 public void TestOsNpcLoadAppearanceNotExistingNotecard()
220 {
221 TestHelpers.InMethod();
222
223 // Store an avatar with a different height from default in a notecard.
224 UUID userId = TestHelpers.ParseTail(0x1);
225 float firstHeight = 1.9f;
226 float secondHeight = 2.1f;
227 string firstAppearanceNcName = "appearanceNc1";
228 string secondAppearanceNcName = "appearanceNc2";
229
230 ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId);
231 sp.Appearance.AvatarHeight = firstHeight;
232 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10);
233 SceneObjectPart part = so.RootPart;
234 m_scene.AddSceneObject(so);
235
236 OSSL_Api osslApi = new OSSL_Api();
237 osslApi.Initialize(m_engine, part, null);
238
239 osslApi.osOwnerSaveAppearance(firstAppearanceNcName);
240
241 string npcRaw
242 = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), firstAppearanceNcName);
243
244 bool gotExpectedException = false;
245 try
246 {
247 osslApi.osNpcLoadAppearance(npcRaw, secondAppearanceNcName);
248 }
249 catch (ScriptException)
250 {
251 gotExpectedException = true;
252 }
253
254 Assert.That(gotExpectedException, Is.True);
255
256 UUID npcId = new UUID(npcRaw);
257 ScenePresence npc = m_scene.GetScenePresence(npcId);
258 Assert.That(npc, Is.Not.Null);
259 Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(firstHeight));
260 }
261
262 /// <summary>
263 /// Test removal of an owned NPC. 82 /// Test removal of an owned NPC.
264 /// </summary> 83 /// </summary>
265 [Test] 84 [Test]
266 public void TestOsNpcRemoveOwned() 85 public void TestOsNpcRemoveOwned()
267 { 86 {
268 TestHelpers.InMethod(); 87 TestHelpers.InMethod();
88// log4net.Config.XmlConfigurator.Configure();
269 89
270 // Store an avatar with a different height from default in a notecard. 90 // Store an avatar with a different height from default in a notecard.
271 UUID userId = TestHelpers.ParseTail(0x1); 91 UUID userId = TestHelpers.ParseTail(0x1);
diff --git a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs
index 9405075..5c4174e 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs
@@ -96,12 +96,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
96 if (part == null) 96 if (part == null)
97 return; 97 return;
98 98
99 if ((part.ScriptEvents & scriptEvents.money) == 0)
100 part = part.ParentGroup.RootPart;
101
102 m_log.Debug("Paid: " + objectID + " from " + agentID + ", amount " + amount); 99 m_log.Debug("Paid: " + objectID + " from " + agentID + ", amount " + amount);
103 100
104// part = part.ParentGroup.RootPart; 101 part = part.ParentGroup.RootPart;
105 money(part.LocalId, agentID, amount); 102 money(part.LocalId, agentID, amount);
106 } 103 }
107 104
@@ -155,7 +152,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
155 det[0] = new DetectParams(); 152 det[0] = new DetectParams();
156 det[0].Key = remoteClient.AgentId; 153 det[0].Key = remoteClient.AgentId;
157 det[0].Populate(myScriptEngine.World); 154 det[0].Populate(myScriptEngine.World);
158 det[0].OffsetPos = offsetPos; 155 det[0].OffsetPos = new LSL_Types.Vector3(offsetPos.X,
156 offsetPos.Y,
157 offsetPos.Z);
159 158
160 if (originalID == 0) 159 if (originalID == 0)
161 { 160 {
@@ -299,7 +298,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
299 foreach (DetectedObject detobj in col.Colliders) 298 foreach (DetectedObject detobj in col.Colliders)
300 { 299 {
301 DetectParams d = new DetectParams(); 300 DetectParams d = new DetectParams();
302 d.Position = detobj.posVector; 301 d.Position = new LSL_Types.Vector3(detobj.posVector.X,
302 detobj.posVector.Y,
303 detobj.posVector.Z);
303 d.Populate(myScriptEngine.World); 304 d.Populate(myScriptEngine.World);
304 det.Add(d); 305 det.Add(d);
305 myScriptEngine.PostObjectEvent(localID, new EventParams( 306 myScriptEngine.PostObjectEvent(localID, new EventParams(
@@ -317,7 +318,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
317 foreach (DetectedObject detobj in col.Colliders) 318 foreach (DetectedObject detobj in col.Colliders)
318 { 319 {
319 DetectParams d = new DetectParams(); 320 DetectParams d = new DetectParams();
320 d.Position = detobj.posVector; 321 d.Position = new LSL_Types.Vector3(detobj.posVector.X,
322 detobj.posVector.Y,
323 detobj.posVector.Z);
321 d.Populate(myScriptEngine.World); 324 d.Populate(myScriptEngine.World);
322 det.Add(d); 325 det.Add(d);
323 myScriptEngine.PostObjectEvent(localID, new EventParams( 326 myScriptEngine.PostObjectEvent(localID, new EventParams(
@@ -334,7 +337,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
334 foreach (DetectedObject detobj in col.Colliders) 337 foreach (DetectedObject detobj in col.Colliders)
335 { 338 {
336 DetectParams d = new DetectParams(); 339 DetectParams d = new DetectParams();
337 d.Position = detobj.posVector; 340 d.Position = new LSL_Types.Vector3(detobj.posVector.X,
341 detobj.posVector.Y,
342 detobj.posVector.Z);
338 d.Populate(myScriptEngine.World); 343 d.Populate(myScriptEngine.World);
339 det.Add(d); 344 det.Add(d);
340 myScriptEngine.PostObjectEvent(localID, new EventParams( 345 myScriptEngine.PostObjectEvent(localID, new EventParams(
@@ -376,8 +381,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
376 myScriptEngine.PostObjectEvent(localID, new EventParams( 381 myScriptEngine.PostObjectEvent(localID, new EventParams(
377 "at_target", new object[] { 382 "at_target", new object[] {
378 new LSL_Types.LSLInteger(handle), 383 new LSL_Types.LSLInteger(handle),
379 new LSL_Types.Vector3(targetpos), 384 new LSL_Types.Vector3(targetpos.X,targetpos.Y,targetpos.Z),
380 new LSL_Types.Vector3(atpos) }, 385 new LSL_Types.Vector3(atpos.X,atpos.Y,atpos.Z) },
381 new DetectParams[0])); 386 new DetectParams[0]));
382 } 387 }
383 388
@@ -394,8 +399,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
394 myScriptEngine.PostObjectEvent(localID, new EventParams( 399 myScriptEngine.PostObjectEvent(localID, new EventParams(
395 "at_rot_target", new object[] { 400 "at_rot_target", new object[] {
396 new LSL_Types.LSLInteger(handle), 401 new LSL_Types.LSLInteger(handle),
397 new LSL_Types.Quaternion(targetrot), 402 new LSL_Types.Quaternion(targetrot.X,targetrot.Y,targetrot.Z,targetrot.W),
398 new LSL_Types.Quaternion(atrot) }, 403 new LSL_Types.Quaternion(atrot.X,atrot.Y,atrot.Z,atrot.W) },
399 new DetectParams[0])); 404 new DetectParams[0]));
400 } 405 }
401 406
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs
index f331658..f247a0b 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs
@@ -90,7 +90,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine.Tests
90// log4net.Config.XmlConfigurator.Configure(); 90// log4net.Config.XmlConfigurator.Configure();
91 91
92 UUID userId = TestHelpers.ParseTail(0x1); 92 UUID userId = TestHelpers.ParseTail(0x1);
93// UUID objectId = TestHelpers.ParseTail(0x100); 93// UUID objectId = TestHelpers.ParseTail(0x2);
94// UUID itemId = TestHelpers.ParseTail(0x3); 94// UUID itemId = TestHelpers.ParseTail(0x3);
95 string itemName = "TestStartScript() Item"; 95 string itemName = "TestStartScript() Item";
96 96
@@ -105,18 +105,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine.Tests
105 105
106 m_scene.EventManager.OnChatFromWorld += OnChatFromWorld; 106 m_scene.EventManager.OnChatFromWorld += OnChatFromWorld;
107 107
108 SceneObjectPart partWhereRezzed = m_scene.RezNewScript(userId, itemTemplate); 108 m_scene.RezNewScript(userId, itemTemplate);
109 109
110 m_chatEvent.WaitOne(60000); 110 m_chatEvent.WaitOne(60000);
111 111
112 Assert.That(m_osChatMessageReceived, Is.Not.Null, "No chat message received in TestStartScript()"); 112 Assert.That(m_osChatMessageReceived, Is.Not.Null, "No chat message received in TestStartScript()");
113 Assert.That(m_osChatMessageReceived.Message, Is.EqualTo("Script running")); 113 Assert.That(m_osChatMessageReceived.Message, Is.EqualTo("Script running"));
114
115 bool running;
116 TaskInventoryItem scriptItem = partWhereRezzed.Inventory.GetInventoryItem(itemName);
117 Assert.That(
118 SceneObjectPartInventory.TryGetScriptInstanceRunning(m_scene, scriptItem, out running), Is.True);
119 Assert.That(running, Is.True);
120 } 114 }
121 115
122 private void OnChatFromWorld(object sender, OSChatMessage oscm) 116 private void OnChatFromWorld(object sender, OSChatMessage oscm)
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index 9f05666..f6cb7df 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -656,19 +656,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
656 if (m_Assemblies.ContainsKey(instance.AssetID)) 656 if (m_Assemblies.ContainsKey(instance.AssetID))
657 { 657 {
658 string assembly = m_Assemblies[instance.AssetID]; 658 string assembly = m_Assemblies[instance.AssetID];
659 659 instance.SaveState(assembly);
660 try
661 {
662 instance.SaveState(assembly);
663 }
664 catch (Exception e)
665 {
666 m_log.Error(
667 string.Format(
668 "[XEngine]: Failed final state save for script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ",
669 instance.PrimName, instance.ScriptName, instance.ItemID, instance.ObjectID, World.Name)
670 , e);
671 }
672 } 660 }
673 661
674 // Clear the event queue and abort the instance thread 662 // Clear the event queue and abort the instance thread
@@ -790,18 +778,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
790 assembly = m_Assemblies[i.AssetID]; 778 assembly = m_Assemblies[i.AssetID];
791 779
792 780
793 try 781 i.SaveState(assembly);
794 {
795 i.SaveState(assembly);
796 }
797 catch (Exception e)
798 {
799 m_log.Error(
800 string.Format(
801 "[XEngine]: Failed to save state of script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ",
802 i.PrimName, i.ScriptName, i.ItemID, i.ObjectID, World.Name)
803 , e);
804 }
805 } 782 }
806 783
807 instances.Clear(); 784 instances.Clear();
@@ -994,8 +971,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine
994 // This delay exists to stop mono problems where script compilation and startup would stop the sim 971 // This delay exists to stop mono problems where script compilation and startup would stop the sim
995 // working properly for the session. 972 // working properly for the session.
996 System.Threading.Thread.Sleep(m_StartDelay); 973 System.Threading.Thread.Sleep(m_StartDelay);
997
998 m_log.InfoFormat("[XEngine]: Performing initial script startup on {0}", m_Scene.Name);
999 } 974 }
1000 975
1001 object[] o; 976 object[] o;
@@ -1011,13 +986,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1011 if (m_InitialStartup) 986 if (m_InitialStartup)
1012 if (scriptsStarted % 50 == 0) 987 if (scriptsStarted % 50 == 0)
1013 m_log.InfoFormat( 988 m_log.InfoFormat(
1014 "[XEngine]: Started {0} scripts in {1}", scriptsStarted, m_Scene.Name); 989 "[XEngine]: Started {0} scripts in {1}", scriptsStarted, m_Scene.RegionInfo.RegionName);
1015 } 990 }
1016 } 991 }
1017 992
1018 if (m_InitialStartup) 993 if (m_InitialStartup)
1019 m_log.InfoFormat( 994 m_log.InfoFormat(
1020 "[XEngine]: Completed starting {0} scripts on {1}", scriptsStarted, m_Scene.Name); 995 "[XEngine]: Completed starting {0} scripts on {1}", scriptsStarted, m_Scene.RegionInfo.RegionName);
1021 996
1022 // NOTE: Despite having a lockless queue, this lock is required 997 // NOTE: Despite having a lockless queue, this lock is required
1023 // to make sure there is never no compile thread while there 998 // to make sure there is never no compile thread while there
@@ -1078,13 +1053,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1078 return false; 1053 return false;
1079 } 1054 }
1080 1055
1081 m_log.DebugFormat(
1082 "[XEngine] Loading script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}",
1083 part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID,
1084 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1085
1086 UUID assetID = item.AssetID; 1056 UUID assetID = item.AssetID;
1087 1057
1058 //m_log.DebugFormat("[XEngine] Compiling script {0} ({1} on object {2})",
1059 // item.Name, itemID.ToString(), part.ParentGroup.RootPart.Name);
1060
1088 ScenePresence presence = m_Scene.GetScenePresence(item.OwnerID); 1061 ScenePresence presence = m_Scene.GetScenePresence(item.OwnerID);
1089 1062
1090 string assembly = ""; 1063 string assembly = "";
@@ -1262,10 +1235,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1262 item.Name, startParam, postOnRez, 1235 item.Name, startParam, postOnRez,
1263 stateSource, m_MaxScriptQueue); 1236 stateSource, m_MaxScriptQueue);
1264 1237
1265// m_log.DebugFormat( 1238 m_log.DebugFormat(
1266// "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}", 1239 "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}",
1267// part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, 1240 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID,
1268// part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); 1241 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1269 1242
1270 if (presence != null) 1243 if (presence != null)
1271 { 1244 {
@@ -1581,9 +1554,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1581 else if (p[i] is string) 1554 else if (p[i] is string)
1582 lsl_p[i] = new LSL_Types.LSLString((string)p[i]); 1555 lsl_p[i] = new LSL_Types.LSLString((string)p[i]);
1583 else if (p[i] is Vector3) 1556 else if (p[i] is Vector3)
1584 lsl_p[i] = new LSL_Types.Vector3((Vector3)p[i]); 1557 lsl_p[i] = new LSL_Types.Vector3(((Vector3)p[i]).X, ((Vector3)p[i]).Y, ((Vector3)p[i]).Z);
1585 else if (p[i] is Quaternion) 1558 else if (p[i] is Quaternion)
1586 lsl_p[i] = new LSL_Types.Quaternion((Quaternion)p[i]); 1559 lsl_p[i] = new LSL_Types.Quaternion(((Quaternion)p[i]).X, ((Quaternion)p[i]).Y, ((Quaternion)p[i]).Z, ((Quaternion)p[i]).W);
1587 else if (p[i] is float) 1560 else if (p[i] is float)
1588 lsl_p[i] = new LSL_Types.LSLFloat((float)p[i]); 1561 lsl_p[i] = new LSL_Types.LSLFloat((float)p[i]);
1589 else 1562 else
@@ -1607,9 +1580,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1607 else if (p[i] is string) 1580 else if (p[i] is string)
1608 lsl_p[i] = new LSL_Types.LSLString((string)p[i]); 1581 lsl_p[i] = new LSL_Types.LSLString((string)p[i]);
1609 else if (p[i] is Vector3) 1582 else if (p[i] is Vector3)
1610 lsl_p[i] = new LSL_Types.Vector3((Vector3)p[i]); 1583 lsl_p[i] = new LSL_Types.Vector3(((Vector3)p[i]).X, ((Vector3)p[i]).Y, ((Vector3)p[i]).Z);
1611 else if (p[i] is Quaternion) 1584 else if (p[i] is Quaternion)
1612 lsl_p[i] = new LSL_Types.Quaternion((Quaternion)p[i]); 1585 lsl_p[i] = new LSL_Types.Quaternion(((Quaternion)p[i]).X, ((Quaternion)p[i]).Y, ((Quaternion)p[i]).Z, ((Quaternion)p[i]).W);
1613 else if (p[i] is float) 1586 else if (p[i] is float)
1614 lsl_p[i] = new LSL_Types.LSLFloat((float)p[i]); 1587 lsl_p[i] = new LSL_Types.LSLFloat((float)p[i]);
1615 else 1588 else
diff --git a/OpenSim/Region/UserStatistics/WebStatsModule.cs b/OpenSim/Region/UserStatistics/WebStatsModule.cs
index 625eba4..c11ea02 100644
--- a/OpenSim/Region/UserStatistics/WebStatsModule.cs
+++ b/OpenSim/Region/UserStatistics/WebStatsModule.cs
@@ -61,7 +61,7 @@ namespace OpenSim.Region.UserStatistics
61 /// <summary> 61 /// <summary>
62 /// User statistics sessions keyed by agent ID 62 /// User statistics sessions keyed by agent ID
63 /// </summary> 63 /// </summary>
64 private Dictionary<UUID, UserSession> m_sessions = new Dictionary<UUID, UserSession>(); 64 private Dictionary<UUID, UserSessionID> m_sessions = new Dictionary<UUID, UserSessionID>();
65 65
66 private List<Scene> m_scenes = new List<Scene>(); 66 private List<Scene> m_scenes = new List<Scene>();
67 private Dictionary<string, IStatsController> reports = new Dictionary<string, IStatsController>(); 67 private Dictionary<string, IStatsController> reports = new Dictionary<string, IStatsController>();
@@ -319,18 +319,14 @@ namespace OpenSim.Region.UserStatistics
319 319
320 private void OnMakeRootAgent(ScenePresence agent) 320 private void OnMakeRootAgent(ScenePresence agent)
321 { 321 {
322// m_log.DebugFormat(
323// "[WEB STATS MODULE]: Looking for session {0} for {1} in {2}",
324// agent.ControllingClient.SessionId, agent.Name, agent.Scene.Name);
325
326 lock (m_sessions) 322 lock (m_sessions)
327 { 323 {
328 UserSession uid; 324 UserSessionID uid;
329 325
330 if (!m_sessions.ContainsKey(agent.UUID)) 326 if (!m_sessions.ContainsKey(agent.UUID))
331 { 327 {
332 UserSessionData usd = UserSessionUtil.newUserSessionData(); 328 UserSessionData usd = UserSessionUtil.newUserSessionData();
333 uid = new UserSession(); 329 uid = new UserSessionID();
334 uid.name_f = agent.Firstname; 330 uid.name_f = agent.Firstname;
335 uid.name_l = agent.Lastname; 331 uid.name_l = agent.Lastname;
336 uid.session_data = usd; 332 uid.session_data = usd;
@@ -415,9 +411,9 @@ namespace OpenSim.Region.UserStatistics
415 return String.Empty; 411 return String.Empty;
416 } 412 }
417 413
418 private UserSession ParseViewerStats(string request, UUID agentID) 414 private UserSessionID ParseViewerStats(string request, UUID agentID)
419 { 415 {
420 UserSession uid = new UserSession(); 416 UserSessionID uid = new UserSessionID();
421 UserSessionData usd; 417 UserSessionData usd;
422 OSD message = OSDParser.DeserializeLLSDXml(request); 418 OSD message = OSDParser.DeserializeLLSDXml(request);
423 OSDMap mmap; 419 OSDMap mmap;
@@ -429,25 +425,22 @@ namespace OpenSim.Region.UserStatistics
429 if (!m_sessions.ContainsKey(agentID)) 425 if (!m_sessions.ContainsKey(agentID))
430 { 426 {
431 m_log.WarnFormat("[WEB STATS MODULE]: no session for stat disclosure for agent {0}", agentID); 427 m_log.WarnFormat("[WEB STATS MODULE]: no session for stat disclosure for agent {0}", agentID);
432 return new UserSession(); 428 return new UserSessionID();
433 } 429 }
434
435 uid = m_sessions[agentID]; 430 uid = m_sessions[agentID];
436
437// m_log.DebugFormat("[WEB STATS MODULE]: Got session {0} for {1}", uid.session_id, agentID);
438 } 431 }
439 else 432 else
440 { 433 {
441 // parse through the beginning to locate the session 434 // parse through the beginning to locate the session
442 if (message.Type != OSDType.Map) 435 if (message.Type != OSDType.Map)
443 return new UserSession(); 436 return new UserSessionID();
444 437
445 mmap = (OSDMap)message; 438 mmap = (OSDMap)message;
446 { 439 {
447 UUID sessionID = mmap["session_id"].AsUUID(); 440 UUID sessionID = mmap["session_id"].AsUUID();
448 441
449 if (sessionID == UUID.Zero) 442 if (sessionID == UUID.Zero)
450 return new UserSession(); 443 return new UserSessionID();
451 444
452 445
453 // search through each session looking for the owner 446 // search through each session looking for the owner
@@ -466,7 +459,7 @@ namespace OpenSim.Region.UserStatistics
466 // can't find a session 459 // can't find a session
467 if (agentID == UUID.Zero) 460 if (agentID == UUID.Zero)
468 { 461 {
469 return new UserSession(); 462 return new UserSessionID();
470 } 463 }
471 } 464 }
472 } 465 }
@@ -475,12 +468,12 @@ namespace OpenSim.Region.UserStatistics
475 usd = uid.session_data; 468 usd = uid.session_data;
476 469
477 if (message.Type != OSDType.Map) 470 if (message.Type != OSDType.Map)
478 return new UserSession(); 471 return new UserSessionID();
479 472
480 mmap = (OSDMap)message; 473 mmap = (OSDMap)message;
481 { 474 {
482 if (mmap["agent"].Type != OSDType.Map) 475 if (mmap["agent"].Type != OSDType.Map)
483 return new UserSession(); 476 return new UserSessionID();
484 OSDMap agent_map = (OSDMap)mmap["agent"]; 477 OSDMap agent_map = (OSDMap)mmap["agent"];
485 usd.agent_id = agentID; 478 usd.agent_id = agentID;
486 usd.name_f = uid.name_f; 479 usd.name_f = uid.name_f;
@@ -500,18 +493,17 @@ namespace OpenSim.Region.UserStatistics
500 (float)agent_map["fps"].AsReal()); 493 (float)agent_map["fps"].AsReal());
501 494
502 if (mmap["downloads"].Type != OSDType.Map) 495 if (mmap["downloads"].Type != OSDType.Map)
503 return new UserSession(); 496 return new UserSessionID();
504 OSDMap downloads_map = (OSDMap)mmap["downloads"]; 497 OSDMap downloads_map = (OSDMap)mmap["downloads"];
505 usd.d_object_kb = (float)downloads_map["object_kbytes"].AsReal(); 498 usd.d_object_kb = (float)downloads_map["object_kbytes"].AsReal();
506 usd.d_texture_kb = (float)downloads_map["texture_kbytes"].AsReal(); 499 usd.d_texture_kb = (float)downloads_map["texture_kbytes"].AsReal();
507 usd.d_world_kb = (float)downloads_map["workd_kbytes"].AsReal(); 500 usd.d_world_kb = (float)downloads_map["workd_kbytes"].AsReal();
508 501
509// m_log.DebugFormat("[WEB STATS MODULE]: mmap[\"session_id\"] = [{0}]", mmap["session_id"].AsUUID());
510 502
511 usd.session_id = mmap["session_id"].AsUUID(); 503 usd.session_id = mmap["session_id"].AsUUID();
512 504
513 if (mmap["system"].Type != OSDType.Map) 505 if (mmap["system"].Type != OSDType.Map)
514 return new UserSession(); 506 return new UserSessionID();
515 OSDMap system_map = (OSDMap)mmap["system"]; 507 OSDMap system_map = (OSDMap)mmap["system"];
516 508
517 usd.s_cpu = system_map["cpu"].AsString(); 509 usd.s_cpu = system_map["cpu"].AsString();
@@ -520,13 +512,13 @@ namespace OpenSim.Region.UserStatistics
520 usd.s_ram = system_map["ram"].AsInteger(); 512 usd.s_ram = system_map["ram"].AsInteger();
521 513
522 if (mmap["stats"].Type != OSDType.Map) 514 if (mmap["stats"].Type != OSDType.Map)
523 return new UserSession(); 515 return new UserSessionID();
524 516
525 OSDMap stats_map = (OSDMap)mmap["stats"]; 517 OSDMap stats_map = (OSDMap)mmap["stats"];
526 { 518 {
527 519
528 if (stats_map["failures"].Type != OSDType.Map) 520 if (stats_map["failures"].Type != OSDType.Map)
529 return new UserSession(); 521 return new UserSessionID();
530 OSDMap stats_failures = (OSDMap)stats_map["failures"]; 522 OSDMap stats_failures = (OSDMap)stats_map["failures"];
531 usd.f_dropped = stats_failures["dropped"].AsInteger(); 523 usd.f_dropped = stats_failures["dropped"].AsInteger();
532 usd.f_failed_resends = stats_failures["failed_resends"].AsInteger(); 524 usd.f_failed_resends = stats_failures["failed_resends"].AsInteger();
@@ -535,18 +527,18 @@ namespace OpenSim.Region.UserStatistics
535 usd.f_send_packet = stats_failures["send_packet"].AsInteger(); 527 usd.f_send_packet = stats_failures["send_packet"].AsInteger();
536 528
537 if (stats_map["net"].Type != OSDType.Map) 529 if (stats_map["net"].Type != OSDType.Map)
538 return new UserSession(); 530 return new UserSessionID();
539 OSDMap stats_net = (OSDMap)stats_map["net"]; 531 OSDMap stats_net = (OSDMap)stats_map["net"];
540 { 532 {
541 if (stats_net["in"].Type != OSDType.Map) 533 if (stats_net["in"].Type != OSDType.Map)
542 return new UserSession(); 534 return new UserSessionID();
543 535
544 OSDMap net_in = (OSDMap)stats_net["in"]; 536 OSDMap net_in = (OSDMap)stats_net["in"];
545 usd.n_in_kb = (float)net_in["kbytes"].AsReal(); 537 usd.n_in_kb = (float)net_in["kbytes"].AsReal();
546 usd.n_in_pk = net_in["packets"].AsInteger(); 538 usd.n_in_pk = net_in["packets"].AsInteger();
547 539
548 if (stats_net["out"].Type != OSDType.Map) 540 if (stats_net["out"].Type != OSDType.Map)
549 return new UserSession(); 541 return new UserSessionID();
550 OSDMap net_out = (OSDMap)stats_net["out"]; 542 OSDMap net_out = (OSDMap)stats_net["out"];
551 543
552 usd.n_out_kb = (float)net_out["kbytes"].AsReal(); 544 usd.n_out_kb = (float)net_out["kbytes"].AsReal();
@@ -557,18 +549,11 @@ namespace OpenSim.Region.UserStatistics
557 549
558 uid.session_data = usd; 550 uid.session_data = usd;
559 m_sessions[agentID] = uid; 551 m_sessions[agentID] = uid;
560
561// m_log.DebugFormat(
562// "[WEB STATS MODULE]: Parse data for {0} {1}, session {2}", uid.name_f, uid.name_l, uid.session_id);
563
564 return uid; 552 return uid;
565 } 553 }
566 554
567 private void UpdateUserStats(UserSession uid, SqliteConnection db) 555 private void UpdateUserStats(UserSessionID uid, SqliteConnection db)
568 { 556 {
569// m_log.DebugFormat(
570// "[WEB STATS MODULE]: Updating user stats for {0} {1}, session {2}", uid.name_f, uid.name_l, uid.session_id);
571
572 if (uid.session_id == UUID.Zero) 557 if (uid.session_id == UUID.Zero)
573 return; 558 return;
574 559
@@ -755,6 +740,7 @@ VALUES
755 s.min_ping = ArrayMin_f(__ping); 740 s.min_ping = ArrayMin_f(__ping);
756 s.max_ping = ArrayMax_f(__ping); 741 s.max_ping = ArrayMax_f(__ping);
757 s.mode_ping = ArrayMode_f(__ping); 742 s.mode_ping = ArrayMode_f(__ping);
743
758 } 744 }
759 745
760 #region Statistics 746 #region Statistics
@@ -999,7 +985,7 @@ VALUES
999 } 985 }
1000 #region structs 986 #region structs
1001 987
1002 public class UserSession 988 public struct UserSessionID
1003 { 989 {
1004 public UUID session_id; 990 public UUID session_id;
1005 public UUID region_id; 991 public UUID region_id;
diff --git a/OpenSim/Server/Base/ServicesServerBase.cs b/OpenSim/Server/Base/ServicesServerBase.cs
index 0cff6ed..b137c05 100644
--- a/OpenSim/Server/Base/ServicesServerBase.cs
+++ b/OpenSim/Server/Base/ServicesServerBase.cs
@@ -26,7 +26,6 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic;
30using System.IO; 29using System.IO;
31using System.Reflection; 30using System.Reflection;
32using System.Threading; 31using System.Threading;
@@ -72,17 +71,10 @@ namespace OpenSim.Server.Base
72 // 71 //
73 private string m_pidFile = String.Empty; 72 private string m_pidFile = String.Empty;
74 73
75 /// <summary>
76 /// Time at which this server was started
77 /// </summary>
78 protected DateTime m_startuptime;
79
80 // Handle all the automagical stuff 74 // Handle all the automagical stuff
81 // 75 //
82 public ServicesServerBase(string prompt, string[] args) 76 public ServicesServerBase(string prompt, string[] args)
83 { 77 {
84 m_startuptime = DateTime.Now;
85
86 // Save raw arguments 78 // Save raw arguments
87 // 79 //
88 m_Arguments = args; 80 m_Arguments = args;
@@ -258,10 +250,6 @@ namespace OpenSim.Server.Base
258 "command-script <script>", 250 "command-script <script>",
259 "Run a command script from file", HandleScript); 251 "Run a command script from file", HandleScript);
260 252
261 MainConsole.Instance.Commands.AddCommand("General", false, "show uptime",
262 "show uptime",
263 "Show server uptime", HandleShow);
264
265 253
266 // Allow derived classes to perform initialization that 254 // Allow derived classes to perform initialization that
267 // needs to be done after the console has opened 255 // needs to be done after the console has opened
@@ -357,34 +345,5 @@ namespace OpenSim.Server.Base
357 { 345 {
358 } 346 }
359 } 347 }
360
361 public virtual void HandleShow(string module, string[] cmd)
362 {
363 List<string> args = new List<string>(cmd);
364
365 args.RemoveAt(0);
366
367 string[] showParams = args.ToArray();
368
369 switch (showParams[0])
370 {
371 case "uptime":
372 MainConsole.Instance.Output(GetUptimeReport());
373 break;
374 }
375 }
376
377 /// <summary>
378 /// Return a report about the uptime of this server
379 /// </summary>
380 /// <returns></returns>
381 protected string GetUptimeReport()
382 {
383 StringBuilder sb = new StringBuilder(String.Format("Time now is {0}\n", DateTime.Now));
384 sb.Append(String.Format("Server has been running since {0}, {1}\n", m_startuptime.DayOfWeek, m_startuptime));
385 sb.Append(String.Format("That is an elapsed time of {0}\n", DateTime.Now - m_startuptime));
386
387 return sb.ToString();
388 }
389 } 348 }
390} 349}
diff --git a/OpenSim/Server/Handlers/Asset/AssetServerConnector.cs b/OpenSim/Server/Handlers/Asset/AssetServerConnector.cs
index ff45d94..46b0c67 100644
--- a/OpenSim/Server/Handlers/Asset/AssetServerConnector.cs
+++ b/OpenSim/Server/Handlers/Asset/AssetServerConnector.cs
@@ -67,25 +67,10 @@ namespace OpenSim.Server.Handlers.Asset
67 throw new Exception(String.Format("Failed to load AssetService from {0}; config is {1}", assetService, m_ConfigName)); 67 throw new Exception(String.Format("Failed to load AssetService from {0}; config is {1}", assetService, m_ConfigName));
68 68
69 bool allowDelete = serverConfig.GetBoolean("AllowRemoteDelete", false); 69 bool allowDelete = serverConfig.GetBoolean("AllowRemoteDelete", false);
70 bool allowDeleteAllTypes = serverConfig.GetBoolean("AllowRemoteDeleteAllTypes", false);
71
72 AllowedRemoteDeleteTypes allowedRemoteDeleteTypes;
73
74 if (!allowDelete)
75 {
76 allowedRemoteDeleteTypes = AllowedRemoteDeleteTypes.None;
77 }
78 else
79 {
80 if (allowDeleteAllTypes)
81 allowedRemoteDeleteTypes = AllowedRemoteDeleteTypes.All;
82 else
83 allowedRemoteDeleteTypes = AllowedRemoteDeleteTypes.MapTile;
84 }
85 70
86 server.AddStreamHandler(new AssetServerGetHandler(m_AssetService)); 71 server.AddStreamHandler(new AssetServerGetHandler(m_AssetService));
87 server.AddStreamHandler(new AssetServerPostHandler(m_AssetService)); 72 server.AddStreamHandler(new AssetServerPostHandler(m_AssetService));
88 server.AddStreamHandler(new AssetServerDeleteHandler(m_AssetService, allowedRemoteDeleteTypes)); 73 server.AddStreamHandler(new AssetServerDeleteHandler(m_AssetService, allowDelete));
89 74
90 MainConsole.Instance.Commands.AddCommand("Assets", false, 75 MainConsole.Instance.Commands.AddCommand("Assets", false,
91 "show asset", 76 "show asset",
@@ -156,9 +141,6 @@ namespace OpenSim.Server.Handlers.Asset
156 } 141 }
157 142
158 string fileName = rawAssetId; 143 string fileName = rawAssetId;
159
160 if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, fileName))
161 return;
162 144
163 using (FileStream fs = new FileStream(fileName, FileMode.CreateNew)) 145 using (FileStream fs = new FileStream(fileName, FileMode.CreateNew))
164 { 146 {
diff --git a/OpenSim/Server/Handlers/Asset/AssetServerDeleteHandler.cs b/OpenSim/Server/Handlers/Asset/AssetServerDeleteHandler.cs
index 986394b..0cfe5b1 100644
--- a/OpenSim/Server/Handlers/Asset/AssetServerDeleteHandler.cs
+++ b/OpenSim/Server/Handlers/Asset/AssetServerDeleteHandler.cs
@@ -42,32 +42,18 @@ using OpenSim.Framework.Servers.HttpServer;
42 42
43namespace OpenSim.Server.Handlers.Asset 43namespace OpenSim.Server.Handlers.Asset
44{ 44{
45 /// <summary>
46 /// Remote deletes allowed.
47 /// </summary>
48 public enum AllowedRemoteDeleteTypes
49 {
50 None,
51 MapTile,
52 All
53 }
54
55 public class AssetServerDeleteHandler : BaseStreamHandler 45 public class AssetServerDeleteHandler : BaseStreamHandler
56 { 46 {
57 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
58 48
59 private IAssetService m_AssetService; 49 private IAssetService m_AssetService;
50 protected bool m_allowDelete;
60 51
61 /// <summary> 52 public AssetServerDeleteHandler(IAssetService service, bool allowDelete) :
62 /// Asset types that can be deleted remotely.
63 /// </summary>
64 private AllowedRemoteDeleteTypes m_allowedTypes;
65
66 public AssetServerDeleteHandler(IAssetService service, AllowedRemoteDeleteTypes allowedTypes) :
67 base("DELETE", "/assets") 53 base("DELETE", "/assets")
68 { 54 {
69 m_AssetService = service; 55 m_AssetService = service;
70 m_allowedTypes = allowedTypes; 56 m_allowDelete = allowDelete;
71 } 57 }
72 58
73 public override byte[] Handle(string path, Stream request, 59 public override byte[] Handle(string path, Stream request,
@@ -77,32 +63,13 @@ namespace OpenSim.Server.Handlers.Asset
77 63
78 string[] p = SplitParams(path); 64 string[] p = SplitParams(path);
79 65
80 if (p.Length > 0) 66 if (p.Length > 0 && m_allowDelete)
81 { 67 {
82 if (m_allowedTypes != AllowedRemoteDeleteTypes.None) 68 result = m_AssetService.Delete(p[0]);
83 {
84 string assetID = p[0];
85
86 AssetBase asset = m_AssetService.Get(assetID);
87 if (asset != null)
88 {
89 if (m_allowedTypes == AllowedRemoteDeleteTypes.All
90 || (int)(asset.Flags & AssetFlags.Maptile) != 0)
91 {
92 result = m_AssetService.Delete(assetID);
93 }
94 else
95 {
96 m_log.DebugFormat(
97 "[ASSET SERVER DELETE HANDLER]: Request to delete asset {0}, but type is {1} and allowed remote delete types are {2}",
98 assetID, (AssetFlags)asset.Flags, m_allowedTypes);
99 }
100 }
101 }
102 } 69 }
103 70
104 XmlSerializer xs = new XmlSerializer(typeof(bool)); 71 XmlSerializer xs = new XmlSerializer(typeof(bool));
105 return ServerUtils.SerializeResult(xs, result); 72 return ServerUtils.SerializeResult(xs, result);
106 } 73 }
107 } 74 }
108} \ No newline at end of file 75}
diff --git a/OpenSim/Server/Handlers/Avatar/AvatarServerPostHandler.cs b/OpenSim/Server/Handlers/Avatar/AvatarServerPostHandler.cs
index 8cd747e..393584e 100644
--- a/OpenSim/Server/Handlers/Avatar/AvatarServerPostHandler.cs
+++ b/OpenSim/Server/Handlers/Avatar/AvatarServerPostHandler.cs
@@ -137,8 +137,6 @@ namespace OpenSim.Server.Handlers.Avatar
137 if (!UUID.TryParse(request["UserID"].ToString(), out user)) 137 if (!UUID.TryParse(request["UserID"].ToString(), out user))
138 return FailureResult(); 138 return FailureResult();
139 139
140 RemoveRequestParamsNotForStorage(request);
141
142 AvatarData avatar = new AvatarData(request); 140 AvatarData avatar = new AvatarData(request);
143 if (m_AvatarService.SetAvatar(user, avatar)) 141 if (m_AvatarService.SetAvatar(user, avatar))
144 return SuccessResult(); 142 return SuccessResult();
@@ -155,25 +153,11 @@ namespace OpenSim.Server.Handlers.Avatar
155 if (!UUID.TryParse(request["UserID"].ToString(), out user)) 153 if (!UUID.TryParse(request["UserID"].ToString(), out user))
156 return FailureResult(); 154 return FailureResult();
157 155
158 RemoveRequestParamsNotForStorage(request);
159
160 if (m_AvatarService.ResetAvatar(user)) 156 if (m_AvatarService.ResetAvatar(user))
161 return SuccessResult(); 157 return SuccessResult();
162 158
163 return FailureResult(); 159 return FailureResult();
164 } 160 }
165
166 /// <summary>
167 /// Remove parameters that were used to invoke the method and should not in themselves be persisted.
168 /// </summary>
169 /// <param name='request'></param>
170 private void RemoveRequestParamsNotForStorage(Dictionary<string, object> request)
171 {
172 request.Remove("VERSIONMAX");
173 request.Remove("VERSIONMIN");
174 request.Remove("METHOD");
175 request.Remove("UserID");
176 }
177 161
178 byte[] SetItems(Dictionary<string, object> request) 162 byte[] SetItems(Dictionary<string, object> request)
179 { 163 {
@@ -189,8 +173,6 @@ namespace OpenSim.Server.Handlers.Avatar
189 if (!(request["Names"] is List<string> || request["Values"] is List<string>)) 173 if (!(request["Names"] is List<string> || request["Values"] is List<string>))
190 return FailureResult(); 174 return FailureResult();
191 175
192 RemoveRequestParamsNotForStorage(request);
193
194 List<string> _names = (List<string>)request["Names"]; 176 List<string> _names = (List<string>)request["Names"];
195 names = _names.ToArray(); 177 names = _names.ToArray();
196 List<string> _values = (List<string>)request["Values"]; 178 List<string> _values = (List<string>)request["Values"];
diff --git a/OpenSim/Server/ServerMain.cs b/OpenSim/Server/ServerMain.cs
index 45c13fb..21fb678 100644
--- a/OpenSim/Server/ServerMain.cs
+++ b/OpenSim/Server/ServerMain.cs
@@ -60,25 +60,7 @@ namespace OpenSim.Server
60 } 60 }
61 61
62 string connList = serverConfig.GetString("ServiceConnectors", String.Empty); 62 string connList = serverConfig.GetString("ServiceConnectors", String.Empty);
63 63 string[] conns = connList.Split(new char[] {',', ' '});
64 IConfig servicesConfig = m_Server.Config.Configs["ServiceList"];
65 if (servicesConfig != null)
66 {
67 List<string> servicesList = new List<string>();
68 if (connList != String.Empty)
69 servicesList.Add(connList);
70
71 foreach (string k in servicesConfig.GetKeys())
72 {
73 string v = servicesConfig.GetString(k);
74 if (v != String.Empty)
75 servicesList.Add(v);
76 }
77
78 connList = String.Join(",", servicesList.ToArray());
79 }
80
81 string[] conns = connList.Split(new char[] {',', ' ', '\n', '\r', '\t'});
82 64
83// int i = 0; 65// int i = 0;
84 foreach (string c in conns) 66 foreach (string c in conns)
@@ -148,4 +130,4 @@ namespace OpenSim.Server
148 return 0; 130 return 0;
149 } 131 }
150 } 132 }
151} 133} \ No newline at end of file
diff --git a/OpenSim/Services/AssetService/AssetService.cs b/OpenSim/Services/AssetService/AssetService.cs
index f1bffa4..96b430d 100644
--- a/OpenSim/Services/AssetService/AssetService.cs
+++ b/OpenSim/Services/AssetService/AssetService.cs
@@ -70,7 +70,7 @@ namespace OpenSim.Services.AssetService
70 70
71 if (assetLoaderEnabled) 71 if (assetLoaderEnabled)
72 { 72 {
73 m_log.DebugFormat("[ASSET SERVICE]: Loading default asset set from {0}", loaderArgs); 73 m_log.DebugFormat("[ASSET]: Loading default asset set from {0}", loaderArgs);
74 74
75 m_AssetLoader.ForEachDefaultXmlAsset( 75 m_AssetLoader.ForEachDefaultXmlAsset(
76 loaderArgs, 76 loaderArgs,
@@ -200,7 +200,20 @@ namespace OpenSim.Services.AssetService
200 if (!UUID.TryParse(id, out assetID)) 200 if (!UUID.TryParse(id, out assetID))
201 return false; 201 return false;
202 202
203 return m_Database.Delete(id); 203 AssetBase asset = m_Database.GetAsset(assetID);
204 if (asset == null)
205 return false;
206
207 if ((int)(asset.Flags & AssetFlags.Maptile) != 0)
208 {
209 return m_Database.Delete(id);
210 }
211 else
212 {
213 m_log.DebugFormat("[ASSET SERVICE]: Request to delete asset {0}, but flags are not Maptile", id);
214 }
215
216 return false;
204 } 217 }
205 } 218 }
206} \ No newline at end of file 219} \ No newline at end of file
diff --git a/OpenSim/Services/AssetService/AssetServiceBase.cs b/OpenSim/Services/AssetService/AssetServiceBase.cs
index 58ab052..177c565 100644
--- a/OpenSim/Services/AssetService/AssetServiceBase.cs
+++ b/OpenSim/Services/AssetService/AssetServiceBase.cs
@@ -84,7 +84,7 @@ namespace OpenSim.Services.AssetService
84 84
85 m_Database = LoadPlugin<IAssetDataPlugin>(dllName); 85 m_Database = LoadPlugin<IAssetDataPlugin>(dllName);
86 if (m_Database == null) 86 if (m_Database == null)
87 throw new Exception(string.Format("Could not find a storage interface in the module {0}", dllName)); 87 throw new Exception("Could not find a storage interface in the given module");
88 88
89 m_Database.Initialise(connString); 89 m_Database.Initialise(connString);
90 90
@@ -96,7 +96,7 @@ namespace OpenSim.Services.AssetService
96 m_AssetLoader = LoadPlugin<IAssetLoader>(loaderName); 96 m_AssetLoader = LoadPlugin<IAssetLoader>(loaderName);
97 97
98 if (m_AssetLoader == null) 98 if (m_AssetLoader == null)
99 throw new Exception(string.Format("Asset loader could not be loaded from {0}", loaderName)); 99 throw new Exception("Asset loader could not be loaded");
100 } 100 }
101 } 101 }
102 } 102 }
diff --git a/OpenSim/Services/AssetService/XAssetService.cs b/OpenSim/Services/AssetService/XAssetService.cs
index a1d10ed..e62bcb5 100644
--- a/OpenSim/Services/AssetService/XAssetService.cs
+++ b/OpenSim/Services/AssetService/XAssetService.cs
@@ -194,7 +194,21 @@ namespace OpenSim.Services.AssetService
194 if (!UUID.TryParse(id, out assetID)) 194 if (!UUID.TryParse(id, out assetID))
195 return false; 195 return false;
196 196
197 return m_Database.Delete(id); 197 AssetBase asset = m_Database.GetAsset(assetID);
198 if (asset == null)
199 return false;
200
201 if ((int)(asset.Flags & AssetFlags.Maptile) != 0)
202 {
203 return m_Database.Delete(id);
204 }
205 else
206 {
207 m_log.DebugFormat("[XASSET SERVICE]: Request to delete asset {0}, but flags are not Maptile", id);
208 }
209
210 return false;
198 } 211 }
199 } 212 }
200} \ No newline at end of file 213}
214
diff --git a/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs b/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs
index 4b502b7..7f32ad3 100644
--- a/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs
+++ b/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs
@@ -52,8 +52,6 @@ namespace OpenSim.Services.Connectors
52 private int m_retryCounter; 52 private int m_retryCounter;
53 private Dictionary<int, List<AssetBase>> m_retryQueue = new Dictionary<int, List<AssetBase>>(); 53 private Dictionary<int, List<AssetBase>> m_retryQueue = new Dictionary<int, List<AssetBase>>();
54 private System.Timers.Timer m_retryTimer; 54 private System.Timers.Timer m_retryTimer;
55 private int m_maxAssetRequestConcurrency = 30;
56
57 private delegate void AssetRetrievedEx(AssetBase asset); 55 private delegate void AssetRetrievedEx(AssetBase asset);
58 56
59 // Keeps track of concurrent requests for the same asset, so that it's only loaded once. 57 // Keeps track of concurrent requests for the same asset, so that it's only loaded once.
@@ -82,10 +80,6 @@ namespace OpenSim.Services.Connectors
82 80
83 public virtual void Initialise(IConfigSource source) 81 public virtual void Initialise(IConfigSource source)
84 { 82 {
85 IConfig netconfig = source.Configs["Network"];
86 if (netconfig != null)
87 m_maxAssetRequestConcurrency = netconfig.GetInt("MaxRequestConcurrency",m_maxAssetRequestConcurrency);
88
89 IConfig assetConfig = source.Configs["AssetService"]; 83 IConfig assetConfig = source.Configs["AssetService"];
90 if (assetConfig == null) 84 if (assetConfig == null)
91 { 85 {
@@ -210,7 +204,7 @@ namespace OpenSim.Services.Connectors
210 if (asset == null || asset.Data == null || asset.Data.Length == 0) 204 if (asset == null || asset.Data == null || asset.Data.Length == 0)
211 { 205 {
212 asset = SynchronousRestObjectRequester. 206 asset = SynchronousRestObjectRequester.
213 MakeRequest<int, AssetBase>("GET", uri, 0, m_maxAssetRequestConcurrency); 207 MakeRequest<int, AssetBase>("GET", uri, 0, 30);
214 208
215 if (m_Cache != null) 209 if (m_Cache != null)
216 m_Cache.Cache(asset); 210 m_Cache.Cache(asset);
diff --git a/OpenSim/Services/Connectors/Friends/FriendsSimConnector.cs b/OpenSim/Services/Connectors/Friends/FriendsSimConnector.cs
index 45f4514..6cd21d1 100644
--- a/OpenSim/Services/Connectors/Friends/FriendsSimConnector.cs
+++ b/OpenSim/Services/Connectors/Friends/FriendsSimConnector.cs
@@ -128,7 +128,7 @@ namespace OpenSim.Services.Connectors.Friends
128 return Call(region, sendData); 128 return Call(region, sendData);
129 } 129 }
130 130
131 public bool StatusNotify(GridRegion region, UUID userID, string friendID, bool online) 131 public bool StatusNotify(GridRegion region, UUID userID, UUID friendID, bool online)
132 { 132 {
133 Dictionary<string, object> sendData = new Dictionary<string, object>(); 133 Dictionary<string, object> sendData = new Dictionary<string, object>();
134 //sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString(); 134 //sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
@@ -136,7 +136,7 @@ namespace OpenSim.Services.Connectors.Friends
136 sendData["METHOD"] = "status"; 136 sendData["METHOD"] = "status";
137 137
138 sendData["FromID"] = userID.ToString(); 138 sendData["FromID"] = userID.ToString();
139 sendData["ToID"] = friendID; 139 sendData["ToID"] = friendID.ToString();
140 sendData["Online"] = online.ToString(); 140 sendData["Online"] = online.ToString();
141 141
142 return Call(region, sendData); 142 return Call(region, sendData);
@@ -154,7 +154,7 @@ namespace OpenSim.Services.Connectors.Friends
154 if (!region.ServerURI.EndsWith("/")) 154 if (!region.ServerURI.EndsWith("/"))
155 path = "/" + path; 155 path = "/" + path;
156 string uri = region.ServerURI + path; 156 string uri = region.ServerURI + path;
157 // m_log.DebugFormat("[FRIENDS SIM CONNECTOR]: calling {0}", uri); 157 m_log.DebugFormat("[FRIENDS SIM CONNECTOR]: calling {0}", uri);
158 158
159 try 159 try
160 { 160 {
diff --git a/OpenSim/Services/Connectors/GridUser/GridUserServicesConnector.cs b/OpenSim/Services/Connectors/GridUser/GridUserServicesConnector.cs
index 94bda82..20d7eaf 100644
--- a/OpenSim/Services/Connectors/GridUser/GridUserServicesConnector.cs
+++ b/OpenSim/Services/Connectors/GridUser/GridUserServicesConnector.cs
@@ -207,7 +207,7 @@ namespace OpenSim.Services.Connectors
207 if ((replyData != null) && replyData.ContainsKey("result") && (replyData["result"] != null)) 207 if ((replyData != null) && replyData.ContainsKey("result") && (replyData["result"] != null))
208 { 208 {
209 if (replyData["result"] is Dictionary<string, object>) 209 if (replyData["result"] is Dictionary<string, object>)
210 guinfo = Create((Dictionary<string, object>)replyData["result"]); 210 guinfo = new GridUserInfo((Dictionary<string, object>)replyData["result"]);
211 } 211 }
212 212
213 return guinfo; 213 return guinfo;
@@ -273,7 +273,7 @@ namespace OpenSim.Services.Connectors
273 { 273 {
274 if (griduser is Dictionary<string, object>) 274 if (griduser is Dictionary<string, object>)
275 { 275 {
276 GridUserInfo pinfo = Create((Dictionary<string, object>)griduser); 276 GridUserInfo pinfo = new GridUserInfo((Dictionary<string, object>)griduser);
277 rinfos.Add(pinfo); 277 rinfos.Add(pinfo);
278 } 278 }
279 else 279 else
@@ -286,10 +286,5 @@ namespace OpenSim.Services.Connectors
286 286
287 return rinfos.ToArray(); 287 return rinfos.ToArray();
288 } 288 }
289
290 protected virtual GridUserInfo Create(Dictionary<string, object> griduser)
291 {
292 return new GridUserInfo(griduser);
293 }
294 } 289 }
295} 290}
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs
index 20eaa3a..0e4d794 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs
@@ -112,7 +112,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
112// m_log.Warn("Registering region " + regionInfo.RegionName + " (" + regionInfo.RegionID + ") that we are not tracking"); 112// m_log.Warn("Registering region " + regionInfo.RegionName + " (" + regionInfo.RegionID + ") that we are not tracking");
113 113
114 Vector3d minPosition = new Vector3d(regionInfo.RegionLocX, regionInfo.RegionLocY, 0.0); 114 Vector3d minPosition = new Vector3d(regionInfo.RegionLocX, regionInfo.RegionLocY, 0.0);
115 Vector3d maxPosition = minPosition + new Vector3d(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); 115 Vector3d maxPosition = minPosition + new Vector3d(Constants.RegionSize, Constants.RegionSize, 4096.0);
116 116
117 OSDMap extraData = new OSDMap 117 OSDMap extraData = new OSDMap
118 { 118 {
@@ -297,7 +297,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
297 List<GridRegion> foundRegions = new List<GridRegion>(); 297 List<GridRegion> foundRegions = new List<GridRegion>();
298 298
299 Vector3d minPosition = new Vector3d(xmin, ymin, 0.0); 299 Vector3d minPosition = new Vector3d(xmin, ymin, 0.0);
300 Vector3d maxPosition = new Vector3d(xmax, ymax, Constants.RegionHeight); 300 Vector3d maxPosition = new Vector3d(xmax, ymax, 4096.0);
301 301
302 NameValueCollection requestArgs = new NameValueCollection 302 NameValueCollection requestArgs = new NameValueCollection
303 { 303 {
@@ -395,8 +395,8 @@ namespace OpenSim.Services.Connectors.SimianGrid
395 if (response["Success"].AsBoolean()) 395 if (response["Success"].AsBoolean())
396 { 396 {
397 OSDMap extraData = response["ExtraData"] as OSDMap; 397 OSDMap extraData = response["ExtraData"] as OSDMap;
398 int enabled = response["Enabled"].AsBoolean() ? (int)OpenSim.Framework.RegionFlags.RegionOnline : 0; 398 int enabled = response["Enabled"].AsBoolean() ? (int) OpenSim.Data.RegionFlags.RegionOnline : 0;
399 int hypergrid = extraData["HyperGrid"].AsBoolean() ? (int)OpenSim.Framework.RegionFlags.Hyperlink : 0; 399 int hypergrid = extraData["HyperGrid"].AsBoolean() ? (int) OpenSim.Data.RegionFlags.Hyperlink : 0;
400 int flags = enabled | hypergrid; 400 int flags = enabled | hypergrid;
401 m_log.DebugFormat("[SGGC] enabled - {0} hg - {1} flags - {2}", enabled, hypergrid, flags); 401 m_log.DebugFormat("[SGGC] enabled - {0} hg - {1} flags - {2}", enabled, hypergrid, flags);
402 return flags; 402 return flags;
diff --git a/OpenSim/Services/GridService/GridService.cs b/OpenSim/Services/GridService/GridService.cs
index ee3b858..aab403a 100644
--- a/OpenSim/Services/GridService/GridService.cs
+++ b/OpenSim/Services/GridService/GridService.cs
@@ -137,25 +137,20 @@ namespace OpenSim.Services.GridService
137 if (regionInfos.RegionID == UUID.Zero) 137 if (regionInfos.RegionID == UUID.Zero)
138 return "Invalid RegionID - cannot be zero UUID"; 138 return "Invalid RegionID - cannot be zero UUID";
139 139
140 // This needs better sanity testing. What if regionInfo is registering in
141 // overlapping coords?
140 RegionData region = m_Database.Get(regionInfos.RegionLocX, regionInfos.RegionLocY, scopeID); 142 RegionData region = m_Database.Get(regionInfos.RegionLocX, regionInfos.RegionLocY, scopeID);
141 if ((region != null) && (region.RegionID != regionInfos.RegionID))
142 {
143 m_log.WarnFormat("[GRID SERVICE]: Region {0} tried to register in coordinates {1}, {2} which are already in use in scope {3}.",
144 regionInfos.RegionID, regionInfos.RegionLocX, regionInfos.RegionLocY, scopeID);
145 return "Region overlaps another region";
146 }
147
148 if (region != null) 143 if (region != null)
149 { 144 {
150 // There is a preexisting record 145 // There is a preexisting record
151 // 146 //
152 // Get it's flags 147 // Get it's flags
153 // 148 //
154 OpenSim.Framework.RegionFlags rflags = (OpenSim.Framework.RegionFlags)Convert.ToInt32(region.Data["flags"]); 149 OpenSim.Data.RegionFlags rflags = (OpenSim.Data.RegionFlags)Convert.ToInt32(region.Data["flags"]);
155 150
156 // Is this a reservation? 151 // Is this a reservation?
157 // 152 //
158 if ((rflags & OpenSim.Framework.RegionFlags.Reservation) != 0) 153 if ((rflags & OpenSim.Data.RegionFlags.Reservation) != 0)
159 { 154 {
160 // Regions reserved for the null key cannot be taken. 155 // Regions reserved for the null key cannot be taken.
161 if ((string)region.Data["PrincipalID"] == UUID.Zero.ToString()) 156 if ((string)region.Data["PrincipalID"] == UUID.Zero.ToString())
@@ -166,10 +161,10 @@ namespace OpenSim.Services.GridService
166 // NOTE: Fudging the flags value here, so these flags 161 // NOTE: Fudging the flags value here, so these flags
167 // should not be used elsewhere. Don't optimize 162 // should not be used elsewhere. Don't optimize
168 // this with the later retrieval of the same flags! 163 // this with the later retrieval of the same flags!
169 rflags |= OpenSim.Framework.RegionFlags.Authenticate; 164 rflags |= OpenSim.Data.RegionFlags.Authenticate;
170 } 165 }
171 166
172 if ((rflags & OpenSim.Framework.RegionFlags.Authenticate) != 0) 167 if ((rflags & OpenSim.Data.RegionFlags.Authenticate) != 0)
173 { 168 {
174 // Can we authenticate at all? 169 // Can we authenticate at all?
175 // 170 //
@@ -181,36 +176,19 @@ namespace OpenSim.Services.GridService
181 } 176 }
182 } 177 }
183 178
184 // If we get here, the destination is clear. Now for the real check. 179 if ((region != null) && (region.RegionID != regionInfos.RegionID))
185
186 if (!m_AllowDuplicateNames)
187 { 180 {
188 List<RegionData> dupe = m_Database.Get(regionInfos.RegionName, scopeID); 181 m_log.WarnFormat("[GRID SERVICE]: Region {0} tried to register in coordinates {1}, {2} which are already in use in scope {3}.",
189 if (dupe != null && dupe.Count > 0) 182 regionInfos.RegionID, regionInfos.RegionLocX, regionInfos.RegionLocY, scopeID);
190 { 183 return "Region overlaps another region";
191 foreach (RegionData d in dupe)
192 {
193 if (d.RegionID != regionInfos.RegionID)
194 {
195 m_log.WarnFormat("[GRID SERVICE]: Region {0} tried to register duplicate name with ID {1}.",
196 regionInfos.RegionName, regionInfos.RegionID);
197 return "Duplicate region name";
198 }
199 }
200 }
201 } 184 }
202 185
203 // If there is an old record for us, delete it if it is elsewhere.
204 region = m_Database.Get(regionInfos.RegionID, scopeID);
205 if ((region != null) && (region.RegionID == regionInfos.RegionID) && 186 if ((region != null) && (region.RegionID == regionInfos.RegionID) &&
206 ((region.posX != regionInfos.RegionLocX) || (region.posY != regionInfos.RegionLocY))) 187 ((region.posX != regionInfos.RegionLocX) || (region.posY != regionInfos.RegionLocY)))
207 { 188 {
208 if ((Convert.ToInt32(region.Data["flags"]) & (int)OpenSim.Framework.RegionFlags.NoMove) != 0) 189 if ((Convert.ToInt32(region.Data["flags"]) & (int)OpenSim.Data.RegionFlags.NoMove) != 0)
209 return "Can't move this region"; 190 return "Can't move this region";
210 191
211 if ((Convert.ToInt32(region.Data["flags"]) & (int)OpenSim.Framework.RegionFlags.LockedOut) != 0)
212 return "Region locked out";
213
214 // Region reregistering in other coordinates. Delete the old entry 192 // Region reregistering in other coordinates. Delete the old entry
215 m_log.DebugFormat("[GRID SERVICE]: Region {0} ({1}) was previously registered at {2}-{3}. Deleting old entry.", 193 m_log.DebugFormat("[GRID SERVICE]: Region {0} ({1}) was previously registered at {2}-{3}. Deleting old entry.",
216 regionInfos.RegionName, regionInfos.RegionID, regionInfos.RegionLocX, regionInfos.RegionLocY); 194 regionInfos.RegionName, regionInfos.RegionID, regionInfos.RegionLocX, regionInfos.RegionLocY);
@@ -225,6 +203,23 @@ namespace OpenSim.Services.GridService
225 } 203 }
226 } 204 }
227 205
206 if (!m_AllowDuplicateNames)
207 {
208 List<RegionData> dupe = m_Database.Get(regionInfos.RegionName, scopeID);
209 if (dupe != null && dupe.Count > 0)
210 {
211 foreach (RegionData d in dupe)
212 {
213 if (d.RegionID != regionInfos.RegionID)
214 {
215 m_log.WarnFormat("[GRID SERVICE]: Region {0} tried to register duplicate name with ID {1}.",
216 regionInfos.RegionName, regionInfos.RegionID);
217 return "Duplicate region name";
218 }
219 }
220 }
221 }
222
228 // Everything is ok, let's register 223 // Everything is ok, let's register
229 RegionData rdata = RegionInfo2RegionData(regionInfos); 224 RegionData rdata = RegionInfo2RegionData(regionInfos);
230 rdata.ScopeID = scopeID; 225 rdata.ScopeID = scopeID;
@@ -232,8 +227,10 @@ namespace OpenSim.Services.GridService
232 if (region != null) 227 if (region != null)
233 { 228 {
234 int oldFlags = Convert.ToInt32(region.Data["flags"]); 229 int oldFlags = Convert.ToInt32(region.Data["flags"]);
230 if ((oldFlags & (int)OpenSim.Data.RegionFlags.LockedOut) != 0)
231 return "Region locked out";
235 232
236 oldFlags &= ~(int)OpenSim.Framework.RegionFlags.Reservation; 233 oldFlags &= ~(int)OpenSim.Data.RegionFlags.Reservation;
237 234
238 rdata.Data["flags"] = oldFlags.ToString(); // Preserve flags 235 rdata.Data["flags"] = oldFlags.ToString(); // Preserve flags
239 } 236 }
@@ -252,7 +249,7 @@ namespace OpenSim.Services.GridService
252 } 249 }
253 250
254 int flags = Convert.ToInt32(rdata.Data["flags"]); 251 int flags = Convert.ToInt32(rdata.Data["flags"]);
255 flags |= (int)OpenSim.Framework.RegionFlags.RegionOnline; 252 flags |= (int)OpenSim.Data.RegionFlags.RegionOnline;
256 rdata.Data["flags"] = flags.ToString(); 253 rdata.Data["flags"] = flags.ToString();
257 254
258 try 255 try
@@ -283,9 +280,9 @@ namespace OpenSim.Services.GridService
283 280
284 int flags = Convert.ToInt32(region.Data["flags"]); 281 int flags = Convert.ToInt32(region.Data["flags"]);
285 282
286 if (!m_DeleteOnUnregister || (flags & (int)OpenSim.Framework.RegionFlags.Persistent) != 0) 283 if (!m_DeleteOnUnregister || (flags & (int)OpenSim.Data.RegionFlags.Persistent) != 0)
287 { 284 {
288 flags &= ~(int)OpenSim.Framework.RegionFlags.RegionOnline; 285 flags &= ~(int)OpenSim.Data.RegionFlags.RegionOnline;
289 region.Data["flags"] = flags.ToString(); 286 region.Data["flags"] = flags.ToString();
290 region.Data["last_seen"] = Util.UnixTimeSinceEpoch(); 287 region.Data["last_seen"] = Util.UnixTimeSinceEpoch();
291 try 288 try
@@ -320,7 +317,7 @@ namespace OpenSim.Services.GridService
320 if (rdata.RegionID != regionID) 317 if (rdata.RegionID != regionID)
321 { 318 {
322 int flags = Convert.ToInt32(rdata.Data["flags"]); 319 int flags = Convert.ToInt32(rdata.Data["flags"]);
323 if ((flags & (int)Framework.RegionFlags.Hyperlink) == 0) // no hyperlinks as neighbours 320 if ((flags & (int)Data.RegionFlags.Hyperlink) == 0) // no hyperlinks as neighbours
324 rinfos.Add(RegionData2RegionInfo(rdata)); 321 rinfos.Add(RegionData2RegionInfo(rdata));
325 } 322 }
326 } 323 }
@@ -470,7 +467,7 @@ namespace OpenSim.Services.GridService
470 467
471 foreach (RegionData r in regions) 468 foreach (RegionData r in regions)
472 { 469 {
473 if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Framework.RegionFlags.RegionOnline) != 0) 470 if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Data.RegionFlags.RegionOnline) != 0)
474 ret.Add(RegionData2RegionInfo(r)); 471 ret.Add(RegionData2RegionInfo(r));
475 } 472 }
476 473
@@ -486,7 +483,7 @@ namespace OpenSim.Services.GridService
486 483
487 foreach (RegionData r in regions) 484 foreach (RegionData r in regions)
488 { 485 {
489 if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Framework.RegionFlags.RegionOnline) != 0) 486 if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Data.RegionFlags.RegionOnline) != 0)
490 ret.Add(RegionData2RegionInfo(r)); 487 ret.Add(RegionData2RegionInfo(r));
491 } 488 }
492 489
@@ -502,7 +499,7 @@ namespace OpenSim.Services.GridService
502 499
503 foreach (RegionData r in regions) 500 foreach (RegionData r in regions)
504 { 501 {
505 if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Framework.RegionFlags.RegionOnline) != 0) 502 if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Data.RegionFlags.RegionOnline) != 0)
506 ret.Add(RegionData2RegionInfo(r)); 503 ret.Add(RegionData2RegionInfo(r));
507 } 504 }
508 505
@@ -629,7 +626,7 @@ namespace OpenSim.Services.GridService
629 626
630 private void OutputRegionToConsole(RegionData r) 627 private void OutputRegionToConsole(RegionData r)
631 { 628 {
632 OpenSim.Framework.RegionFlags flags = (OpenSim.Framework.RegionFlags)Convert.ToInt32(r.Data["flags"]); 629 OpenSim.Data.RegionFlags flags = (OpenSim.Data.RegionFlags)Convert.ToInt32(r.Data["flags"]);
633 630
634 ConsoleDisplayList dispList = new ConsoleDisplayList(); 631 ConsoleDisplayList dispList = new ConsoleDisplayList();
635 dispList.AddRow("Region Name", r.RegionName); 632 dispList.AddRow("Region Name", r.RegionName);
@@ -659,7 +656,7 @@ namespace OpenSim.Services.GridService
659 656
660 foreach (RegionData r in regions) 657 foreach (RegionData r in regions)
661 { 658 {
662 OpenSim.Framework.RegionFlags flags = (OpenSim.Framework.RegionFlags)Convert.ToInt32(r.Data["flags"]); 659 OpenSim.Data.RegionFlags flags = (OpenSim.Data.RegionFlags)Convert.ToInt32(r.Data["flags"]);
663 dispTable.AddRow( 660 dispTable.AddRow(
664 r.RegionName, 661 r.RegionName,
665 r.RegionID.ToString(), 662 r.RegionID.ToString(),
@@ -673,7 +670,7 @@ namespace OpenSim.Services.GridService
673 670
674 private int ParseFlags(int prev, string flags) 671 private int ParseFlags(int prev, string flags)
675 { 672 {
676 OpenSim.Framework.RegionFlags f = (OpenSim.Framework.RegionFlags)prev; 673 OpenSim.Data.RegionFlags f = (OpenSim.Data.RegionFlags)prev;
677 674
678 string[] parts = flags.Split(new char[] {',', ' '}, StringSplitOptions.RemoveEmptyEntries); 675 string[] parts = flags.Split(new char[] {',', ' '}, StringSplitOptions.RemoveEmptyEntries);
679 676
@@ -685,18 +682,18 @@ namespace OpenSim.Services.GridService
685 { 682 {
686 if (p.StartsWith("+")) 683 if (p.StartsWith("+"))
687 { 684 {
688 val = (int)Enum.Parse(typeof(OpenSim.Framework.RegionFlags), p.Substring(1)); 685 val = (int)Enum.Parse(typeof(OpenSim.Data.RegionFlags), p.Substring(1));
689 f |= (OpenSim.Framework.RegionFlags)val; 686 f |= (OpenSim.Data.RegionFlags)val;
690 } 687 }
691 else if (p.StartsWith("-")) 688 else if (p.StartsWith("-"))
692 { 689 {
693 val = (int)Enum.Parse(typeof(OpenSim.Framework.RegionFlags), p.Substring(1)); 690 val = (int)Enum.Parse(typeof(OpenSim.Data.RegionFlags), p.Substring(1));
694 f &= ~(OpenSim.Framework.RegionFlags)val; 691 f &= ~(OpenSim.Data.RegionFlags)val;
695 } 692 }
696 else 693 else
697 { 694 {
698 val = (int)Enum.Parse(typeof(OpenSim.Framework.RegionFlags), p); 695 val = (int)Enum.Parse(typeof(OpenSim.Data.RegionFlags), p);
699 f |= (OpenSim.Framework.RegionFlags)val; 696 f |= (OpenSim.Data.RegionFlags)val;
700 } 697 }
701 } 698 }
702 catch (Exception) 699 catch (Exception)
@@ -728,7 +725,7 @@ namespace OpenSim.Services.GridService
728 int flags = Convert.ToInt32(r.Data["flags"]); 725 int flags = Convert.ToInt32(r.Data["flags"]);
729 flags = ParseFlags(flags, cmd[4]); 726 flags = ParseFlags(flags, cmd[4]);
730 r.Data["flags"] = flags.ToString(); 727 r.Data["flags"] = flags.ToString();
731 OpenSim.Framework.RegionFlags f = (OpenSim.Framework.RegionFlags)flags; 728 OpenSim.Data.RegionFlags f = (OpenSim.Data.RegionFlags)flags;
732 729
733 MainConsole.Instance.Output(String.Format("Set region {0} to {1}", r.RegionName, f)); 730 MainConsole.Instance.Output(String.Format("Set region {0} to {1}", r.RegionName, f));
734 m_Database.Store(r); 731 m_Database.Store(r);
diff --git a/OpenSim/Services/GridService/HypergridLinker.cs b/OpenSim/Services/GridService/HypergridLinker.cs
index 743d089..78eab3d 100644
--- a/OpenSim/Services/GridService/HypergridLinker.cs
+++ b/OpenSim/Services/GridService/HypergridLinker.cs
@@ -390,8 +390,8 @@ namespace OpenSim.Services.GridService
390 List<RegionData> regions = m_Database.Get(mapName, m_ScopeID); 390 List<RegionData> regions = m_Database.Get(mapName, m_ScopeID);
391 if (regions != null && regions.Count > 0) 391 if (regions != null && regions.Count > 0)
392 { 392 {
393 OpenSim.Framework.RegionFlags rflags = (OpenSim.Framework.RegionFlags)Convert.ToInt32(regions[0].Data["flags"]); 393 OpenSim.Data.RegionFlags rflags = (OpenSim.Data.RegionFlags)Convert.ToInt32(regions[0].Data["flags"]);
394 if ((rflags & OpenSim.Framework.RegionFlags.Hyperlink) != 0) 394 if ((rflags & OpenSim.Data.RegionFlags.Hyperlink) != 0)
395 { 395 {
396 regInfo = new GridRegion(); 396 regInfo = new GridRegion();
397 regInfo.RegionID = regions[0].RegionID; 397 regInfo.RegionID = regions[0].RegionID;
@@ -460,7 +460,7 @@ namespace OpenSim.Services.GridService
460 private void AddHyperlinkRegion(GridRegion regionInfo, ulong regionHandle) 460 private void AddHyperlinkRegion(GridRegion regionInfo, ulong regionHandle)
461 { 461 {
462 RegionData rdata = m_GridService.RegionInfo2RegionData(regionInfo); 462 RegionData rdata = m_GridService.RegionInfo2RegionData(regionInfo);
463 int flags = (int)OpenSim.Framework.RegionFlags.Hyperlink + (int)OpenSim.Framework.RegionFlags.NoDirectLogin + (int)OpenSim.Framework.RegionFlags.RegionOnline; 463 int flags = (int)OpenSim.Data.RegionFlags.Hyperlink + (int)OpenSim.Data.RegionFlags.NoDirectLogin + (int)OpenSim.Data.RegionFlags.RegionOnline;
464 rdata.Data["flags"] = flags.ToString(); 464 rdata.Data["flags"] = flags.ToString();
465 465
466 m_Database.Store(rdata); 466 m_Database.Store(rdata);
diff --git a/OpenSim/Services/HypergridService/GatekeeperService.cs b/OpenSim/Services/HypergridService/GatekeeperService.cs
index 004311f..47d22b9 100644
--- a/OpenSim/Services/HypergridService/GatekeeperService.cs
+++ b/OpenSim/Services/HypergridService/GatekeeperService.cs
@@ -57,13 +57,10 @@ namespace OpenSim.Services.HypergridService
57 private static IUserAccountService m_UserAccountService; 57 private static IUserAccountService m_UserAccountService;
58 private static IUserAgentService m_UserAgentService; 58 private static IUserAgentService m_UserAgentService;
59 private static ISimulationService m_SimulationService; 59 private static ISimulationService m_SimulationService;
60 private static IGridUserService m_GridUserService;
61 60
62 private static string m_AllowedClients = string.Empty; 61 protected string m_AllowedClients = string.Empty;
63 private static string m_DeniedClients = string.Empty; 62 protected string m_DeniedClients = string.Empty;
64 private static bool m_ForeignAgentsAllowed = true; 63 private static bool m_ForeignAgentsAllowed = true;
65 private static List<string> m_ForeignsAllowedExceptions = new List<string>();
66 private static List<string> m_ForeignsDisallowedExceptions = new List<string>();
67 64
68 private static UUID m_ScopeID; 65 private static UUID m_ScopeID;
69 private static bool m_AllowTeleportsToAnyRegion; 66 private static bool m_AllowTeleportsToAnyRegion;
@@ -85,9 +82,8 @@ namespace OpenSim.Services.HypergridService
85 string gridService = serverConfig.GetString("GridService", String.Empty); 82 string gridService = serverConfig.GetString("GridService", String.Empty);
86 string presenceService = serverConfig.GetString("PresenceService", String.Empty); 83 string presenceService = serverConfig.GetString("PresenceService", String.Empty);
87 string simulationService = serverConfig.GetString("SimulationService", String.Empty); 84 string simulationService = serverConfig.GetString("SimulationService", String.Empty);
88 string gridUserService = serverConfig.GetString("GridUserService", String.Empty);
89 85
90 // These are mandatory, the others aren't 86 // These 3 are mandatory, the others aren't
91 if (gridService == string.Empty || presenceService == string.Empty) 87 if (gridService == string.Empty || presenceService == string.Empty)
92 throw new Exception("Incomplete specifications, Gatekeeper Service cannot function."); 88 throw new Exception("Incomplete specifications, Gatekeeper Service cannot function.");
93 89
@@ -107,8 +103,6 @@ namespace OpenSim.Services.HypergridService
107 m_UserAccountService = ServerUtils.LoadPlugin<IUserAccountService>(accountService, args); 103 m_UserAccountService = ServerUtils.LoadPlugin<IUserAccountService>(accountService, args);
108 if (homeUsersService != string.Empty) 104 if (homeUsersService != string.Empty)
109 m_UserAgentService = ServerUtils.LoadPlugin<IUserAgentService>(homeUsersService, args); 105 m_UserAgentService = ServerUtils.LoadPlugin<IUserAgentService>(homeUsersService, args);
110 if (gridUserService != string.Empty)
111 m_GridUserService = ServerUtils.LoadPlugin<IGridUserService>(gridUserService, args);
112 106
113 if (simService != null) 107 if (simService != null)
114 m_SimulationService = simService; 108 m_SimulationService = simService;
@@ -119,9 +113,6 @@ namespace OpenSim.Services.HypergridService
119 m_DeniedClients = serverConfig.GetString("DeniedClients", string.Empty); 113 m_DeniedClients = serverConfig.GetString("DeniedClients", string.Empty);
120 m_ForeignAgentsAllowed = serverConfig.GetBoolean("ForeignAgentsAllowed", true); 114 m_ForeignAgentsAllowed = serverConfig.GetBoolean("ForeignAgentsAllowed", true);
121 115
122 LoadDomainExceptionsFromConfig(serverConfig, "AllowExcept", m_ForeignsAllowedExceptions);
123 LoadDomainExceptionsFromConfig(serverConfig, "DisallowExcept", m_ForeignsDisallowedExceptions);
124
125 if (m_GridService == null || m_PresenceService == null || m_SimulationService == null) 116 if (m_GridService == null || m_PresenceService == null || m_SimulationService == null)
126 throw new Exception("Unable to load a required plugin, Gatekeeper Service cannot function."); 117 throw new Exception("Unable to load a required plugin, Gatekeeper Service cannot function.");
127 118
@@ -134,15 +125,6 @@ namespace OpenSim.Services.HypergridService
134 { 125 {
135 } 126 }
136 127
137 protected void LoadDomainExceptionsFromConfig(IConfig config, string variable, List<string> exceptions)
138 {
139 string value = config.GetString(variable, string.Empty);
140 string[] parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
141
142 foreach (string s in parts)
143 exceptions.Add(s.Trim());
144 }
145
146 public bool LinkRegion(string regionName, out UUID regionID, out ulong regionHandle, out string externalName, out string imageURL, out string reason) 128 public bool LinkRegion(string regionName, out UUID regionID, out ulong regionHandle, out string externalName, out string imageURL, out string reason)
147 { 129 {
148 regionID = UUID.Zero; 130 regionID = UUID.Zero;
@@ -278,27 +260,18 @@ namespace OpenSim.Services.HypergridService
278 m_log.DebugFormat("[GATEKEEPER SERVICE]: User is ok"); 260 m_log.DebugFormat("[GATEKEEPER SERVICE]: User is ok");
279 261
280 // 262 //
281 // Foreign agents allowed? Exceptions? 263 // Foreign agents allowed
282 // 264 //
283 if (account == null) 265 if (account == null && !m_ForeignAgentsAllowed)
284 { 266 {
285 bool allowed = m_ForeignAgentsAllowed; 267 reason = "Unauthorized";
286 268 m_log.InfoFormat("[GATEKEEPER SERVICE]: Foreign agents are not permitted {0} {1}. Refusing service.",
287 if (m_ForeignAgentsAllowed && IsException(aCircuit, m_ForeignsAllowedExceptions)) 269 aCircuit.firstname, aCircuit.lastname);
288 allowed = false; 270 return false;
289
290 if (!m_ForeignAgentsAllowed && IsException(aCircuit, m_ForeignsDisallowedExceptions))
291 allowed = true;
292
293 if (!allowed)
294 {
295 reason = "Destination does not allow visitors from your world";
296 m_log.InfoFormat("[GATEKEEPER SERVICE]: Foreign agents are not permitted {0} {1} @ {2}. Refusing service.",
297 aCircuit.firstname, aCircuit.lastname, aCircuit.ServiceURLs["HomeURI"]);
298 return false;
299 }
300 } 271 }
301 272
273 // May want to authorize
274
302 bool isFirstLogin = false; 275 bool isFirstLogin = false;
303 // 276 //
304 // Login the presence, if it's not there yet (by the login service) 277 // Login the presence, if it's not there yet (by the login service)
@@ -307,8 +280,7 @@ namespace OpenSim.Services.HypergridService
307 if (presence != null) // it has been placed there by the login service 280 if (presence != null) // it has been placed there by the login service
308 isFirstLogin = true; 281 isFirstLogin = true;
309 282
310 else 283 else
311 {
312 if (!m_PresenceService.LoginAgent(aCircuit.AgentID.ToString(), aCircuit.SessionID, aCircuit.SecureSessionID)) 284 if (!m_PresenceService.LoginAgent(aCircuit.AgentID.ToString(), aCircuit.SessionID, aCircuit.SecureSessionID))
313 { 285 {
314 reason = "Unable to login presence"; 286 reason = "Unable to login presence";
@@ -318,26 +290,6 @@ namespace OpenSim.Services.HypergridService
318 } 290 }
319 m_log.DebugFormat("[GATEKEEPER SERVICE]: Login presence ok"); 291 m_log.DebugFormat("[GATEKEEPER SERVICE]: Login presence ok");
320 292
321 // Also login foreigners with GridUser service
322 if (m_GridUserService != null && account == null)
323 {
324 string userId = aCircuit.AgentID.ToString();
325 string first = aCircuit.firstname, last = aCircuit.lastname;
326 if (last.StartsWith("@"))
327 {
328 string[] parts = aCircuit.firstname.Split('.');
329 if (parts.Length >= 2)
330 {
331 first = parts[0];
332 last = parts[1];
333 }
334 }
335
336 userId += ";" + aCircuit.ServiceURLs["HomeURI"] + ";" + first + " " + last;
337 m_GridUserService.LoggedIn(userId);
338 }
339 }
340
341 // 293 //
342 // Get the region 294 // Get the region
343 // 295 //
@@ -441,27 +393,6 @@ namespace OpenSim.Services.HypergridService
441 393
442 #region Misc 394 #region Misc
443 395
444 private bool IsException(AgentCircuitData aCircuit, List<string> exceptions)
445 {
446 bool exception = false;
447 if (exceptions.Count > 0) // we have exceptions
448 {
449 // Retrieve the visitor's origin
450 string userURL = aCircuit.ServiceURLs["HomeURI"].ToString();
451 if (!userURL.EndsWith("/"))
452 userURL += "/";
453
454 if (exceptions.Find(delegate(string s)
455 {
456 if (!s.EndsWith("/"))
457 s += "/";
458 return s == userURL;
459 }) != null)
460 exception = true;
461 }
462
463 return exception;
464 }
465 396
466 #endregion 397 #endregion
467 } 398 }
diff --git a/OpenSim/Services/HypergridService/HGAssetService.cs b/OpenSim/Services/HypergridService/HGAssetService.cs
index 84dec8d..db98166 100644
--- a/OpenSim/Services/HypergridService/HGAssetService.cs
+++ b/OpenSim/Services/HypergridService/HGAssetService.cs
@@ -58,8 +58,6 @@ namespace OpenSim.Services.HypergridService
58 58
59 private UserAccountCache m_Cache; 59 private UserAccountCache m_Cache;
60 60
61 private AssetPermissions m_AssetPerms;
62
63 public HGAssetService(IConfigSource config, string configName) : base(config, configName) 61 public HGAssetService(IConfigSource config, string configName) : base(config, configName)
64 { 62 {
65 m_log.Debug("[HGAsset Service]: Starting"); 63 m_log.Debug("[HGAsset Service]: Starting");
@@ -82,10 +80,6 @@ namespace OpenSim.Services.HypergridService
82 m_HomeURL = assetConfig.GetString("HomeURI", m_HomeURL); 80 m_HomeURL = assetConfig.GetString("HomeURI", m_HomeURL);
83 81
84 m_Cache = UserAccountCache.CreateUserAccountCache(m_UserAccountService); 82 m_Cache = UserAccountCache.CreateUserAccountCache(m_UserAccountService);
85
86 // Permissions
87 m_AssetPerms = new AssetPermissions(assetConfig);
88
89 } 83 }
90 84
91 #region IAssetService overrides 85 #region IAssetService overrides
@@ -96,9 +90,6 @@ namespace OpenSim.Services.HypergridService
96 if (asset == null) 90 if (asset == null)
97 return null; 91 return null;
98 92
99 if (!m_AssetPerms.AllowedExport(asset.Type))
100 return null;
101
102 if (asset.Metadata.Type == (sbyte)AssetType.Object) 93 if (asset.Metadata.Type == (sbyte)AssetType.Object)
103 asset.Data = AdjustIdentifiers(asset.Data); ; 94 asset.Data = AdjustIdentifiers(asset.Data); ;
104 95
@@ -121,27 +112,16 @@ namespace OpenSim.Services.HypergridService
121 112
122 public override byte[] GetData(string id) 113 public override byte[] GetData(string id)
123 { 114 {
124 AssetBase asset = Get(id); 115 byte[] data = base.GetData(id);
125
126 if (asset == null)
127 return null;
128 116
129 if (!m_AssetPerms.AllowedExport(asset.Type)) 117 if (data == null)
130 return null; 118 return null;
131 119
132 return asset.Data; 120 return AdjustIdentifiers(data);
133 } 121 }
134 122
135 //public virtual bool Get(string id, Object sender, AssetRetrieved handler) 123 //public virtual bool Get(string id, Object sender, AssetRetrieved handler)
136 124
137 public override string Store(AssetBase asset)
138 {
139 if (!m_AssetPerms.AllowedImport(asset.Type))
140 return string.Empty;
141
142 return base.Store(asset);
143 }
144
145 public override bool Delete(string id) 125 public override bool Delete(string id)
146 { 126 {
147 // NOGO 127 // NOGO
diff --git a/OpenSim/Services/HypergridService/HGFriendsService.cs b/OpenSim/Services/HypergridService/HGFriendsService.cs
index a8bcfb2..98423d7 100644
--- a/OpenSim/Services/HypergridService/HGFriendsService.cs
+++ b/OpenSim/Services/HypergridService/HGFriendsService.cs
@@ -397,7 +397,7 @@ namespace OpenSim.Services.HypergridService
397 if (region != null) 397 if (region != null)
398 { 398 {
399 m_log.DebugFormat("[HGFRIENDS SERVICE]: Remote Notify to region {0}, user {1} is {2}", region.RegionName, foreignUserID, (online ? "online" : "offline")); 399 m_log.DebugFormat("[HGFRIENDS SERVICE]: Remote Notify to region {0}, user {1} is {2}", region.RegionName, foreignUserID, (online ? "online" : "offline"));
400 m_FriendsSimConnector.StatusNotify(region, foreignUserID, userID.ToString(), online); 400 m_FriendsSimConnector.StatusNotify(region, foreignUserID, userID, online);
401 } 401 }
402 } 402 }
403 } 403 }
diff --git a/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs b/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs
index 784f136..6e4b68c 100644
--- a/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs
+++ b/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs
@@ -56,12 +56,10 @@ namespace OpenSim.Services.HypergridService
56 56
57 private string m_HomeURL; 57 private string m_HomeURL;
58 private IUserAccountService m_UserAccountService; 58 private IUserAccountService m_UserAccountService;
59 private IAvatarService m_AvatarService;
60 59
61// private UserAccountCache m_Cache; 60// private UserAccountCache m_Cache;
62 61
63 private ExpiringCache<UUID, List<XInventoryFolder>> m_SuitcaseTrees = new ExpiringCache<UUID, List<XInventoryFolder>>(); 62 private ExpiringCache<UUID, List<XInventoryFolder>> m_SuitcaseTrees = new ExpiringCache<UUID, List<XInventoryFolder>>();
64 private ExpiringCache<UUID, AvatarAppearance> m_Appearances = new ExpiringCache<UUID, AvatarAppearance>();
65 63
66 public HGSuitcaseInventoryService(IConfigSource config, string configName) 64 public HGSuitcaseInventoryService(IConfigSource config, string configName)
67 : base(config, configName) 65 : base(config, configName)
@@ -71,7 +69,7 @@ namespace OpenSim.Services.HypergridService
71 m_ConfigName = configName; 69 m_ConfigName = configName;
72 70
73 if (m_Database == null) 71 if (m_Database == null)
74 m_log.ErrorFormat("[HG SUITCASE INVENTORY SERVICE]: m_Database is null!"); 72 m_log.WarnFormat("[XXX]: m_Database is null!");
75 73
76 // 74 //
77 // Try reading the [InventoryService] section, if it exists 75 // Try reading the [InventoryService] section, if it exists
@@ -79,6 +77,7 @@ namespace OpenSim.Services.HypergridService
79 IConfig invConfig = config.Configs[m_ConfigName]; 77 IConfig invConfig = config.Configs[m_ConfigName];
80 if (invConfig != null) 78 if (invConfig != null)
81 { 79 {
80 // realm = authConfig.GetString("Realm", realm);
82 string userAccountsDll = invConfig.GetString("UserAccountsService", string.Empty); 81 string userAccountsDll = invConfig.GetString("UserAccountsService", string.Empty);
83 if (userAccountsDll == string.Empty) 82 if (userAccountsDll == string.Empty)
84 throw new Exception("Please specify UserAccountsService in HGInventoryService configuration"); 83 throw new Exception("Please specify UserAccountsService in HGInventoryService configuration");
@@ -88,14 +87,8 @@ namespace OpenSim.Services.HypergridService
88 if (m_UserAccountService == null) 87 if (m_UserAccountService == null)
89 throw new Exception(String.Format("Unable to create UserAccountService from {0}", userAccountsDll)); 88 throw new Exception(String.Format("Unable to create UserAccountService from {0}", userAccountsDll));
90 89
91 string avatarDll = invConfig.GetString("AvatarService", string.Empty); 90 // legacy configuration [obsolete]
92 if (avatarDll == string.Empty) 91 m_HomeURL = invConfig.GetString("ProfileServerURI", string.Empty);
93 throw new Exception("Please specify AvatarService in HGInventoryService configuration");
94
95 m_AvatarService = ServerUtils.LoadPlugin<IAvatarService>(avatarDll, args);
96 if (m_AvatarService == null)
97 throw new Exception(String.Format("Unable to create m_AvatarService from {0}", avatarDll));
98
99 // Preferred 92 // Preferred
100 m_HomeURL = invConfig.GetString("HomeURI", m_HomeURL); 93 m_HomeURL = invConfig.GetString("HomeURI", m_HomeURL);
101 94
@@ -301,7 +294,7 @@ namespace OpenSim.Services.HypergridService
301 294
302 public override bool AddFolder(InventoryFolderBase folder) 295 public override bool AddFolder(InventoryFolderBase folder)
303 { 296 {
304 //m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: AddFolder {0} {1}", folder.Name, folder.ParentID); 297 m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: AddFolder {0} {1}", folder.Name, folder.ParentID);
305 // Let's do a bit of sanity checking, more than the base service does 298 // Let's do a bit of sanity checking, more than the base service does
306 // make sure the given folder's parent folder exists under the suitcase tree of this user 299 // make sure the given folder's parent folder exists under the suitcase tree of this user
307 300
@@ -323,7 +316,7 @@ namespace OpenSim.Services.HypergridService
323 316
324 public override bool UpdateFolder(InventoryFolderBase folder) 317 public override bool UpdateFolder(InventoryFolderBase folder)
325 { 318 {
326 //m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Update folder {0}, version {1}", folder.ID, folder.Version); 319 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Update folder {0}, version {1}", folder.ID, folder.Version);
327 if (!IsWithinSuitcaseTree(folder.Owner, folder.ID)) 320 if (!IsWithinSuitcaseTree(folder.Owner, folder.ID))
328 { 321 {
329 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: folder {0} not within Suitcase tree", folder.Name); 322 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: folder {0} not within Suitcase tree", folder.Name);
@@ -401,7 +394,7 @@ namespace OpenSim.Services.HypergridService
401 return null; 394 return null;
402 } 395 }
403 396
404 if (!IsWithinSuitcaseTree(it.Owner, it.Folder) && !IsPartOfAppearance(it.Owner, it.ID)) 397 if (!IsWithinSuitcaseTree(it.Owner, it.Folder))
405 { 398 {
406 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Item {0} (folder {1}) is not within Suitcase", 399 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Item {0} (folder {1}) is not within Suitcase",
407 it.Name, it.Folder); 400 it.Name, it.Folder);
@@ -460,15 +453,6 @@ namespace OpenSim.Services.HypergridService
460 453
461 if (folders != null && folders.Length > 0) 454 if (folders != null && folders.Length > 0)
462 return folders[0]; 455 return folders[0];
463
464 // OK, so the RootFolder type didn't work. Let's look for any type with parent UUID.Zero.
465 folders = m_Database.GetFolders(
466 new string[] { "agentID", "folderName", "parentFolderID" },
467 new string[] { principalID.ToString(), "My Inventory", UUID.Zero.ToString() });
468
469 if (folders != null && folders.Length > 0)
470 return folders[0];
471
472 return null; 456 return null;
473 } 457 }
474 458
@@ -565,52 +549,6 @@ namespace OpenSim.Services.HypergridService
565 else return true; 549 else return true;
566 } 550 }
567 #endregion 551 #endregion
568
569 #region Avatar Appearance
570
571 private AvatarAppearance GetAppearance(UUID principalID)
572 {
573 AvatarAppearance a = null;
574 if (m_Appearances.TryGetValue(principalID, out a))
575 return a;
576
577 a = m_AvatarService.GetAppearance(principalID);
578 m_Appearances.AddOrUpdate(principalID, a, 5 * 60); // 5minutes
579 return a;
580 }
581
582 private bool IsPartOfAppearance(UUID principalID, UUID itemID)
583 {
584 AvatarAppearance a = GetAppearance(principalID);
585
586 if (a == null)
587 return false;
588
589 // Check wearables (body parts and clothes)
590 for (int i = 0; i < a.Wearables.Length; i++)
591 {
592 for (int j = 0; j < a.Wearables[i].Count; j++)
593 {
594 if (a.Wearables[i][j].ItemID == itemID)
595 {
596 //m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: item {0} is a wearable", itemID);
597 return true;
598 }
599 }
600 }
601
602 // Check attachments
603 if (a.GetAttachmentForItem(itemID) != null)
604 {
605 //m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: item {0} is an attachment", itemID);
606 return true;
607 }
608
609 return false;
610 }
611
612 #endregion
613
614 } 552 }
615 553
616} 554}
diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs
index 416ad16..a49993c 100644
--- a/OpenSim/Services/HypergridService/UserAgentService.cs
+++ b/OpenSim/Services/HypergridService/UserAgentService.cs
@@ -77,10 +77,6 @@ namespace OpenSim.Services.HypergridService
77 77
78 protected static bool m_BypassClientVerification; 78 protected static bool m_BypassClientVerification;
79 79
80 private static Dictionary<int, bool> m_ForeignTripsAllowed = new Dictionary<int, bool>();
81 private static Dictionary<int, List<string>> m_TripsAllowedExceptions = new Dictionary<int, List<string>>();
82 private static Dictionary<int, List<string>> m_TripsDisallowedExceptions = new Dictionary<int, List<string>>();
83
84 public UserAgentService(IConfigSource config) : this(config, null) 80 public UserAgentService(IConfigSource config) : this(config, null)
85 { 81 {
86 } 82 }
@@ -125,12 +121,6 @@ namespace OpenSim.Services.HypergridService
125 m_PresenceService = ServerUtils.LoadPlugin<IPresenceService>(presenceService, args); 121 m_PresenceService = ServerUtils.LoadPlugin<IPresenceService>(presenceService, args);
126 m_UserAccountService = ServerUtils.LoadPlugin<IUserAccountService>(userAccountService, args); 122 m_UserAccountService = ServerUtils.LoadPlugin<IUserAccountService>(userAccountService, args);
127 123
128 m_LevelOutsideContacts = serverConfig.GetInt("LevelOutsideContacts", 0);
129
130 LoadTripPermissionsFromConfig(serverConfig, "ForeignTripsAllowed");
131 LoadDomainExceptionsFromConfig(serverConfig, "AllowExcept", m_TripsAllowedExceptions);
132 LoadDomainExceptionsFromConfig(serverConfig, "DisallowExcept", m_TripsDisallowedExceptions);
133
134 m_GridName = serverConfig.GetString("ExternalName", string.Empty); 124 m_GridName = serverConfig.GetString("ExternalName", string.Empty);
135 if (m_GridName == string.Empty) 125 if (m_GridName == string.Empty)
136 { 126 {
@@ -140,43 +130,10 @@ namespace OpenSim.Services.HypergridService
140 if (!m_GridName.EndsWith("/")) 130 if (!m_GridName.EndsWith("/"))
141 m_GridName = m_GridName + "/"; 131 m_GridName = m_GridName + "/";
142 132
133 m_LevelOutsideContacts = serverConfig.GetInt("LevelOutsideContacts", 0);
143 } 134 }
144 } 135 }
145 136
146 protected void LoadTripPermissionsFromConfig(IConfig config, string variable)
147 {
148 foreach (string keyName in config.GetKeys())
149 {
150 if (keyName.StartsWith(variable + "_Level_"))
151 {
152 int level = 0;
153 if (Int32.TryParse(keyName.Replace(variable + "_Level_", ""), out level))
154 m_ForeignTripsAllowed.Add(level, config.GetBoolean(keyName, true));
155 }
156 }
157 }
158
159 protected void LoadDomainExceptionsFromConfig(IConfig config, string variable, Dictionary<int, List<string>> exceptions)
160 {
161 foreach (string keyName in config.GetKeys())
162 {
163 if (keyName.StartsWith(variable + "_Level_"))
164 {
165 int level = 0;
166 if (Int32.TryParse(keyName.Replace(variable + "_Level_", ""), out level) && !exceptions.ContainsKey(level))
167 {
168 exceptions.Add(level, new List<string>());
169 string value = config.GetString(keyName, string.Empty);
170 string[] parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
171
172 foreach (string s in parts)
173 exceptions[level].Add(s.Trim());
174 }
175 }
176 }
177 }
178
179
180 public GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt) 137 public GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt)
181 { 138 {
182 position = new Vector3(128, 128, 0); lookAt = Vector3.UnitY; 139 position = new Vector3(128, 128, 0); lookAt = Vector3.UnitY;
@@ -209,39 +166,13 @@ namespace OpenSim.Services.HypergridService
209 m_log.DebugFormat("[USER AGENT SERVICE]: Request to login user {0} {1} (@{2}) to grid {3}", 166 m_log.DebugFormat("[USER AGENT SERVICE]: Request to login user {0} {1} (@{2}) to grid {3}",
210 agentCircuit.firstname, agentCircuit.lastname, ((clientIP == null) ? "stored IP" : clientIP.Address.ToString()), gatekeeper.ServerURI); 167 agentCircuit.firstname, agentCircuit.lastname, ((clientIP == null) ? "stored IP" : clientIP.Address.ToString()), gatekeeper.ServerURI);
211 168
212 string gridName = gatekeeper.ServerURI; 169 if (m_UserAccountService.GetUserAccount(UUID.Zero, agentCircuit.AgentID) == null)
213
214 UserAccount account = m_UserAccountService.GetUserAccount(UUID.Zero, agentCircuit.AgentID);
215 if (account == null)
216 { 170 {
217 m_log.WarnFormat("[USER AGENT SERVICE]: Someone attempted to lauch a foreign user from here {0} {1}", agentCircuit.firstname, agentCircuit.lastname); 171 m_log.WarnFormat("[USER AGENT SERVICE]: Someone attempted to lauch a foreign user from here {0} {1}", agentCircuit.firstname, agentCircuit.lastname);
218 reason = "Forbidden to launch your agents from here"; 172 reason = "Forbidden to launch your agents from here";
219 return false; 173 return false;
220 } 174 }
221 175
222 // Is this user allowed to go there?
223 if (m_GridName != gridName)
224 {
225 if (m_ForeignTripsAllowed.ContainsKey(account.UserLevel))
226 {
227 bool allowed = m_ForeignTripsAllowed[account.UserLevel];
228
229 if (m_ForeignTripsAllowed[account.UserLevel] && IsException(gridName, account.UserLevel, m_TripsAllowedExceptions))
230 allowed = false;
231
232 if (!m_ForeignTripsAllowed[account.UserLevel] && IsException(gridName, account.UserLevel, m_TripsDisallowedExceptions))
233 allowed = true;
234
235 if (!allowed)
236 {
237 reason = "Your world does not allow you to visit the destination";
238 m_log.InfoFormat("[USER AGENT SERVICE]: Agents not permitted to visit {0}. Refusing service.", gridName);
239 return false;
240 }
241 }
242 }
243
244
245 // Take the IP address + port of the gatekeeper (reg) plus the info of finalDestination 176 // Take the IP address + port of the gatekeeper (reg) plus the info of finalDestination
246 GridRegion region = new GridRegion(gatekeeper); 177 GridRegion region = new GridRegion(gatekeeper);
247 region.ServerURI = gatekeeper.ServerURI; 178 region.ServerURI = gatekeeper.ServerURI;
@@ -258,6 +189,7 @@ namespace OpenSim.Services.HypergridService
258 189
259 bool success = false; 190 bool success = false;
260 string myExternalIP = string.Empty; 191 string myExternalIP = string.Empty;
192 string gridName = gatekeeper.ServerURI;
261 193
262 m_log.DebugFormat("[USER AGENT SERVICE]: this grid: {0}, desired grid: {1}", m_GridName, gridName); 194 m_log.DebugFormat("[USER AGENT SERVICE]: this grid: {0}, desired grid: {1}", m_GridName, gridName);
263 195
@@ -502,7 +434,7 @@ namespace OpenSim.Services.HypergridService
502 if (region != null) 434 if (region != null)
503 { 435 {
504 m_log.DebugFormat("[USER AGENT SERVICE]: Remote Notify to region {0}, user {1} is {2}", region.RegionName, foreignUserID, (online ? "online" : "offline")); 436 m_log.DebugFormat("[USER AGENT SERVICE]: Remote Notify to region {0}, user {1} is {2}", region.RegionName, foreignUserID, (online ? "online" : "offline"));
505 m_FriendsSimConnector.StatusNotify(region, foreignUserID, userID.ToString(), online); 437 m_FriendsSimConnector.StatusNotify(region, foreignUserID, userID, online);
506 } 438 }
507 } 439 }
508 } 440 }
@@ -654,35 +586,6 @@ namespace OpenSim.Services.HypergridService
654 else 586 else
655 return UUID.Zero; 587 return UUID.Zero;
656 } 588 }
657
658 #region Misc
659
660 private bool IsException(string dest, int level, Dictionary<int, List<string>> exceptions)
661 {
662 if (!exceptions.ContainsKey(level))
663 return false;
664
665 bool exception = false;
666 if (exceptions[level].Count > 0) // we have exceptions
667 {
668 string destination = dest;
669 if (!destination.EndsWith("/"))
670 destination += "/";
671
672 if (exceptions[level].Find(delegate(string s)
673 {
674 if (!s.EndsWith("/"))
675 s += "/";
676 return s == destination;
677 }) != null)
678 exception = true;
679 }
680
681 return exception;
682 }
683
684 #endregion
685
686 } 589 }
687 590
688 class TravelingAgentInfo 591 class TravelingAgentInfo
diff --git a/OpenSim/Services/Interfaces/IAssetService.cs b/OpenSim/Services/Interfaces/IAssetService.cs
index 3c469c6..80494f1 100644
--- a/OpenSim/Services/Interfaces/IAssetService.cs
+++ b/OpenSim/Services/Interfaces/IAssetService.cs
@@ -68,11 +68,7 @@ namespace OpenSim.Services.Interfaces
68 /// </summary> 68 /// </summary>
69 /// <param name="id">The asset id</param> 69 /// <param name="id">The asset id</param>
70 /// <param name="sender">Represents the requester. Passed back via the handler</param> 70 /// <param name="sender">Represents the requester. Passed back via the handler</param>
71 /// <param name="handler"> 71 /// <param name="handler">The handler to call back once the asset has been retrieved</param>
72 /// The handler to call back once the asset has been retrieved. This will be called back with a null AssetBase
73 /// if the asset could not be found for some reason (e.g. if it does not exist, if a remote asset service
74 /// was not contactable, if it is not in the database, etc.).
75 /// </param>
76 /// <returns>True if the id was parseable, false otherwise</returns> 72 /// <returns>True if the id was parseable, false otherwise</returns>
77 bool Get(string id, Object sender, AssetRetrieved handler); 73 bool Get(string id, Object sender, AssetRetrieved handler);
78 74
diff --git a/OpenSim/Services/Interfaces/IGridService.cs b/OpenSim/Services/Interfaces/IGridService.cs
index 3f4c958..cdcb961 100644
--- a/OpenSim/Services/Interfaces/IGridService.cs
+++ b/OpenSim/Services/Interfaces/IGridService.cs
@@ -100,19 +100,6 @@ namespace OpenSim.Services.Interfaces
100 List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y); 100 List<GridRegion> GetFallbackRegions(UUID scopeID, int x, int y);
101 List<GridRegion> GetHyperlinks(UUID scopeID); 101 List<GridRegion> GetHyperlinks(UUID scopeID);
102 102
103 /// <summary>
104 /// Get internal OpenSimulator region flags.
105 /// </summary>
106 /// <remarks>
107 /// See OpenSimulator.Framework.RegionFlags. These are not returned in the GridRegion structure -
108 /// they currently need to be requested separately. Possibly this should change to avoid multiple service calls
109 /// in some situations.
110 /// </remarks>
111 /// <returns>
112 /// The region flags.
113 /// </returns>
114 /// <param name='scopeID'></param>
115 /// <param name='regionID'></param>
116 int GetRegionFlags(UUID scopeID, UUID regionID); 103 int GetRegionFlags(UUID scopeID, UUID regionID);
117 } 104 }
118 105
diff --git a/OpenSim/Services/Interfaces/IGridUserService.cs b/OpenSim/Services/Interfaces/IGridUserService.cs
index 2e7237e..0a52bfa 100644
--- a/OpenSim/Services/Interfaces/IGridUserService.cs
+++ b/OpenSim/Services/Interfaces/IGridUserService.cs
@@ -80,7 +80,7 @@ namespace OpenSim.Services.Interfaces
80 80
81 } 81 }
82 82
83 public virtual Dictionary<string, object> ToKeyValuePairs() 83 public Dictionary<string, object> ToKeyValuePairs()
84 { 84 {
85 Dictionary<string, object> result = new Dictionary<string, object>(); 85 Dictionary<string, object> result = new Dictionary<string, object>();
86 result["UserID"] = UserID; 86 result["UserID"] = UserID;
@@ -96,6 +96,7 @@ namespace OpenSim.Services.Interfaces
96 result["Online"] = Online.ToString(); 96 result["Online"] = Online.ToString();
97 result["Login"] = Login.ToString(); 97 result["Login"] = Login.ToString();
98 result["Logout"] = Logout.ToString(); 98 result["Logout"] = Logout.ToString();
99
99 100
100 return result; 101 return result;
101 } 102 }
diff --git a/OpenSim/Services/Interfaces/IPresenceService.cs b/OpenSim/Services/Interfaces/IPresenceService.cs
index 90f9842..8d583ff 100644
--- a/OpenSim/Services/Interfaces/IPresenceService.cs
+++ b/OpenSim/Services/Interfaces/IPresenceService.cs
@@ -61,49 +61,13 @@ namespace OpenSim.Services.Interfaces
61 61
62 public interface IPresenceService 62 public interface IPresenceService
63 { 63 {
64 /// <summary>
65 /// Store session information.
66 /// </summary>
67 /// <returns>/returns>
68 /// <param name='userID'></param>
69 /// <param name='sessionID'></param>
70 /// <param name='secureSessionID'></param>
71 bool LoginAgent(string userID, UUID sessionID, UUID secureSessionID); 64 bool LoginAgent(string userID, UUID sessionID, UUID secureSessionID);
72
73 /// <summary>
74 /// Remove session information.
75 /// </summary>
76 /// <returns></returns>
77 /// <param name='sessionID'></param>
78 bool LogoutAgent(UUID sessionID); 65 bool LogoutAgent(UUID sessionID);
79
80 /// <summary>
81 /// Remove session information for all agents in the given region.
82 /// </summary>
83 /// <returns></returns>
84 /// <param name='regionID'></param>
85 bool LogoutRegionAgents(UUID regionID); 66 bool LogoutRegionAgents(UUID regionID);
86 67
87 /// <summary>
88 /// Update data for an existing session.
89 /// </summary>
90 /// <returns></returns>
91 /// <param name='sessionID'></param>
92 /// <param name='regionID'></param>
93 bool ReportAgent(UUID sessionID, UUID regionID); 68 bool ReportAgent(UUID sessionID, UUID regionID);
94 69
95 /// <summary>
96 /// Get session information for a given session ID.
97 /// </summary>
98 /// <returns></returns>
99 /// <param name='sessionID'></param>
100 PresenceInfo GetAgent(UUID sessionID); 70 PresenceInfo GetAgent(UUID sessionID);
101
102 /// <summary>
103 /// Get session information for a collection of users.
104 /// </summary>
105 /// <returns>Session information for the users.</returns>
106 /// <param name='userIDs'></param>
107 PresenceInfo[] GetAgents(string[] userIDs); 71 PresenceInfo[] GetAgents(string[] userIDs);
108 } 72 }
109} \ No newline at end of file 73}
diff --git a/OpenSim/Services/InventoryService/XInventoryService.cs b/OpenSim/Services/InventoryService/XInventoryService.cs
index 309dab4..7518b86 100644
--- a/OpenSim/Services/InventoryService/XInventoryService.cs
+++ b/OpenSim/Services/InventoryService/XInventoryService.cs
@@ -94,7 +94,6 @@ namespace OpenSim.Services.InventoryService
94 94
95 m_Database = LoadPlugin<IXInventoryData>(dllName, 95 m_Database = LoadPlugin<IXInventoryData>(dllName,
96 new Object[] {connString, String.Empty}); 96 new Object[] {connString, String.Empty});
97
98 if (m_Database == null) 97 if (m_Database == null)
99 throw new Exception("Could not find a storage interface in the given module"); 98 throw new Exception("Could not find a storage interface in the given module");
100 } 99 }
@@ -230,28 +229,10 @@ namespace OpenSim.Services.InventoryService
230 public virtual InventoryFolderBase GetFolderForType(UUID principalID, AssetType type) 229 public virtual InventoryFolderBase GetFolderForType(UUID principalID, AssetType type)
231 { 230 {
232// m_log.DebugFormat("[XINVENTORY SERVICE]: Getting folder type {0} for user {1}", type, principalID); 231// m_log.DebugFormat("[XINVENTORY SERVICE]: Getting folder type {0} for user {1}", type, principalID);
233
234 InventoryFolderBase rootFolder = GetRootFolder(principalID);
235
236 if (rootFolder == null)
237 {
238 m_log.WarnFormat(
239 "[XINVENTORY]: Found no root folder for {0} in GetFolderForType() when looking for {1}",
240 principalID, type);
241
242 return null;
243 }
244
245 return GetSystemFolderForType(rootFolder, type);
246 }
247
248 private InventoryFolderBase GetSystemFolderForType(InventoryFolderBase rootFolder, AssetType type)
249 {
250// m_log.DebugFormat("[XINVENTORY SERVICE]: Getting folder type {0} for user {1}", type, principalID);
251 232
252 XInventoryFolder[] folders = m_Database.GetFolders( 233 XInventoryFolder[] folders = m_Database.GetFolders(
253 new string[] { "agentID", "parentFolderID", "type"}, 234 new string[] { "agentID", "type"},
254 new string[] { rootFolder.Owner.ToString(), rootFolder.ID.ToString(), ((int)type).ToString() }); 235 new string[] { principalID.ToString(), ((int)type).ToString() });
255 236
256 if (folders.Length == 0) 237 if (folders.Length == 0)
257 { 238 {
@@ -327,38 +308,22 @@ namespace OpenSim.Services.InventoryService
327 if (check != null) 308 if (check != null)
328 return false; 309 return false;
329 310
330 if (folder.Type != (short)AssetType.Folder && folder.Type != (short)AssetType.Unknown) 311 if (folder.Type == (short)AssetType.Folder
312 || folder.Type == (short)AssetType.Unknown
313 || folder.Type == (short)AssetType.OutfitFolder
314 || GetFolderForType(folder.Owner, (AssetType)(folder.Type)) == null)
331 { 315 {
332 InventoryFolderBase rootFolder = GetRootFolder(folder.Owner); 316 XInventoryFolder xFolder = ConvertFromOpenSim(folder);
333 317 return m_Database.StoreFolder(xFolder);
334 if (rootFolder == null) 318 }
335 { 319 else
336 m_log.WarnFormat( 320 {
337 "[XINVENTORY]: Found no root folder for {0} in AddFolder() when looking for {1}", 321 m_log.WarnFormat(
338 folder.Owner, folder.Type); 322 "[XINVENTORY]: Folder of type {0} already exists when tried to add {1} to {2} for {3}",
339 323 folder.Type, folder.Name, folder.ParentID, folder.Owner);
340 return false;
341 }
342
343 // Check we're not trying to add this as a system folder.
344 if (folder.ParentID == rootFolder.ID)
345 {
346 InventoryFolderBase existingSystemFolder
347 = GetSystemFolderForType(rootFolder, (AssetType)folder.Type);
348
349 if (existingSystemFolder != null)
350 {
351 m_log.WarnFormat(
352 "[XINVENTORY]: System folder of type {0} already exists when tried to add {1} to {2} for {3}",
353 folder.Type, folder.Name, folder.ParentID, folder.Owner);
354
355 return false;
356 }
357 }
358 } 324 }
359 325
360 XInventoryFolder xFolder = ConvertFromOpenSim(folder); 326 return false;
361 return m_Database.StoreFolder(xFolder);
362 } 327 }
363 328
364 public virtual bool UpdateFolder(InventoryFolderBase folder) 329 public virtual bool UpdateFolder(InventoryFolderBase folder)
diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs
index cbb6e6c..988a9b9 100644
--- a/OpenSim/Services/LLLoginService/LLLoginService.cs
+++ b/OpenSim/Services/LLLoginService/LLLoginService.cs
@@ -300,7 +300,7 @@ namespace OpenSim.Services.LLLoginService
300 { 300 {
301 m_log.InfoFormat( 301 m_log.InfoFormat(
302 "[LLOGIN SERVICE]: Login failed for {0} {1}, reason: user level is {2} but minimum login level is {3}", 302 "[LLOGIN SERVICE]: Login failed for {0} {1}, reason: user level is {2} but minimum login level is {3}",
303 firstName, lastName, account.UserLevel, m_MinLoginLevel); 303 firstName, lastName, m_MinLoginLevel, account.UserLevel);
304 return LLFailedLoginResponse.LoginBlockedProblem; 304 return LLFailedLoginResponse.LoginBlockedProblem;
305 } 305 }
306 306
diff --git a/OpenSim/Services/UserAccountService/GridUserService.cs b/OpenSim/Services/UserAccountService/GridUserService.cs
index 43fa04b..ac3d8fd 100644
--- a/OpenSim/Services/UserAccountService/GridUserService.cs
+++ b/OpenSim/Services/UserAccountService/GridUserService.cs
@@ -49,7 +49,7 @@ namespace OpenSim.Services.UserAccountService
49 m_log.Debug("[USER GRID SERVICE]: Starting user grid service"); 49 m_log.Debug("[USER GRID SERVICE]: Starting user grid service");
50 } 50 }
51 51
52 public virtual GridUserInfo GetGridUserInfo(string userID) 52 public GridUserInfo GetGridUserInfo(string userID)
53 { 53 {
54 GridUserData d = m_Database.Get(userID); 54 GridUserData d = m_Database.Get(userID);
55 55
@@ -122,6 +122,17 @@ namespace OpenSim.Services.UserAccountService
122 return m_Database.Store(d); 122 return m_Database.Store(d);
123 } 123 }
124 124
125 protected bool StoreGridUserInfo(GridUserInfo info)
126 {
127 GridUserData d = new GridUserData();
128
129 d.Data["HomeRegionID"] = info.HomeRegionID.ToString();
130 d.Data["HomePosition"] = info.HomePosition.ToString();
131 d.Data["HomeLookAt"] = info.HomeLookAt.ToString();
132
133 return m_Database.Store(d);
134 }
135
125 public bool SetHome(string userID, UUID homeID, Vector3 homePosition, Vector3 homeLookAt) 136 public bool SetHome(string userID, UUID homeID, Vector3 homePosition, Vector3 homeLookAt)
126 { 137 {
127 GridUserData d = m_Database.Get(userID); 138 GridUserData d = m_Database.Get(userID);
diff --git a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs
index fc49169..7598cc3 100644
--- a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs
+++ b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs
@@ -245,7 +245,7 @@ namespace OpenSim.Tests.Common
245 config.AddConfig("Modules"); 245 config.AddConfig("Modules");
246 config.AddConfig("InventoryService"); 246 config.AddConfig("InventoryService");
247 config.Configs["Modules"].Set("InventoryServices", "LocalInventoryServicesConnector"); 247 config.Configs["Modules"].Set("InventoryServices", "LocalInventoryServicesConnector");
248 config.Configs["InventoryService"].Set("LocalServiceModule", "OpenSim.Services.InventoryService.dll:XInventoryService"); 248 config.Configs["InventoryService"].Set("LocalServiceModule", "OpenSim.Services.InventoryService.dll:InventoryService");
249 config.Configs["InventoryService"].Set("StorageProvider", "OpenSim.Tests.Common.dll"); 249 config.Configs["InventoryService"].Set("StorageProvider", "OpenSim.Tests.Common.dll");
250 250
251 LocalInventoryServicesConnector inventoryService = new LocalInventoryServicesConnector(); 251 LocalInventoryServicesConnector inventoryService = new LocalInventoryServicesConnector();
diff --git a/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs b/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs
index 87d9410..b3a7c9e 100644
--- a/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs
+++ b/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs
@@ -199,9 +199,7 @@ namespace OpenSim.Tests.Common
199 string[] components = path.Split(new string[] { PATH_DELIMITER }, 2, StringSplitOptions.None); 199 string[] components = path.Split(new string[] { PATH_DELIMITER }, 2, StringSplitOptions.None);
200 200
201 InventoryFolderBase newFolder 201 InventoryFolderBase newFolder
202 = new InventoryFolderBase( 202 = new InventoryFolderBase(UUID.Random(), components[0], parentFolder.Owner, parentFolder.ID);
203 UUID.Random(), components[0], parentFolder.Owner, (short)AssetType.Unknown, parentFolder.ID, 0);
204
205 inventoryService.AddFolder(newFolder); 203 inventoryService.AddFolder(newFolder);
206 204
207 if (components.Length > 1) 205 if (components.Length > 1)
diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs
index 5ad3c9f..78bb18e 100644
--- a/OpenSim/Tests/Common/Mock/TestClient.cs
+++ b/OpenSim/Tests/Common/Mock/TestClient.cs
@@ -531,9 +531,13 @@ namespace OpenSim.Tests.Common.Mock
531 { 531 {
532 } 532 }
533 533
534 public virtual void SendChatMessage( 534 public virtual void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName,
535 string message, byte type, Vector3 fromPos, string fromName, 535 UUID fromAgentID, byte source, byte audible)
536 UUID fromAgentID, UUID ownerID, byte source, byte audible) 536 {
537 }
538
539 public virtual void SendChatMessage(byte[] message, byte type, Vector3 fromPos, string fromName,
540 UUID fromAgentID, byte source, byte audible)
537 { 541 {
538 } 542 }
539 543
@@ -935,12 +939,12 @@ namespace OpenSim.Tests.Common.Mock
935 Close(); 939 Close();
936 } 940 }
937 941
938 public void Close() 942 public void Close(bool c)
939 { 943 {
940 Close(true, false); 944 Close();
941 } 945 }
942 946
943 public void Close(bool sendStop, bool force) 947 public void Close()
944 { 948 {
945 // Fire the callback for this connection closing 949 // Fire the callback for this connection closing
946 // This is necesary to get the presence detector to notice that a client has logged out. 950 // This is necesary to get the presence detector to notice that a client has logged out.
diff --git a/OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs b/OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs
deleted file mode 100644
index bca5979..0000000
--- a/OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs
+++ /dev/null
@@ -1,131 +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.Linq;
31using System.Reflection;
32using log4net;
33using OpenMetaverse;
34using OpenSim.Framework;
35using OpenSim.Data;
36
37namespace OpenSim.Tests.Common.Mock
38{
39 public class TestXInventoryDataPlugin : IXInventoryData
40 {
41 private Dictionary<UUID, XInventoryFolder> m_allFolders = new Dictionary<UUID, XInventoryFolder>();
42 private Dictionary<UUID, XInventoryItem> m_allItems = new Dictionary<UUID, XInventoryItem>();
43
44 public TestXInventoryDataPlugin(string conn, string realm) {}
45
46 public XInventoryItem[] GetItems(string[] fields, string[] vals)
47 {
48 List<XInventoryItem> origItems = Get<XInventoryItem>(fields, vals, m_allItems.Values.ToList());
49
50 return origItems.Select(i => i.Clone()).ToArray();
51 }
52
53 public XInventoryFolder[] GetFolders(string[] fields, string[] vals)
54 {
55 List<XInventoryFolder> origFolders
56 = Get<XInventoryFolder>(fields, vals, m_allFolders.Values.ToList());
57
58 return origFolders.Select(f => f.Clone()).ToArray();
59 }
60
61 private List<T> Get<T>(string[] fields, string[] vals, List<T> inputEntities)
62 {
63 List<T> entities = inputEntities;
64
65 for (int i = 0; i < fields.Length; i++)
66 {
67 entities
68 = entities.Where(
69 e =>
70 {
71 FieldInfo fi = typeof(T).GetField(fields[i]);
72 if (fi == null)
73 throw new NotImplementedException(string.Format("No field {0} for val {1}", fields[i], vals[i]));
74
75 return fi.GetValue(e).ToString() == vals[i];
76 }
77 ).ToList();
78 }
79
80 return entities;
81 }
82
83 public bool StoreFolder(XInventoryFolder folder)
84 {
85 m_allFolders[folder.folderID] = folder.Clone();
86
87// Console.WriteLine("Added folder {0} {1}", folder.folderName, folder.folderID);
88
89 return true;
90 }
91
92 public bool StoreItem(XInventoryItem item)
93 {
94 m_allItems[item.inventoryID] = item.Clone();
95
96// Console.WriteLine("Added item {0} {1}, creator {2}, owner {3}", item.inventoryName, item.inventoryID, item.creatorID, item.avatarID);
97
98 return true;
99 }
100
101 public bool DeleteFolders(string field, string val)
102 {
103 return DeleteFolders(new string[] { field }, new string[] { val });
104 }
105
106 public bool DeleteFolders(string[] fields, string[] vals)
107 {
108 XInventoryFolder[] foldersToDelete = GetFolders(fields, vals);
109 Array.ForEach(foldersToDelete, f => m_allFolders.Remove(f.folderID));
110
111 return true;
112 }
113
114 public bool DeleteItems(string field, string val)
115 {
116 return DeleteItems(new string[] { field }, new string[] { val });
117 }
118
119 public bool DeleteItems(string[] fields, string[] vals)
120 {
121 XInventoryItem[] itemsToDelete = GetItems(fields, vals);
122 Array.ForEach(itemsToDelete, i => m_allItems.Remove(i.inventoryID));
123
124 return true;
125 }
126
127 public bool MoveItem(string id, string newParent) { throw new NotImplementedException(); }
128 public XInventoryItem[] GetActiveGestures(UUID principalID) { throw new NotImplementedException(); }
129 public int GetAssetPermissions(UUID principalID, UUID assetID) { throw new NotImplementedException(); }
130 }
131} \ No newline at end of file
diff --git a/OpenSim/Tests/Common/TestHelpers.cs b/OpenSim/Tests/Common/TestHelpers.cs
index 57da802..30121fe 100644
--- a/OpenSim/Tests/Common/TestHelpers.cs
+++ b/OpenSim/Tests/Common/TestHelpers.cs
@@ -95,7 +95,6 @@ namespace OpenSim.Tests.Common
95 public static void EnableLogging() 95 public static void EnableLogging()
96 { 96 {
97 log4net.Config.XmlConfigurator.Configure(EnableLoggingConfigStream); 97 log4net.Config.XmlConfigurator.Configure(EnableLoggingConfigStream);
98 EnableLoggingConfigStream.Position = 0;
99 } 98 }
100 99
101 /// <summary> 100 /// <summary>
diff --git a/OpenSim/Tests/Stress/VectorRenderModuleStressTests.cs b/OpenSim/Tests/Stress/VectorRenderModuleStressTests.cs
deleted file mode 100644
index 1f220c0..0000000
--- a/OpenSim/Tests/Stress/VectorRenderModuleStressTests.cs
+++ /dev/null
@@ -1,132 +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.Linq;
32using System.Reflection;
33using System.Threading;
34using log4net.Config;
35using NUnit.Framework;
36using OpenMetaverse;
37using OpenMetaverse.Assets;
38using OpenSim.Framework;
39using OpenSim.Region.CoreModules.Scripting.DynamicTexture;
40using OpenSim.Region.CoreModules.Scripting.VectorRender;
41using OpenSim.Region.Framework.Scenes;
42using OpenSim.Region.Framework.Scenes.Serialization;
43using OpenSim.Tests.Common;
44using OpenSim.Tests.Common.Mock;
45
46namespace OpenSim.Tests.Stress
47{
48 [TestFixture]
49 public class VectorRenderModuleStressTests : OpenSimTestCase
50 {
51 public Scene Scene { get; private set; }
52 public DynamicTextureModule Dtm { get; private set; }
53 public VectorRenderModule Vrm { get; private set; }
54
55 private void SetupScene(bool reuseTextures)
56 {
57 Scene = new SceneHelpers().SetupScene();
58
59 Dtm = new DynamicTextureModule();
60 Dtm.ReuseTextures = reuseTextures;
61
62 Vrm = new VectorRenderModule();
63
64 SceneHelpers.SetupSceneModules(Scene, Dtm, Vrm);
65 }
66
67 [Test]
68 public void TestConcurrentRepeatedDraw()
69 {
70 int threads = 4;
71 TestHelpers.InMethod();
72
73 SetupScene(false);
74
75 List<Drawer> drawers = new List<Drawer>();
76
77 for (int i = 0; i < threads; i++)
78 {
79 Drawer d = new Drawer(this, i);
80 drawers.Add(d);
81 Console.WriteLine("Starting drawer {0}", i);
82 Util.FireAndForget(o => d.Draw());
83 }
84
85 Thread.Sleep(10 * 60 * 1000);
86
87 drawers.ForEach(d => d.Ready = false);
88 drawers.ForEach(d => Console.WriteLine("Drawer {0} drew {1} textures", d.Number, d.Pass + 1));
89 }
90
91 class Drawer
92 {
93 public int Number { get; private set; }
94 public int Pass { get; private set; }
95 public bool Ready { get; set; }
96
97 private VectorRenderModuleStressTests m_tests;
98
99 public Drawer(VectorRenderModuleStressTests tests, int number)
100 {
101 m_tests = tests;
102 Number = number;
103 Ready = true;
104 }
105
106 public void Draw()
107 {
108 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_tests.Scene);
109
110 while (Ready)
111 {
112 UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
113
114 // Ensure unique text
115 string text = string.Format("{0:D2}{1}", Number, Pass);
116
117 m_tests.Dtm.AddDynamicTextureData(
118 m_tests.Scene.RegionInfo.RegionID,
119 so.UUID,
120 m_tests.Vrm.GetContentType(),
121 string.Format("PenColour BLACK; MoveTo 40,220; FontSize 32; Text {0};", text),
122 "",
123 0);
124
125 Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
126
127 Pass++;
128 }
129 }
130 }
131 }
132} \ No newline at end of file
diff --git a/OpenSim/Tests/Performance/NPCPerformanceTests.cs b/OpenSim/Tests/Torture/NPCTortureTests.cs
index 627765b..731df68 100644
--- a/OpenSim/Tests/Performance/NPCPerformanceTests.cs
+++ b/OpenSim/Tests/Torture/NPCTortureTests.cs
@@ -47,10 +47,10 @@ using OpenSim.Services.AvatarService;
47using OpenSim.Tests.Common; 47using OpenSim.Tests.Common;
48using OpenSim.Tests.Common.Mock; 48using OpenSim.Tests.Common.Mock;
49 49
50namespace OpenSim.Tests.Performance 50namespace OpenSim.Tests.Torture
51{ 51{
52 /// <summary> 52 /// <summary>
53 /// NPC performance tests 53 /// NPC torture tests
54 /// </summary> 54 /// </summary>
55 /// <remarks> 55 /// <remarks>
56 /// Don't rely on the numbers given by these tests - they will vary a lot depending on what is already cached, 56 /// Don't rely on the numbers given by these tests - they will vary a lot depending on what is already cached,
@@ -58,7 +58,7 @@ namespace OpenSim.Tests.Performance
58 /// earlier tests. 58 /// earlier tests.
59 /// </remarks> 59 /// </remarks>
60 [TestFixture] 60 [TestFixture]
61 public class NPCPerformanceTests 61 public class NPCTortureTests
62 { 62 {
63 private TestScene scene; 63 private TestScene scene;
64 private AvatarFactoryModule afm; 64 private AvatarFactoryModule afm;
diff --git a/OpenSim/Tests/Performance/ObjectPerformanceTests.cs b/OpenSim/Tests/Torture/ObjectTortureTests.cs
index 2264d86..195d47b 100644
--- a/OpenSim/Tests/Performance/ObjectPerformanceTests.cs
+++ b/OpenSim/Tests/Torture/ObjectTortureTests.cs
@@ -36,10 +36,10 @@ using OpenSim.Region.Framework.Scenes;
36using OpenSim.Tests.Common; 36using OpenSim.Tests.Common;
37using OpenSim.Tests.Common.Mock; 37using OpenSim.Tests.Common.Mock;
38 38
39namespace OpenSim.Tests.Performance 39namespace OpenSim.Tests.Torture
40{ 40{
41 /// <summary> 41 /// <summary>
42 /// Object performance tests 42 /// Object torture tests
43 /// </summary> 43 /// </summary>
44 /// <remarks> 44 /// <remarks>
45 /// Don't rely on the numbers given by these tests - they will vary a lot depending on what is already cached, 45 /// Don't rely on the numbers given by these tests - they will vary a lot depending on what is already cached,
@@ -47,7 +47,7 @@ namespace OpenSim.Tests.Performance
47 /// earlier tests. 47 /// earlier tests.
48 /// </remarks> 48 /// </remarks>
49 [TestFixture] 49 [TestFixture]
50 public class ObjectPerformanceTests 50 public class ObjectTortureTests
51 { 51 {
52 [TearDown] 52 [TearDown]
53 public void TearDown() 53 public void TearDown()
diff --git a/OpenSim/Tests/Performance/ScriptPerformanceTests.cs b/OpenSim/Tests/Torture/ScriptTortureTests.cs
index d708abd..24f278f 100644
--- a/OpenSim/Tests/Performance/ScriptPerformanceTests.cs
+++ b/OpenSim/Tests/Torture/ScriptTortureTests.cs
@@ -42,10 +42,10 @@ using OpenSim.Region.ScriptEngine.XEngine;
42using OpenSim.Tests.Common; 42using OpenSim.Tests.Common;
43using OpenSim.Tests.Common.Mock; 43using OpenSim.Tests.Common.Mock;
44 44
45namespace OpenSim.Tests.Performance 45namespace OpenSim.Tests.Torture
46{ 46{
47 /// <summary> 47 /// <summary>
48 /// Script performance tests 48 /// Script torture tests
49 /// </summary> 49 /// </summary>
50 /// <remarks> 50 /// <remarks>
51 /// Don't rely on the numbers given by these tests - they will vary a lot depending on what is already cached, 51 /// Don't rely on the numbers given by these tests - they will vary a lot depending on what is already cached,
@@ -53,7 +53,7 @@ namespace OpenSim.Tests.Performance
53 /// earlier tests. 53 /// earlier tests.
54 /// </remarks> 54 /// </remarks>
55 [TestFixture] 55 [TestFixture]
56 public class ScriptPerformanceTests 56 public class ScriptTortureTests
57 { 57 {
58 private TestScene m_scene; 58 private TestScene m_scene;
59 private XEngine m_xEngine; 59 private XEngine m_xEngine;