aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--.gitignore6
-rw-r--r--.nant/local.include19
-rw-r--r--BUILDING.md (renamed from BUILDING.txt)23
-rw-r--r--CONTRIBUTORS.txt8
-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/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/PacketPool.cs (renamed from OpenSim/Framework/PacketPool.cs)97
-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/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/ScriptModuleComms/ScriptModuleCommsModule.cs (renamed from OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs)81
-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/World/NPC/NPCAvatar.cs18
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs11
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs58
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs672
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs45
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs621
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs112
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs393
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs385
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs238
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs4
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs1269
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs858
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs833
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs492
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs727
-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/ScriptException.cs (renamed from OpenSim/Region/CoreModules/Framework/InventoryAccess/HGUuidGatherer.cs)33
-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.cs67
-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/Performance/NPCPerformanceTests.cs (renamed from OpenSim/Tests/Torture/NPCTortureTests.cs)6
-rw-r--r--OpenSim/Tests/Performance/ObjectPerformanceTests.cs (renamed from OpenSim/Tests/Torture/ObjectTortureTests.cs)6
-rw-r--r--OpenSim/Tests/Performance/ScriptPerformanceTests.cs (renamed from OpenSim/Tests/Torture/ScriptTortureTests.cs)6
-rw-r--r--OpenSim/Tests/Stress/VectorRenderModuleStressTests.cs132
-rw-r--r--README.md (renamed from README.txt)42
-rw-r--r--ThirdPartyLicenses/Newtonsoft-JsonDotNet.txt23
-rwxr-xr-xbin/Newtonsoft.Json.Net20.dllbin356352 -> 0 bytes
-rw-r--r--bin/Newtonsoft.Json.XML5827
-rw-r--r--bin/Newtonsoft.Json.pdbbin742912 -> 0 bytes
-rwxr-xr-xbin/OpenMetaverse.Rendering.Meshmerizer.dllbin24576 -> 24576 bytes
-rwxr-xr-xbin/OpenMetaverse.StructuredData.dllbin114688 -> 102400 bytes
-rwxr-xr-xbin/OpenMetaverse.dllbin1904640 -> 1765376 bytes
-rw-r--r--bin/OpenMetaverse.dll.config8
-rwxr-xr-xbin/OpenMetaverseTypes.dllbin122880 -> 114688 bytes
-rw-r--r--bin/OpenSim.ini.example113
-rw-r--r--bin/OpenSimDefaults.ini110
-rw-r--r--bin/Robust.HG.ini.example90
-rw-r--r--bin/Robust.ini.example32
-rw-r--r--bin/assets/CollisionSoundsAssetSet/CollisionSoundsAssetSet.xml12
-rw-r--r--bin/config-include/FlotsamCache.ini.example7
-rw-r--r--bin/config-include/GridCommon.ini.example20
-rw-r--r--bin/config-include/StandaloneCommon.ini.example159
-rw-r--r--bin/config-include/StandaloneHypergrid.ini16
-rw-r--r--bin/config-include/storage/SQLiteStandalone.ini10
-rwxr-xr-xbin/lib32/BulletSim.dllbin550400 -> 598016 bytes
-rwxr-xr-xbin/lib32/libBulletSim.sobin2387345 -> 2772770 bytes
-rw-r--r--bin/lib32/libopenjpeg-dotnet-2.1.3.0-dotnet-1-i686.sobin124540 -> 0 bytes
-rw-r--r--bin/lib32/libopenjpeg-dotnet-2.1.3.0-dotnet-1.sobin128100 -> 0 bytes
-rwxr-xr-xbin/lib32/libopenjpeg-dotnet.sobin0 -> 140028 bytes
-rwxr-xr-xbin/lib64/BulletSim.dllbin706048 -> 764416 bytes
-rwxr-xr-xbin/lib64/libBulletSim.sobin2599320 -> 3031859 bytes
-rw-r--r--bin/lib64/libopenjpeg-dotnet-2.1.3.0-dotnet-1-x86_64.sobin142616 -> 0 bytes
-rw-r--r--bin/lib64/libopenjpeg-dotnet-2.1.3.0-dotnet-1.dylibbin125136 -> 0 bytes
-rwxr-xr-xbin/lib64/libopenjpeg-dotnet-x86_64.sobin0 -> 149368 bytes
-rwxr-xr-xbin/lib64/libopenjpeg-dotnet.dylibbin0 -> 130560 bytes
-rwxr-xr-xbin/openjpeg-dotnet-x86_64.dllbin843776 -> 215040 bytes
-rwxr-xr-xbin/openjpeg-dotnet.dllbin187392 -> 201216 bytes
-rw-r--r--bin/openmetaverse_data/avatar_lad.xml12308
-rw-r--r--bin/openmetaverse_data/blush_alpha.tgabin0 -> 17352 bytes
-rw-r--r--bin/openmetaverse_data/body_skingrain.tgabin0 -> 262188 bytes
-rw-r--r--bin/openmetaverse_data/bodyfreckles_alpha.tgabin0 -> 257249 bytes
-rw-r--r--bin/openmetaverse_data/bump_face_wrinkles.tgabin0 -> 25243 bytes
-rw-r--r--bin/openmetaverse_data/bump_head_base.tgabin0 -> 105525 bytes
-rw-r--r--bin/openmetaverse_data/bump_lowerbody_base.tgabin0 -> 112782 bytes
-rw-r--r--bin/openmetaverse_data/bump_pants_wrinkles.tgabin0 -> 83183 bytes
-rw-r--r--bin/openmetaverse_data/bump_shirt_wrinkles.tgabin0 -> 81501 bytes
-rw-r--r--bin/openmetaverse_data/bump_upperbody_base.tgabin0 -> 147581 bytes
-rw-r--r--bin/openmetaverse_data/eyebrows_alpha.tgabin0 -> 9469 bytes
-rw-r--r--bin/openmetaverse_data/eyeliner_alpha.tgabin0 -> 4720 bytes
-rw-r--r--bin/openmetaverse_data/eyeshadow_inner_alpha.tgabin0 -> 5466 bytes
-rw-r--r--bin/openmetaverse_data/eyeshadow_outer_alpha.tgabin0 -> 7382 bytes
-rw-r--r--bin/openmetaverse_data/eyewhite.tgabin0 -> 42353 bytes
-rw-r--r--bin/openmetaverse_data/facehair_chincurtains_alpha.tgabin0 -> 34610 bytes
-rw-r--r--bin/openmetaverse_data/facehair_moustache_alpha.tgabin0 -> 14017 bytes
-rw-r--r--bin/openmetaverse_data/facehair_sideburns_alpha.tgabin0 -> 27328 bytes
-rw-r--r--bin/openmetaverse_data/facehair_soulpatch_alpha.tgabin0 -> 11277 bytes
-rw-r--r--bin/openmetaverse_data/freckles_alpha.tgabin0 -> 140558 bytes
-rw-r--r--bin/openmetaverse_data/glove_length_alpha.tgabin0 -> 49745 bytes
-rw-r--r--bin/openmetaverse_data/gloves_fingers_alpha.tgabin0 -> 39616 bytes
-rw-r--r--bin/openmetaverse_data/head_alpha.tgabin0 -> 6066 bytes
-rw-r--r--bin/openmetaverse_data/head_color.tgabin0 -> 70715 bytes
-rw-r--r--bin/openmetaverse_data/head_hair.tgabin0 -> 75600 bytes
-rw-r--r--bin/openmetaverse_data/head_highlights_alpha.tgabin0 -> 20503 bytes
-rw-r--r--bin/openmetaverse_data/head_shading_alpha.tgabin0 -> 35304 bytes
-rw-r--r--bin/openmetaverse_data/head_skingrain.tgabin0 -> 262376 bytes
-rw-r--r--bin/openmetaverse_data/jacket_length_lower_alpha.tgabin0 -> 9768 bytes
-rw-r--r--bin/openmetaverse_data/jacket_length_upper_alpha.tgabin0 -> 14617 bytes
-rw-r--r--bin/openmetaverse_data/jacket_open_lower_alpha.tgabin0 -> 19732 bytes
-rw-r--r--bin/openmetaverse_data/jacket_open_upper_alpha.tgabin0 -> 41606 bytes
-rw-r--r--bin/openmetaverse_data/lipgloss_alpha.tgabin0 -> 4738 bytes
-rw-r--r--bin/openmetaverse_data/lips_mask.tgabin0 -> 6110 bytes
-rw-r--r--bin/openmetaverse_data/lipstick_alpha.tgabin0 -> 7966 bytes
-rw-r--r--bin/openmetaverse_data/lowerbody_color.tgabin0 -> 135395 bytes
-rw-r--r--bin/openmetaverse_data/lowerbody_highlights_alpha.tgabin0 -> 8695 bytes
-rw-r--r--bin/openmetaverse_data/lowerbody_shading_alpha.tgabin0 -> 41766 bytes
-rw-r--r--bin/openmetaverse_data/nailpolish_alpha.tgabin0 -> 4656 bytes
-rw-r--r--bin/openmetaverse_data/pants_length_alpha.tgabin0 -> 26843 bytes
-rw-r--r--bin/openmetaverse_data/pants_waist_alpha.tgabin0 -> 10487 bytes
-rw-r--r--bin/openmetaverse_data/rosyface_alpha.tgabin0 -> 44382 bytes
-rw-r--r--bin/openmetaverse_data/rouge_alpha.tgabin0 -> 44382 bytes
-rw-r--r--bin/openmetaverse_data/shirt_bottom_alpha.tgabin0 -> 32242 bytes
-rw-r--r--bin/openmetaverse_data/shirt_collar_alpha.tgabin0 -> 14417 bytes
-rw-r--r--bin/openmetaverse_data/shirt_collar_back_alpha.tgabin0 -> 12789 bytes
-rw-r--r--bin/openmetaverse_data/shirt_sleeve_alpha.tgabin0 -> 72196 bytes
-rw-r--r--bin/openmetaverse_data/shoe_height_alpha.tgabin0 -> 24461 bytes
-rw-r--r--bin/openmetaverse_data/skirt_length_alpha.tgabin0 -> 4114 bytes
-rw-r--r--bin/openmetaverse_data/skirt_slit_back_alpha.tgabin0 -> 90350 bytes
-rw-r--r--bin/openmetaverse_data/skirt_slit_front_alpha.tgabin0 -> 90350 bytes
-rw-r--r--bin/openmetaverse_data/skirt_slit_left_alpha.tgabin0 -> 82006 bytes
-rw-r--r--bin/openmetaverse_data/skirt_slit_right_alpha.tgabin0 -> 91410 bytes
-rw-r--r--bin/openmetaverse_data/underpants_trial_female.tgabin0 -> 48063 bytes
-rw-r--r--bin/openmetaverse_data/underpants_trial_male.tgabin0 -> 144983 bytes
-rw-r--r--bin/openmetaverse_data/undershirt_trial_female.tgabin0 -> 81390 bytes
-rw-r--r--bin/openmetaverse_data/upperbody_color.tgabin0 -> 23348 bytes
-rw-r--r--bin/openmetaverse_data/upperbody_highlights_alpha.tgabin0 -> 6509 bytes
-rw-r--r--bin/openmetaverse_data/upperbody_shading_alpha.tgabin0 -> 25297 bytes
-rw-r--r--bin/openmetaverse_data/upperbodyfreckles_alpha.tgabin0 -> 180104 bytes
-rwxr-xr-x[-rw-r--r--]bin/pCampBot.exe.config0
-rw-r--r--prebuild.xml310
333 files changed, 29988 insertions, 12938 deletions
diff --git a/.gitignore b/.gitignore
index e04c219..fae7509 100644
--- a/.gitignore
+++ b/.gitignore
@@ -29,9 +29,14 @@ addon-modules/
29bin/Debug/*.dll 29bin/Debug/*.dll
30bin/*.dll.mdb 30bin/*.dll.mdb
31bin/*.db 31bin/*.db
32bin/*.db-journal
32bin/addin-db-* 33bin/addin-db-*
33bin/*.dll 34bin/*.dll
34bin/OpenSim.vshost.exe.config 35bin/OpenSim.vshost.exe.config
36bin/OpenSim.32BitLaunch.vshost.exe.config
37bin/OpenSim.32BitLaunch.log
38UpgradeLog.XML
39_UpgradeReport_Files/
35bin/ScriptEngines/*-*-*-*-* 40bin/ScriptEngines/*-*-*-*-*
36bin/ScriptEngines/*.dll 41bin/ScriptEngines/*.dll
37bin/ScriptEngines/*/*.dll 42bin/ScriptEngines/*/*.dll
@@ -64,6 +69,7 @@ Examples/*.dll
64OpenSim.build 69OpenSim.build
65OpenSim.sln 70OpenSim.sln
66OpenSim.suo 71OpenSim.suo
72OpenSim.userprefs
67Prebuild/Prebuild.build 73Prebuild/Prebuild.build
68Prebuild/Prebuild.sln 74Prebuild/Prebuild.sln
69TestResult.xml 75TestResult.xml
diff --git a/.nant/local.include b/.nant/local.include
index 6d3e972..35f0058 100644
--- a/.nant/local.include
+++ b/.nant/local.include
@@ -135,14 +135,25 @@
135 <delete dir="%temp%"/> 135 <delete dir="%temp%"/>
136</target> 136</target>
137 137
138<target name="torture" depends="build, find-nunit"> 138<target name="test-stress" depends="build, find-nunit">
139 <setenv name="MONO_THREADS_PER_CPU" value="100" /> 139 <setenv name="MONO_THREADS_PER_CPU" value="100" />
140 140
141 <exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.tests.torture"> 141 <exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.tests.stress">
142 <arg value="./bin/OpenSim.Tests.Torture.dll" /> 142 <arg value="./bin/OpenSim.Tests.Stress.dll" />
143 </exec> 143 </exec>
144 144
145 <fail message="Failures reported in unit tests." unless="${int::parse(testresult.opensim.tests.torture)==0}" /> 145 <fail message="Failures reported in stress tests." unless="${int::parse(testresult.opensim.tests.stress)==0}" />
146 <delete dir="%temp%"/>
147</target>
148
149<target name="test-perf" depends="build, find-nunit">
150 <setenv name="MONO_THREADS_PER_CPU" value="100" />
151
152 <exec program="${nunitcmd}" failonerror="true" resultproperty="testresult.opensim.tests.performance">
153 <arg value="./bin/OpenSim.Tests.Performance.dll" />
154 </exec>
155
156 <fail message="Failures reported in performance tests." unless="${int::parse(testresult.opensim.tests.performance)==0}" />
146 <delete dir="%temp%"/> 157 <delete dir="%temp%"/>
147</target> 158</target>
148 159
diff --git a/BUILDING.txt b/BUILDING.md
index 12e5ea5..5210b58 100644
--- a/BUILDING.txt
+++ b/BUILDING.md
@@ -1,6 +1,4 @@
1==== Building OpenSim ==== 1# Building on Windows
2
3=== Building on Windows ===
4 2
5Steps: 3Steps:
6 * runprebuild.bat 4 * runprebuild.bat
@@ -9,16 +7,15 @@ Steps:
9 * copy OpenSim.ini.example to OpenSim.ini and other appropriate files in bin/config-include 7 * copy OpenSim.ini.example to OpenSim.ini and other appropriate files in bin/config-include
10 * run OpenSim.exe 8 * run OpenSim.exe
11 9
12=== Building on Linux === 10# Building on Linux
13 11
14Prereqs: 12Prereqs:
15 * Mono >= 2.4.3 13* Mono >= 2.4.3
16 * Nant >= 0.85 14* Nant >= 0.85
17 * On some Linux distributions you may need to install additional packages. 15* On some Linux distributions you may need to install additional packages.
18 See http://opensimulator.org/wiki/Dependencies for more information. 16 See http://opensimulator.org/wiki/Dependencies for more information.
19 17* May also use xbuild (included in mono distributions)
20 * May also use xbuild (included in mono distributions) 18* May use Monodevelop, a cross-platform IDE
21 * May use Monodevelop, a cross-platform IDE
22 19
23From the distribution type: 20From the distribution type:
24 * ./runprebuild.sh 21 * ./runprebuild.sh
@@ -27,13 +24,13 @@ From the distribution type:
27 * copy OpenSim.ini.example to OpenSim.ini and other appropriate files in bin/config-include 24 * copy OpenSim.ini.example to OpenSim.ini and other appropriate files in bin/config-include
28 * run mono OpenSim.exe 25 * run mono OpenSim.exe
29 26
30=== Using Monodevelop === 27# Using Monodevelop
31 28
32From the distribution type: 29From the distribution type:
33 * ./runprebuild.sh 30 * ./runprebuild.sh
34 * type monodevelop OpenSim.sln 31 * type monodevelop OpenSim.sln
35 32
36=== References === 33# References
37 34
38Helpful resources: 35Helpful resources:
39* http://opensimulator.org/wiki/Build_Instructions 36* http://opensimulator.org/wiki/Build_Instructions
diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt
index 9dd0797..fd00fe8 100644
--- a/CONTRIBUTORS.txt
+++ b/CONTRIBUTORS.txt
@@ -1,5 +1,5 @@
1<<<>>>>The following people have contributed to OpenSim (Thank you 1 <<<>>>>The following people have contributed to OpenSim (Thank you
2for your effort!) 2for your effort!)
3 3
4= Current OpenSim Developers (in very rough order of appearance) = 4= Current OpenSim Developers (in very rough order of appearance) =
5These folks represent the current core team for OpenSim, and are the 5These folks represent the current core team for OpenSim, and are the
@@ -16,7 +16,7 @@ people that make the day to day of OpenSim happen.
16* BlueWall (James Hughes) 16* BlueWall (James Hughes)
17* Nebadon Izumi (Michael Cerquoni, OSgrid) 17* Nebadon Izumi (Michael Cerquoni, OSgrid)
18* Snoopy Pfeffer 18* Snoopy Pfeffer
19* Richard Adams (Intel) 19* Robert Adams (Intel)
20 20
21= Core Developers Following the White Rabbit = 21= Core Developers Following the White Rabbit =
22Core developers who have temporarily (we hope) gone chasing the white rabbit. 22Core developers who have temporarily (we hope) gone chasing the white rabbit.
@@ -92,6 +92,7 @@ what it is today.
92* Flyte Xevious 92* Flyte Xevious
93* Garmin Kawaguichi 93* Garmin Kawaguichi
94* Gryc Ueusp 94* Gryc Ueusp
95* Hiro Lecker
95* Imaze Rhiano 96* Imaze Rhiano
96* Intimidated 97* Intimidated
97* Jeremy Bongio (IBM) 98* Jeremy Bongio (IBM)
@@ -208,3 +209,4 @@ In addition, we would like to thank:
208* The NANT Developers 209* The NANT Developers
209* Microsoft (.NET, MSSQL-Adapters) 210* Microsoft (.NET, MSSQL-Adapters)
210*x 211*x
212
diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
index 437d150..9c933ee 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((string) requestData["persist"]); 699 bool persist = Convert.ToBoolean(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,7 +852,6 @@ 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
856 855
857 m_log.Info("[RADMIN]: CreateRegion: request complete"); 856 m_log.Info("[RADMIN]: CreateRegion: request complete");
858 } 857 }
@@ -1106,8 +1105,8 @@ namespace OpenSim.ApplicationPlugins.RemoteController
1106 string lastName = (string) requestData["user_lastname"]; 1105 string lastName = (string) requestData["user_lastname"];
1107 string password = (string) requestData["user_password"]; 1106 string password = (string) requestData["user_password"];
1108 1107
1109 uint regionXLocation = Convert.ToUInt32((Int32) requestData["start_region_x"]); 1108 uint regionXLocation = Convert.ToUInt32(requestData["start_region_x"]);
1110 uint regionYLocation = Convert.ToUInt32((Int32) requestData["start_region_y"]); 1109 uint regionYLocation = Convert.ToUInt32(requestData["start_region_y"]);
1111 1110
1112 string email = ""; // empty string for email 1111 string email = ""; // empty string for email
1113 if (requestData.Contains("user_email")) 1112 if (requestData.Contains("user_email"))
@@ -1304,9 +1303,9 @@ namespace OpenSim.ApplicationPlugins.RemoteController
1304 1303
1305 if (requestData.ContainsKey("user_password")) password = (string) requestData["user_password"]; 1304 if (requestData.ContainsKey("user_password")) password = (string) requestData["user_password"];
1306 if (requestData.ContainsKey("start_region_x")) 1305 if (requestData.ContainsKey("start_region_x"))
1307 regionXLocation = Convert.ToUInt32((Int32) requestData["start_region_x"]); 1306 regionXLocation = Convert.ToUInt32(requestData["start_region_x"]);
1308 if (requestData.ContainsKey("start_region_y")) 1307 if (requestData.ContainsKey("start_region_y"))
1309 regionYLocation = Convert.ToUInt32((Int32) requestData["start_region_y"]); 1308 regionYLocation = Convert.ToUInt32(requestData["start_region_y"]);
1310 1309
1311 // if (requestData.ContainsKey("start_lookat_x")) 1310 // if (requestData.ContainsKey("start_lookat_x"))
1312 // ulaX = Convert.ToUInt32((Int32) requestData["start_lookat_x"]); 1311 // ulaX = Convert.ToUInt32((Int32) requestData["start_lookat_x"]);
@@ -1493,6 +1492,8 @@ namespace OpenSim.ApplicationPlugins.RemoteController
1493 /// <description>profile url</description></item> 1492 /// <description>profile url</description></item>
1494 /// <item><term>noassets</term> 1493 /// <item><term>noassets</term>
1495 /// <description>true if no assets should be saved</description></item> 1494 /// <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>
1496 /// <item><term>perm</term> 1497 /// <item><term>perm</term>
1497 /// <description>C and/or T</description></item> 1498 /// <description>C and/or T</description></item>
1498 /// </list> 1499 /// </list>
@@ -1549,6 +1550,11 @@ namespace OpenSim.ApplicationPlugins.RemoteController
1549 options["checkPermissions"] = (string)requestData["perm"]; 1550 options["checkPermissions"] = (string)requestData["perm"];
1550 } 1551 }
1551 1552
1553 if ((string)requestData["all"] == "true")
1554 {
1555 options["all"] = (string)requestData["all"];
1556 }
1557
1552 IRegionArchiverModule archiver = scene.RequestModuleInterface<IRegionArchiverModule>(); 1558 IRegionArchiverModule archiver = scene.RequestModuleInterface<IRegionArchiverModule>();
1553 1559
1554 if (archiver != null) 1560 if (archiver != null)
@@ -2008,29 +2014,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController
2008 { 2014 {
2009 return; 2015 return;
2010 } 2016 }
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
2034 else 2017 else
2035 { 2018 {
2036 responseData["accepted"] = false; 2019 responseData["accepted"] = false;
@@ -2052,56 +2035,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController
2052 throw new Exception(String.Format("Region ID {0} not found", regionID)); 2035 throw new Exception(String.Format("Region ID {0} not found", regionID));
2053 } 2036 }
2054 } 2037 }
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
2105 else if (requestData.ContainsKey("region_name") && 2038 else if (requestData.ContainsKey("region_name") &&
2106 !String.IsNullOrEmpty((string)requestData["region_name"])) 2039 !String.IsNullOrEmpty((string)requestData["region_name"]))
2107 { 2040 {
diff --git a/OpenSim/ApplicationPlugins/Rest/Inventory/RestHandler.cs b/OpenSim/ApplicationPlugins/Rest/Inventory/RestHandler.cs
index cb88695..072bd6f 100644
--- a/OpenSim/ApplicationPlugins/Rest/Inventory/RestHandler.cs
+++ b/OpenSim/ApplicationPlugins/Rest/Inventory/RestHandler.cs
@@ -312,14 +312,16 @@ 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 if (!AddAgentHandler(Rest.Name,this)) 315 // FIXME: If this code is ever to be re-enabled (most of it is disabled already) then this will
316 { 316 // have to be handled through the AddHttpHandler interface.
317 Rest.Log.ErrorFormat("{0} Unable to activate handler interface", MsgId); 317// if (!AddAgentHandler(Rest.Name,this))
318 foreach (IRest handler in handlers) 318// {
319 { 319// Rest.Log.ErrorFormat("{0} Unable to activate handler interface", MsgId);
320 handler.Close(); 320// foreach (IRest handler in handlers)
321 } 321// {
322 } 322// handler.Close();
323// }
324// }
323 325
324 } 326 }
325 catch (Exception e) 327 catch (Exception e)
@@ -342,11 +344,13 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory
342 { 344 {
343 Rest.Log.InfoFormat("{0} Plugin is terminating", MsgId); 345 Rest.Log.InfoFormat("{0} Plugin is terminating", MsgId);
344 346
345 try 347 // FIXME: If this code is ever to be re-enabled (most of it is disabled already) then this will
346 { 348 // have to be handled through the AddHttpHandler interface.
347 RemoveAgentHandler(Rest.Name, this); 349// try
348 } 350// {
349 catch (KeyNotFoundException){} 351// RemoveAgentHandler(Rest.Name, this);
352// }
353// catch (KeyNotFoundException){}
350 354
351 foreach (IRest handler in handlers) 355 foreach (IRest handler in handlers)
352 { 356 {
diff --git a/OpenSim/ApplicationPlugins/Rest/RestPlugin.cs b/OpenSim/ApplicationPlugins/Rest/RestPlugin.cs
index eb16750..a2425b5 100644
--- a/OpenSim/ApplicationPlugins/Rest/RestPlugin.cs
+++ b/OpenSim/ApplicationPlugins/Rest/RestPlugin.cs
@@ -297,7 +297,9 @@ 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;
301 } 303 }
302 304
303 /// <summary> 305 /// <summary>
@@ -316,7 +318,7 @@ namespace OpenSim.ApplicationPlugins.Rest
316 if (_agents[agentName] == handler) 318 if (_agents[agentName] == handler)
317 { 319 {
318 _agents.Remove(agentName); 320 _agents.Remove(agentName);
319 return _httpd.RemoveAgentHandler(agentName, handler); 321// return _httpd.RemoveAgentHandler(agentName, handler);
320 } 322 }
321 return false; 323 return false;
322 } 324 }
@@ -358,10 +360,10 @@ namespace OpenSim.ApplicationPlugins.Rest
358 _httpd.RemoveStreamHandler(h.HttpMethod, h.Path); 360 _httpd.RemoveStreamHandler(h.HttpMethod, h.Path);
359 } 361 }
360 _handlers = null; 362 _handlers = null;
361 foreach (KeyValuePair<string, IHttpAgentHandler> h in _agents) 363// foreach (KeyValuePair<string, IHttpAgentHandler> h in _agents)
362 { 364// {
363 _httpd.RemoveAgentHandler(h.Key, h.Value); 365// _httpd.RemoveAgentHandler(h.Key, h.Value);
364 } 366// }
365 _agents = null; 367 _agents = null;
366 } 368 }
367 369
diff --git a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
index b3a4d61..c275d87 100644
--- a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
+++ b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs
@@ -200,11 +200,25 @@ 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
204 // Before clamping start make sure we can satisfy it in order to avoid 203 // Before clamping start make sure we can satisfy it in order to avoid
205 // sending back the last byte instead of an error status 204 // sending back the last byte instead of an error status
206 if (start >= texture.Data.Length) 205 if (start >= texture.Data.Length)
207 { 206 {
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
208// response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable; 222// response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable;
209 // viewers don't seem to handle RequestedRangeNotSatisfiable and keep retrying with same parameters 223 // viewers don't seem to handle RequestedRangeNotSatisfiable and keep retrying with same parameters
210 response["int_response_code"] = (int)System.Net.HttpStatusCode.NotFound; 224 response["int_response_code"] = (int)System.Net.HttpStatusCode.NotFound;
@@ -215,7 +229,7 @@ namespace OpenSim.Capabilities.Handlers
215 start = Utils.Clamp(start, 0, end); 229 start = Utils.Clamp(start, 0, end);
216 int len = end - start + 1; 230 int len = end - start + 1;
217 231
218 //m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID); 232// m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
219 233
220 response["content-type"] = texture.Metadata.ContentType; 234 response["content-type"] = texture.Metadata.ContentType;
221 235
diff --git a/OpenSim/Data/IRegionData.cs b/OpenSim/Data/IRegionData.cs
index 546b5e8..70e1065 100644
--- a/OpenSim/Data/IRegionData.cs
+++ b/OpenSim/Data/IRegionData.cs
@@ -85,21 +85,6 @@ 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
103 public class RegionDataDistanceCompare : IComparer<RegionData> 88 public class RegionDataDistanceCompare : IComparer<RegionData>
104 { 89 {
105 private Vector2 m_origin; 90 private Vector2 m_origin;
diff --git a/OpenSim/Data/IXInventoryData.cs b/OpenSim/Data/IXInventoryData.cs
index 85a5c08..e64a828 100644
--- a/OpenSim/Data/IXInventoryData.cs
+++ b/OpenSim/Data/IXInventoryData.cs
@@ -40,6 +40,11 @@ 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 }
43 } 48 }
44 49
45 public class XInventoryItem 50 public class XInventoryItem
@@ -64,6 +69,11 @@ namespace OpenSim.Data
64 public UUID avatarID; 69 public UUID avatarID;
65 public UUID parentFolderID; 70 public UUID parentFolderID;
66 public int inventoryGroupPermissions; 71 public int inventoryGroupPermissions;
72
73 public XInventoryItem Clone()
74 {
75 return (XInventoryItem)MemberwiseClone();
76 }
67 } 77 }
68 78
69 public interface IXInventoryData 79 public interface IXInventoryData
diff --git a/OpenSim/Data/MSSQL/MSSQLRegionData.cs b/OpenSim/Data/MSSQL/MSSQLRegionData.cs
index 3ae87c3..0d89706 100644
--- a/OpenSim/Data/MSSQL/MSSQLRegionData.cs
+++ b/OpenSim/Data/MSSQL/MSSQLRegionData.cs
@@ -37,6 +37,7 @@ 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;
40 41
41namespace OpenSim.Data.MSSQL 42namespace OpenSim.Data.MSSQL
42{ 43{
diff --git a/OpenSim/Data/MySQL/MySQLRegionData.cs b/OpenSim/Data/MySQL/MySQLRegionData.cs
index 0614879..a2d4ae4 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;
33 33using MySql.Data.MySqlClient;
34using OpenMetaverse; 34using OpenMetaverse;
35using OpenSim.Framework; 35using OpenSim.Framework;
36using OpenSim.Data; 36using OpenSim.Data;
37using MySql.Data.MySqlClient; 37using RegionFlags = OpenSim.Framework.RegionFlags;
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 4d7c0c9..12c979a 100644
--- a/OpenSim/Data/MySQL/MySQLSimulationData.cs
+++ b/OpenSim/Data/MySQL/MySQLSimulationData.cs
@@ -747,95 +747,99 @@ 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 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) 750 lock (m_dbLock)
751 { 751 {
752 dbcon.Open(); 752 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
753
754 string command = "select * from `regionwindlight` where region_id = ?regionID";
755
756 using (MySqlCommand cmd = new MySqlCommand(command))
757 { 753 {
758 cmd.Connection = dbcon; 754 dbcon.Open();
759 755
760 cmd.Parameters.AddWithValue("?regionID", regionUUID.ToString()); 756 string command = "select * from `regionwindlight` where region_id = ?regionID";
761 757
762 IDataReader result = ExecuteReader(cmd); 758 using (MySqlCommand cmd = new MySqlCommand(command))
763 if (!result.Read())
764 {
765 //No result, so store our default windlight profile and return it
766 nWP.regionID = regionUUID;
767 // StoreRegionWindlightSettings(nWP);
768 return nWP;
769 }
770 else
771 { 759 {
772 nWP.regionID = DBGuid.FromDB(result["region_id"]); 760 cmd.Connection = dbcon;
773 nWP.waterColor.X = Convert.ToSingle(result["water_color_r"]); 761
774 nWP.waterColor.Y = Convert.ToSingle(result["water_color_g"]); 762 cmd.Parameters.AddWithValue("?regionID", regionUUID.ToString());
775 nWP.waterColor.Z = Convert.ToSingle(result["water_color_b"]); 763
776 nWP.waterFogDensityExponent = Convert.ToSingle(result["water_fog_density_exponent"]); 764 IDataReader result = ExecuteReader(cmd);
777 nWP.underwaterFogModifier = Convert.ToSingle(result["underwater_fog_modifier"]); 765 if (!result.Read())
778 nWP.reflectionWaveletScale.X = Convert.ToSingle(result["reflection_wavelet_scale_1"]); 766 {
779 nWP.reflectionWaveletScale.Y = Convert.ToSingle(result["reflection_wavelet_scale_2"]); 767 //No result, so store our default windlight profile and return it
780 nWP.reflectionWaveletScale.Z = Convert.ToSingle(result["reflection_wavelet_scale_3"]); 768 nWP.regionID = regionUUID;
781 nWP.fresnelScale = Convert.ToSingle(result["fresnel_scale"]); 769// StoreRegionWindlightSettings(nWP);
782 nWP.fresnelOffset = Convert.ToSingle(result["fresnel_offset"]); 770 return nWP;
783 nWP.refractScaleAbove = Convert.ToSingle(result["refract_scale_above"]); 771 }
784 nWP.refractScaleBelow = Convert.ToSingle(result["refract_scale_below"]); 772 else
785 nWP.blurMultiplier = Convert.ToSingle(result["blur_multiplier"]); 773 {
786 nWP.bigWaveDirection.X = Convert.ToSingle(result["big_wave_direction_x"]); 774 nWP.regionID = DBGuid.FromDB(result["region_id"]);
787 nWP.bigWaveDirection.Y = Convert.ToSingle(result["big_wave_direction_y"]); 775 nWP.waterColor.X = Convert.ToSingle(result["water_color_r"]);
788 nWP.littleWaveDirection.X = Convert.ToSingle(result["little_wave_direction_x"]); 776 nWP.waterColor.Y = Convert.ToSingle(result["water_color_g"]);
789 nWP.littleWaveDirection.Y = Convert.ToSingle(result["little_wave_direction_y"]); 777 nWP.waterColor.Z = Convert.ToSingle(result["water_color_b"]);
790 UUID.TryParse(result["normal_map_texture"].ToString(), out nWP.normalMapTexture); 778 nWP.waterFogDensityExponent = Convert.ToSingle(result["water_fog_density_exponent"]);
791 nWP.horizon.X = Convert.ToSingle(result["horizon_r"]); 779 nWP.underwaterFogModifier = Convert.ToSingle(result["underwater_fog_modifier"]);
792 nWP.horizon.Y = Convert.ToSingle(result["horizon_g"]); 780 nWP.reflectionWaveletScale.X = Convert.ToSingle(result["reflection_wavelet_scale_1"]);
793 nWP.horizon.Z = Convert.ToSingle(result["horizon_b"]); 781 nWP.reflectionWaveletScale.Y = Convert.ToSingle(result["reflection_wavelet_scale_2"]);
794 nWP.horizon.W = Convert.ToSingle(result["horizon_i"]); 782 nWP.reflectionWaveletScale.Z = Convert.ToSingle(result["reflection_wavelet_scale_3"]);
795 nWP.hazeHorizon = Convert.ToSingle(result["haze_horizon"]); 783 nWP.fresnelScale = Convert.ToSingle(result["fresnel_scale"]);
796 nWP.blueDensity.X = Convert.ToSingle(result["blue_density_r"]); 784 nWP.fresnelOffset = Convert.ToSingle(result["fresnel_offset"]);
797 nWP.blueDensity.Y = Convert.ToSingle(result["blue_density_g"]); 785 nWP.refractScaleAbove = Convert.ToSingle(result["refract_scale_above"]);
798 nWP.blueDensity.Z = Convert.ToSingle(result["blue_density_b"]); 786 nWP.refractScaleBelow = Convert.ToSingle(result["refract_scale_below"]);
799 nWP.blueDensity.W = Convert.ToSingle(result["blue_density_i"]); 787 nWP.blurMultiplier = Convert.ToSingle(result["blur_multiplier"]);
800 nWP.hazeDensity = Convert.ToSingle(result["haze_density"]); 788 nWP.bigWaveDirection.X = Convert.ToSingle(result["big_wave_direction_x"]);
801 nWP.densityMultiplier = Convert.ToSingle(result["density_multiplier"]); 789 nWP.bigWaveDirection.Y = Convert.ToSingle(result["big_wave_direction_y"]);
802 nWP.distanceMultiplier = Convert.ToSingle(result["distance_multiplier"]); 790 nWP.littleWaveDirection.X = Convert.ToSingle(result["little_wave_direction_x"]);
803 nWP.maxAltitude = Convert.ToUInt16(result["max_altitude"]); 791 nWP.littleWaveDirection.Y = Convert.ToSingle(result["little_wave_direction_y"]);
804 nWP.sunMoonColor.X = Convert.ToSingle(result["sun_moon_color_r"]); 792 UUID.TryParse(result["normal_map_texture"].ToString(), out nWP.normalMapTexture);
805 nWP.sunMoonColor.Y = Convert.ToSingle(result["sun_moon_color_g"]); 793 nWP.horizon.X = Convert.ToSingle(result["horizon_r"]);
806 nWP.sunMoonColor.Z = Convert.ToSingle(result["sun_moon_color_b"]); 794 nWP.horizon.Y = Convert.ToSingle(result["horizon_g"]);
807 nWP.sunMoonColor.W = Convert.ToSingle(result["sun_moon_color_i"]); 795 nWP.horizon.Z = Convert.ToSingle(result["horizon_b"]);
808 nWP.sunMoonPosition = Convert.ToSingle(result["sun_moon_position"]); 796 nWP.horizon.W = Convert.ToSingle(result["horizon_i"]);
809 nWP.ambient.X = Convert.ToSingle(result["ambient_r"]); 797 nWP.hazeHorizon = Convert.ToSingle(result["haze_horizon"]);
810 nWP.ambient.Y = Convert.ToSingle(result["ambient_g"]); 798 nWP.blueDensity.X = Convert.ToSingle(result["blue_density_r"]);
811 nWP.ambient.Z = Convert.ToSingle(result["ambient_b"]); 799 nWP.blueDensity.Y = Convert.ToSingle(result["blue_density_g"]);
812 nWP.ambient.W = Convert.ToSingle(result["ambient_i"]); 800 nWP.blueDensity.Z = Convert.ToSingle(result["blue_density_b"]);
813 nWP.eastAngle = Convert.ToSingle(result["east_angle"]); 801 nWP.blueDensity.W = Convert.ToSingle(result["blue_density_i"]);
814 nWP.sunGlowFocus = Convert.ToSingle(result["sun_glow_focus"]); 802 nWP.hazeDensity = Convert.ToSingle(result["haze_density"]);
815 nWP.sunGlowSize = Convert.ToSingle(result["sun_glow_size"]); 803 nWP.densityMultiplier = Convert.ToSingle(result["density_multiplier"]);
816 nWP.sceneGamma = Convert.ToSingle(result["scene_gamma"]); 804 nWP.distanceMultiplier = Convert.ToSingle(result["distance_multiplier"]);
817 nWP.starBrightness = Convert.ToSingle(result["star_brightness"]); 805 nWP.maxAltitude = Convert.ToUInt16(result["max_altitude"]);
818 nWP.cloudColor.X = Convert.ToSingle(result["cloud_color_r"]); 806 nWP.sunMoonColor.X = Convert.ToSingle(result["sun_moon_color_r"]);
819 nWP.cloudColor.Y = Convert.ToSingle(result["cloud_color_g"]); 807 nWP.sunMoonColor.Y = Convert.ToSingle(result["sun_moon_color_g"]);
820 nWP.cloudColor.Z = Convert.ToSingle(result["cloud_color_b"]); 808 nWP.sunMoonColor.Z = Convert.ToSingle(result["sun_moon_color_b"]);
821 nWP.cloudColor.W = Convert.ToSingle(result["cloud_color_i"]); 809 nWP.sunMoonColor.W = Convert.ToSingle(result["sun_moon_color_i"]);
822 nWP.cloudXYDensity.X = Convert.ToSingle(result["cloud_x"]); 810 nWP.sunMoonPosition = Convert.ToSingle(result["sun_moon_position"]);
823 nWP.cloudXYDensity.Y = Convert.ToSingle(result["cloud_y"]); 811 nWP.ambient.X = Convert.ToSingle(result["ambient_r"]);
824 nWP.cloudXYDensity.Z = Convert.ToSingle(result["cloud_density"]); 812 nWP.ambient.Y = Convert.ToSingle(result["ambient_g"]);
825 nWP.cloudCoverage = Convert.ToSingle(result["cloud_coverage"]); 813 nWP.ambient.Z = Convert.ToSingle(result["ambient_b"]);
826 nWP.cloudScale = Convert.ToSingle(result["cloud_scale"]); 814 nWP.ambient.W = Convert.ToSingle(result["ambient_i"]);
827 nWP.cloudDetailXYDensity.X = Convert.ToSingle(result["cloud_detail_x"]); 815 nWP.eastAngle = Convert.ToSingle(result["east_angle"]);
828 nWP.cloudDetailXYDensity.Y = Convert.ToSingle(result["cloud_detail_y"]); 816 nWP.sunGlowFocus = Convert.ToSingle(result["sun_glow_focus"]);
829 nWP.cloudDetailXYDensity.Z = Convert.ToSingle(result["cloud_detail_density"]); 817 nWP.sunGlowSize = Convert.ToSingle(result["sun_glow_size"]);
830 nWP.cloudScrollX = Convert.ToSingle(result["cloud_scroll_x"]); 818 nWP.sceneGamma = Convert.ToSingle(result["scene_gamma"]);
831 nWP.cloudScrollXLock = Convert.ToBoolean(result["cloud_scroll_x_lock"]); 819 nWP.starBrightness = Convert.ToSingle(result["star_brightness"]);
832 nWP.cloudScrollY = Convert.ToSingle(result["cloud_scroll_y"]); 820 nWP.cloudColor.X = Convert.ToSingle(result["cloud_color_r"]);
833 nWP.cloudScrollYLock = Convert.ToBoolean(result["cloud_scroll_y_lock"]); 821 nWP.cloudColor.Y = Convert.ToSingle(result["cloud_color_g"]);
834 nWP.drawClassicClouds = Convert.ToBoolean(result["draw_classic_clouds"]); 822 nWP.cloudColor.Z = Convert.ToSingle(result["cloud_color_b"]);
835 nWP.valid = true; 823 nWP.cloudColor.W = Convert.ToSingle(result["cloud_color_i"]);
824 nWP.cloudXYDensity.X = Convert.ToSingle(result["cloud_x"]);
825 nWP.cloudXYDensity.Y = Convert.ToSingle(result["cloud_y"]);
826 nWP.cloudXYDensity.Z = Convert.ToSingle(result["cloud_density"]);
827 nWP.cloudCoverage = Convert.ToSingle(result["cloud_coverage"]);
828 nWP.cloudScale = Convert.ToSingle(result["cloud_scale"]);
829 nWP.cloudDetailXYDensity.X = Convert.ToSingle(result["cloud_detail_x"]);
830 nWP.cloudDetailXYDensity.Y = Convert.ToSingle(result["cloud_detail_y"]);
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 }
836 } 839 }
837 } 840 }
838 } 841 }
842
839 return nWP; 843 return nWP;
840 } 844 }
841 845
@@ -881,118 +885,124 @@ namespace OpenSim.Data.MySQL
881 885
882 public virtual void StoreRegionWindlightSettings(RegionLightShareData wl) 886 public virtual void StoreRegionWindlightSettings(RegionLightShareData wl)
883 { 887 {
884 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) 888 lock (m_dbLock)
885 { 889 {
886 dbcon.Open(); 890 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
887
888 using (MySqlCommand cmd = dbcon.CreateCommand())
889 { 891 {
890 cmd.CommandText = "REPLACE INTO `regionwindlight` (`region_id`, `water_color_r`, `water_color_g`, "; 892 dbcon.Open();
891 cmd.CommandText += "`water_color_b`, `water_fog_density_exponent`, `underwater_fog_modifier`, "; 893
892 cmd.CommandText += "`reflection_wavelet_scale_1`, `reflection_wavelet_scale_2`, `reflection_wavelet_scale_3`, "; 894 using (MySqlCommand cmd = dbcon.CreateCommand())
893 cmd.CommandText += "`fresnel_scale`, `fresnel_offset`, `refract_scale_above`, `refract_scale_below`, "; 895 {
894 cmd.CommandText += "`blur_multiplier`, `big_wave_direction_x`, `big_wave_direction_y`, `little_wave_direction_x`, "; 896 cmd.CommandText = "REPLACE INTO `regionwindlight` (`region_id`, `water_color_r`, `water_color_g`, ";
895 cmd.CommandText += "`little_wave_direction_y`, `normal_map_texture`, `horizon_r`, `horizon_g`, `horizon_b`, "; 897 cmd.CommandText += "`water_color_b`, `water_fog_density_exponent`, `underwater_fog_modifier`, ";
896 cmd.CommandText += "`horizon_i`, `haze_horizon`, `blue_density_r`, `blue_density_g`, `blue_density_b`, "; 898 cmd.CommandText += "`reflection_wavelet_scale_1`, `reflection_wavelet_scale_2`, `reflection_wavelet_scale_3`, ";
897 cmd.CommandText += "`blue_density_i`, `haze_density`, `density_multiplier`, `distance_multiplier`, `max_altitude`, "; 899 cmd.CommandText += "`fresnel_scale`, `fresnel_offset`, `refract_scale_above`, `refract_scale_below`, ";
898 cmd.CommandText += "`sun_moon_color_r`, `sun_moon_color_g`, `sun_moon_color_b`, `sun_moon_color_i`, `sun_moon_position`, "; 900 cmd.CommandText += "`blur_multiplier`, `big_wave_direction_x`, `big_wave_direction_y`, `little_wave_direction_x`, ";
899 cmd.CommandText += "`ambient_r`, `ambient_g`, `ambient_b`, `ambient_i`, `east_angle`, `sun_glow_focus`, `sun_glow_size`, "; 901 cmd.CommandText += "`little_wave_direction_y`, `normal_map_texture`, `horizon_r`, `horizon_g`, `horizon_b`, ";
900 cmd.CommandText += "`scene_gamma`, `star_brightness`, `cloud_color_r`, `cloud_color_g`, `cloud_color_b`, `cloud_color_i`, "; 902 cmd.CommandText += "`horizon_i`, `haze_horizon`, `blue_density_r`, `blue_density_g`, `blue_density_b`, ";
901 cmd.CommandText += "`cloud_x`, `cloud_y`, `cloud_density`, `cloud_coverage`, `cloud_scale`, `cloud_detail_x`, "; 903 cmd.CommandText += "`blue_density_i`, `haze_density`, `density_multiplier`, `distance_multiplier`, `max_altitude`, ";
902 cmd.CommandText += "`cloud_detail_y`, `cloud_detail_density`, `cloud_scroll_x`, `cloud_scroll_x_lock`, `cloud_scroll_y`, "; 904 cmd.CommandText += "`sun_moon_color_r`, `sun_moon_color_g`, `sun_moon_color_b`, `sun_moon_color_i`, `sun_moon_position`, ";
903 cmd.CommandText += "`cloud_scroll_y_lock`, `draw_classic_clouds`) VALUES (?region_id, ?water_color_r, "; 905 cmd.CommandText += "`ambient_r`, `ambient_g`, `ambient_b`, `ambient_i`, `east_angle`, `sun_glow_focus`, `sun_glow_size`, ";
904 cmd.CommandText += "?water_color_g, ?water_color_b, ?water_fog_density_exponent, ?underwater_fog_modifier, ?reflection_wavelet_scale_1, "; 906 cmd.CommandText += "`scene_gamma`, `star_brightness`, `cloud_color_r`, `cloud_color_g`, `cloud_color_b`, `cloud_color_i`, ";
905 cmd.CommandText += "?reflection_wavelet_scale_2, ?reflection_wavelet_scale_3, ?fresnel_scale, ?fresnel_offset, ?refract_scale_above, "; 907 cmd.CommandText += "`cloud_x`, `cloud_y`, `cloud_density`, `cloud_coverage`, `cloud_scale`, `cloud_detail_x`, ";
906 cmd.CommandText += "?refract_scale_below, ?blur_multiplier, ?big_wave_direction_x, ?big_wave_direction_y, ?little_wave_direction_x, "; 908 cmd.CommandText += "`cloud_detail_y`, `cloud_detail_density`, `cloud_scroll_x`, `cloud_scroll_x_lock`, `cloud_scroll_y`, ";
907 cmd.CommandText += "?little_wave_direction_y, ?normal_map_texture, ?horizon_r, ?horizon_g, ?horizon_b, ?horizon_i, ?haze_horizon, "; 909 cmd.CommandText += "`cloud_scroll_y_lock`, `draw_classic_clouds`) VALUES (?region_id, ?water_color_r, ";
908 cmd.CommandText += "?blue_density_r, ?blue_density_g, ?blue_density_b, ?blue_density_i, ?haze_density, ?density_multiplier, "; 910 cmd.CommandText += "?water_color_g, ?water_color_b, ?water_fog_density_exponent, ?underwater_fog_modifier, ?reflection_wavelet_scale_1, ";
909 cmd.CommandText += "?distance_multiplier, ?max_altitude, ?sun_moon_color_r, ?sun_moon_color_g, ?sun_moon_color_b, "; 911 cmd.CommandText += "?reflection_wavelet_scale_2, ?reflection_wavelet_scale_3, ?fresnel_scale, ?fresnel_offset, ?refract_scale_above, ";
910 cmd.CommandText += "?sun_moon_color_i, ?sun_moon_position, ?ambient_r, ?ambient_g, ?ambient_b, ?ambient_i, ?east_angle, "; 912 cmd.CommandText += "?refract_scale_below, ?blur_multiplier, ?big_wave_direction_x, ?big_wave_direction_y, ?little_wave_direction_x, ";
911 cmd.CommandText += "?sun_glow_focus, ?sun_glow_size, ?scene_gamma, ?star_brightness, ?cloud_color_r, ?cloud_color_g, "; 913 cmd.CommandText += "?little_wave_direction_y, ?normal_map_texture, ?horizon_r, ?horizon_g, ?horizon_b, ?horizon_i, ?haze_horizon, ";
912 cmd.CommandText += "?cloud_color_b, ?cloud_color_i, ?cloud_x, ?cloud_y, ?cloud_density, ?cloud_coverage, ?cloud_scale, "; 914 cmd.CommandText += "?blue_density_r, ?blue_density_g, ?blue_density_b, ?blue_density_i, ?haze_density, ?density_multiplier, ";
913 cmd.CommandText += "?cloud_detail_x, ?cloud_detail_y, ?cloud_detail_density, ?cloud_scroll_x, ?cloud_scroll_x_lock, "; 915 cmd.CommandText += "?distance_multiplier, ?max_altitude, ?sun_moon_color_r, ?sun_moon_color_g, ?sun_moon_color_b, ";
914 cmd.CommandText += "?cloud_scroll_y, ?cloud_scroll_y_lock, ?draw_classic_clouds)"; 916 cmd.CommandText += "?sun_moon_color_i, ?sun_moon_position, ?ambient_r, ?ambient_g, ?ambient_b, ?ambient_i, ?east_angle, ";
915 917 cmd.CommandText += "?sun_glow_focus, ?sun_glow_size, ?scene_gamma, ?star_brightness, ?cloud_color_r, ?cloud_color_g, ";
916 cmd.Parameters.AddWithValue("region_id", wl.regionID); 918 cmd.CommandText += "?cloud_color_b, ?cloud_color_i, ?cloud_x, ?cloud_y, ?cloud_density, ?cloud_coverage, ?cloud_scale, ";
917 cmd.Parameters.AddWithValue("water_color_r", wl.waterColor.X); 919 cmd.CommandText += "?cloud_detail_x, ?cloud_detail_y, ?cloud_detail_density, ?cloud_scroll_x, ?cloud_scroll_x_lock, ";
918 cmd.Parameters.AddWithValue("water_color_g", wl.waterColor.Y); 920 cmd.CommandText += "?cloud_scroll_y, ?cloud_scroll_y_lock, ?draw_classic_clouds)";
919 cmd.Parameters.AddWithValue("water_color_b", wl.waterColor.Z); 921
920 cmd.Parameters.AddWithValue("water_fog_density_exponent", wl.waterFogDensityExponent); 922 cmd.Parameters.AddWithValue("region_id", wl.regionID);
921 cmd.Parameters.AddWithValue("underwater_fog_modifier", wl.underwaterFogModifier); 923 cmd.Parameters.AddWithValue("water_color_r", wl.waterColor.X);
922 cmd.Parameters.AddWithValue("reflection_wavelet_scale_1", wl.reflectionWaveletScale.X); 924 cmd.Parameters.AddWithValue("water_color_g", wl.waterColor.Y);
923 cmd.Parameters.AddWithValue("reflection_wavelet_scale_2", wl.reflectionWaveletScale.Y); 925 cmd.Parameters.AddWithValue("water_color_b", wl.waterColor.Z);
924 cmd.Parameters.AddWithValue("reflection_wavelet_scale_3", wl.reflectionWaveletScale.Z); 926 cmd.Parameters.AddWithValue("water_fog_density_exponent", wl.waterFogDensityExponent);
925 cmd.Parameters.AddWithValue("fresnel_scale", wl.fresnelScale); 927 cmd.Parameters.AddWithValue("underwater_fog_modifier", wl.underwaterFogModifier);
926 cmd.Parameters.AddWithValue("fresnel_offset", wl.fresnelOffset); 928 cmd.Parameters.AddWithValue("reflection_wavelet_scale_1", wl.reflectionWaveletScale.X);
927 cmd.Parameters.AddWithValue("refract_scale_above", wl.refractScaleAbove); 929 cmd.Parameters.AddWithValue("reflection_wavelet_scale_2", wl.reflectionWaveletScale.Y);
928 cmd.Parameters.AddWithValue("refract_scale_below", wl.refractScaleBelow); 930 cmd.Parameters.AddWithValue("reflection_wavelet_scale_3", wl.reflectionWaveletScale.Z);
929 cmd.Parameters.AddWithValue("blur_multiplier", wl.blurMultiplier); 931 cmd.Parameters.AddWithValue("fresnel_scale", wl.fresnelScale);
930 cmd.Parameters.AddWithValue("big_wave_direction_x", wl.bigWaveDirection.X); 932 cmd.Parameters.AddWithValue("fresnel_offset", wl.fresnelOffset);
931 cmd.Parameters.AddWithValue("big_wave_direction_y", wl.bigWaveDirection.Y); 933 cmd.Parameters.AddWithValue("refract_scale_above", wl.refractScaleAbove);
932 cmd.Parameters.AddWithValue("little_wave_direction_x", wl.littleWaveDirection.X); 934 cmd.Parameters.AddWithValue("refract_scale_below", wl.refractScaleBelow);
933 cmd.Parameters.AddWithValue("little_wave_direction_y", wl.littleWaveDirection.Y); 935 cmd.Parameters.AddWithValue("blur_multiplier", wl.blurMultiplier);
934 cmd.Parameters.AddWithValue("normal_map_texture", wl.normalMapTexture); 936 cmd.Parameters.AddWithValue("big_wave_direction_x", wl.bigWaveDirection.X);
935 cmd.Parameters.AddWithValue("horizon_r", wl.horizon.X); 937 cmd.Parameters.AddWithValue("big_wave_direction_y", wl.bigWaveDirection.Y);
936 cmd.Parameters.AddWithValue("horizon_g", wl.horizon.Y); 938 cmd.Parameters.AddWithValue("little_wave_direction_x", wl.littleWaveDirection.X);
937 cmd.Parameters.AddWithValue("horizon_b", wl.horizon.Z); 939 cmd.Parameters.AddWithValue("little_wave_direction_y", wl.littleWaveDirection.Y);
938 cmd.Parameters.AddWithValue("horizon_i", wl.horizon.W); 940 cmd.Parameters.AddWithValue("normal_map_texture", wl.normalMapTexture);
939 cmd.Parameters.AddWithValue("haze_horizon", wl.hazeHorizon); 941 cmd.Parameters.AddWithValue("horizon_r", wl.horizon.X);
940 cmd.Parameters.AddWithValue("blue_density_r", wl.blueDensity.X); 942 cmd.Parameters.AddWithValue("horizon_g", wl.horizon.Y);
941 cmd.Parameters.AddWithValue("blue_density_g", wl.blueDensity.Y); 943 cmd.Parameters.AddWithValue("horizon_b", wl.horizon.Z);
942 cmd.Parameters.AddWithValue("blue_density_b", wl.blueDensity.Z); 944 cmd.Parameters.AddWithValue("horizon_i", wl.horizon.W);
943 cmd.Parameters.AddWithValue("blue_density_i", wl.blueDensity.W); 945 cmd.Parameters.AddWithValue("haze_horizon", wl.hazeHorizon);
944 cmd.Parameters.AddWithValue("haze_density", wl.hazeDensity); 946 cmd.Parameters.AddWithValue("blue_density_r", wl.blueDensity.X);
945 cmd.Parameters.AddWithValue("density_multiplier", wl.densityMultiplier); 947 cmd.Parameters.AddWithValue("blue_density_g", wl.blueDensity.Y);
946 cmd.Parameters.AddWithValue("distance_multiplier", wl.distanceMultiplier); 948 cmd.Parameters.AddWithValue("blue_density_b", wl.blueDensity.Z);
947 cmd.Parameters.AddWithValue("max_altitude", wl.maxAltitude); 949 cmd.Parameters.AddWithValue("blue_density_i", wl.blueDensity.W);
948 cmd.Parameters.AddWithValue("sun_moon_color_r", wl.sunMoonColor.X); 950 cmd.Parameters.AddWithValue("haze_density", wl.hazeDensity);
949 cmd.Parameters.AddWithValue("sun_moon_color_g", wl.sunMoonColor.Y); 951 cmd.Parameters.AddWithValue("density_multiplier", wl.densityMultiplier);
950 cmd.Parameters.AddWithValue("sun_moon_color_b", wl.sunMoonColor.Z); 952 cmd.Parameters.AddWithValue("distance_multiplier", wl.distanceMultiplier);
951 cmd.Parameters.AddWithValue("sun_moon_color_i", wl.sunMoonColor.W); 953 cmd.Parameters.AddWithValue("max_altitude", wl.maxAltitude);
952 cmd.Parameters.AddWithValue("sun_moon_position", wl.sunMoonPosition); 954 cmd.Parameters.AddWithValue("sun_moon_color_r", wl.sunMoonColor.X);
953 cmd.Parameters.AddWithValue("ambient_r", wl.ambient.X); 955 cmd.Parameters.AddWithValue("sun_moon_color_g", wl.sunMoonColor.Y);
954 cmd.Parameters.AddWithValue("ambient_g", wl.ambient.Y); 956 cmd.Parameters.AddWithValue("sun_moon_color_b", wl.sunMoonColor.Z);
955 cmd.Parameters.AddWithValue("ambient_b", wl.ambient.Z); 957 cmd.Parameters.AddWithValue("sun_moon_color_i", wl.sunMoonColor.W);
956 cmd.Parameters.AddWithValue("ambient_i", wl.ambient.W); 958 cmd.Parameters.AddWithValue("sun_moon_position", wl.sunMoonPosition);
957 cmd.Parameters.AddWithValue("east_angle", wl.eastAngle); 959 cmd.Parameters.AddWithValue("ambient_r", wl.ambient.X);
958 cmd.Parameters.AddWithValue("sun_glow_focus", wl.sunGlowFocus); 960 cmd.Parameters.AddWithValue("ambient_g", wl.ambient.Y);
959 cmd.Parameters.AddWithValue("sun_glow_size", wl.sunGlowSize); 961 cmd.Parameters.AddWithValue("ambient_b", wl.ambient.Z);
960 cmd.Parameters.AddWithValue("scene_gamma", wl.sceneGamma); 962 cmd.Parameters.AddWithValue("ambient_i", wl.ambient.W);
961 cmd.Parameters.AddWithValue("star_brightness", wl.starBrightness); 963 cmd.Parameters.AddWithValue("east_angle", wl.eastAngle);
962 cmd.Parameters.AddWithValue("cloud_color_r", wl.cloudColor.X); 964 cmd.Parameters.AddWithValue("sun_glow_focus", wl.sunGlowFocus);
963 cmd.Parameters.AddWithValue("cloud_color_g", wl.cloudColor.Y); 965 cmd.Parameters.AddWithValue("sun_glow_size", wl.sunGlowSize);
964 cmd.Parameters.AddWithValue("cloud_color_b", wl.cloudColor.Z); 966 cmd.Parameters.AddWithValue("scene_gamma", wl.sceneGamma);
965 cmd.Parameters.AddWithValue("cloud_color_i", wl.cloudColor.W); 967 cmd.Parameters.AddWithValue("star_brightness", wl.starBrightness);
966 cmd.Parameters.AddWithValue("cloud_x", wl.cloudXYDensity.X); 968 cmd.Parameters.AddWithValue("cloud_color_r", wl.cloudColor.X);
967 cmd.Parameters.AddWithValue("cloud_y", wl.cloudXYDensity.Y); 969 cmd.Parameters.AddWithValue("cloud_color_g", wl.cloudColor.Y);
968 cmd.Parameters.AddWithValue("cloud_density", wl.cloudXYDensity.Z); 970 cmd.Parameters.AddWithValue("cloud_color_b", wl.cloudColor.Z);
969 cmd.Parameters.AddWithValue("cloud_coverage", wl.cloudCoverage); 971 cmd.Parameters.AddWithValue("cloud_color_i", wl.cloudColor.W);
970 cmd.Parameters.AddWithValue("cloud_scale", wl.cloudScale); 972 cmd.Parameters.AddWithValue("cloud_x", wl.cloudXYDensity.X);
971 cmd.Parameters.AddWithValue("cloud_detail_x", wl.cloudDetailXYDensity.X); 973 cmd.Parameters.AddWithValue("cloud_y", wl.cloudXYDensity.Y);
972 cmd.Parameters.AddWithValue("cloud_detail_y", wl.cloudDetailXYDensity.Y); 974 cmd.Parameters.AddWithValue("cloud_density", wl.cloudXYDensity.Z);
973 cmd.Parameters.AddWithValue("cloud_detail_density", wl.cloudDetailXYDensity.Z); 975 cmd.Parameters.AddWithValue("cloud_coverage", wl.cloudCoverage);
974 cmd.Parameters.AddWithValue("cloud_scroll_x", wl.cloudScrollX); 976 cmd.Parameters.AddWithValue("cloud_scale", wl.cloudScale);
975 cmd.Parameters.AddWithValue("cloud_scroll_x_lock", wl.cloudScrollXLock); 977 cmd.Parameters.AddWithValue("cloud_detail_x", wl.cloudDetailXYDensity.X);
976 cmd.Parameters.AddWithValue("cloud_scroll_y", wl.cloudScrollY); 978 cmd.Parameters.AddWithValue("cloud_detail_y", wl.cloudDetailXYDensity.Y);
977 cmd.Parameters.AddWithValue("cloud_scroll_y_lock", wl.cloudScrollYLock); 979 cmd.Parameters.AddWithValue("cloud_detail_density", wl.cloudDetailXYDensity.Z);
978 cmd.Parameters.AddWithValue("draw_classic_clouds", wl.drawClassicClouds); 980 cmd.Parameters.AddWithValue("cloud_scroll_x", wl.cloudScrollX);
979 981 cmd.Parameters.AddWithValue("cloud_scroll_x_lock", wl.cloudScrollXLock);
980 ExecuteNonQuery(cmd); 982 cmd.Parameters.AddWithValue("cloud_scroll_y", wl.cloudScrollY);
983 cmd.Parameters.AddWithValue("cloud_scroll_y_lock", wl.cloudScrollYLock);
984 cmd.Parameters.AddWithValue("draw_classic_clouds", wl.drawClassicClouds);
985
986 ExecuteNonQuery(cmd);
987 }
981 } 988 }
982 } 989 }
983 } 990 }
984 991
985 public virtual void RemoveRegionWindlightSettings(UUID regionID) 992 public virtual void RemoveRegionWindlightSettings(UUID regionID)
986 { 993 {
987 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) 994 lock (m_dbLock)
988 { 995 {
989 dbcon.Open(); 996 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
990
991 using (MySqlCommand cmd = dbcon.CreateCommand())
992 { 997 {
993 cmd.CommandText = "delete from `regionwindlight` where `region_id`=?regionID"; 998 dbcon.Open();
994 cmd.Parameters.AddWithValue("?regionID", regionID.ToString()); 999
995 ExecuteNonQuery(cmd); 1000 using (MySqlCommand cmd = dbcon.CreateCommand())
1001 {
1002 cmd.CommandText = "delete from `regionwindlight` where `region_id`=?regionID";
1003 cmd.Parameters.AddWithValue("?regionID", regionID.ToString());
1004 ExecuteNonQuery(cmd);
1005 }
996 } 1006 }
997 } 1007 }
998 } 1008 }
@@ -1000,26 +1010,29 @@ namespace OpenSim.Data.MySQL
1000 #region RegionEnvironmentSettings 1010 #region RegionEnvironmentSettings
1001 public string LoadRegionEnvironmentSettings(UUID regionUUID) 1011 public string LoadRegionEnvironmentSettings(UUID regionUUID)
1002 { 1012 {
1003 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) 1013 lock (m_dbLock)
1004 { 1014 {
1005 dbcon.Open(); 1015 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
1006
1007 string command = "select * from `regionenvironment` where region_id = ?region_id";
1008
1009 using (MySqlCommand cmd = new MySqlCommand(command))
1010 { 1016 {
1011 cmd.Connection = dbcon; 1017 dbcon.Open();
1012 1018
1013 cmd.Parameters.AddWithValue("?region_id", regionUUID.ToString()); 1019 string command = "select * from `regionenvironment` where region_id = ?region_id";
1014 1020
1015 IDataReader result = ExecuteReader(cmd); 1021 using (MySqlCommand cmd = new MySqlCommand(command))
1016 if (!result.Read())
1017 {
1018 return String.Empty;
1019 }
1020 else
1021 { 1022 {
1022 return Convert.ToString(result["llsd_settings"]); 1023 cmd.Connection = dbcon;
1024
1025 cmd.Parameters.AddWithValue("?region_id", regionUUID.ToString());
1026
1027 IDataReader result = ExecuteReader(cmd);
1028 if (!result.Read())
1029 {
1030 return String.Empty;
1031 }
1032 else
1033 {
1034 return Convert.ToString(result["llsd_settings"]);
1035 }
1023 } 1036 }
1024 } 1037 }
1025 } 1038 }
@@ -1027,33 +1040,39 @@ namespace OpenSim.Data.MySQL
1027 1040
1028 public void StoreRegionEnvironmentSettings(UUID regionUUID, string settings) 1041 public void StoreRegionEnvironmentSettings(UUID regionUUID, string settings)
1029 { 1042 {
1030 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) 1043 lock (m_dbLock)
1031 { 1044 {
1032 dbcon.Open(); 1045 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
1033
1034 using (MySqlCommand cmd = dbcon.CreateCommand())
1035 { 1046 {
1036 cmd.CommandText = "REPLACE INTO `regionenvironment` (`region_id`, `llsd_settings`) VALUES (?region_id, ?llsd_settings)"; 1047 dbcon.Open();
1037 1048
1038 cmd.Parameters.AddWithValue("region_id", regionUUID); 1049 using (MySqlCommand cmd = dbcon.CreateCommand())
1039 cmd.Parameters.AddWithValue("llsd_settings", settings); 1050 {
1040 1051 cmd.CommandText = "REPLACE INTO `regionenvironment` (`region_id`, `llsd_settings`) VALUES (?region_id, ?llsd_settings)";
1041 ExecuteNonQuery(cmd); 1052
1053 cmd.Parameters.AddWithValue("region_id", regionUUID);
1054 cmd.Parameters.AddWithValue("llsd_settings", settings);
1055
1056 ExecuteNonQuery(cmd);
1057 }
1042 } 1058 }
1043 } 1059 }
1044 } 1060 }
1045 1061
1046 public void RemoveRegionEnvironmentSettings(UUID regionUUID) 1062 public void RemoveRegionEnvironmentSettings(UUID regionUUID)
1047 { 1063 {
1048 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) 1064 lock (m_dbLock)
1049 { 1065 {
1050 dbcon.Open(); 1066 using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
1051
1052 using (MySqlCommand cmd = dbcon.CreateCommand())
1053 { 1067 {
1054 cmd.CommandText = "delete from `regionenvironment` where region_id = ?region_id"; 1068 dbcon.Open();
1055 cmd.Parameters.AddWithValue("?region_id", regionUUID.ToString()); 1069
1056 ExecuteNonQuery(cmd); 1070 using (MySqlCommand cmd = dbcon.CreateCommand())
1071 {
1072 cmd.CommandText = "delete from `regionenvironment` where region_id = ?region_id";
1073 cmd.Parameters.AddWithValue("?region_id", regionUUID.ToString());
1074 ExecuteNonQuery(cmd);
1075 }
1057 } 1076 }
1058 } 1077 }
1059 } 1078 }
diff --git a/OpenSim/Data/MySQL/Resources/GridUserStore.migrations b/OpenSim/Data/MySQL/Resources/GridUserStore.migrations
index 32b85ee..d08e096 100644
--- a/OpenSim/Data/MySQL/Resources/GridUserStore.migrations
+++ b/OpenSim/Data/MySQL/Resources/GridUserStore.migrations
@@ -17,3 +17,8 @@ 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 deb50cb..b4d701a 100644
--- a/OpenSim/Data/Null/NullRegionData.cs
+++ b/OpenSim/Data/Null/NullRegionData.cs
@@ -33,6 +33,7 @@ using OpenSim.Framework;
33using OpenSim.Data; 33using OpenSim.Data;
34using System.Reflection; 34using System.Reflection;
35using log4net; 35using log4net;
36using RegionFlags = OpenSim.Framework.RegionFlags;
36 37
37namespace OpenSim.Data.Null 38namespace OpenSim.Data.Null
38{ 39{
diff --git a/OpenSim/Data/SQLite/SQLiteSimulationData.cs b/OpenSim/Data/SQLite/SQLiteSimulationData.cs
index 431709f..42cd59d 100644
--- a/OpenSim/Data/SQLite/SQLiteSimulationData.cs
+++ b/OpenSim/Data/SQLite/SQLiteSimulationData.cs
@@ -1366,6 +1366,13 @@ 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));
1369 1376
1370 land.PrimaryKey = new DataColumn[] { land.Columns["UUID"] }; 1377 land.PrimaryKey = new DataColumn[] { land.Columns["UUID"] };
1371 1378
@@ -1781,9 +1788,16 @@ namespace OpenSim.Data.SQLite
1781 newData.PassHours = Convert.ToSingle(row["PassHours"]); 1788 newData.PassHours = Convert.ToSingle(row["PassHours"]);
1782 newData.PassPrice = Convert.ToInt32(row["PassPrice"]); 1789 newData.PassPrice = Convert.ToInt32(row["PassPrice"]);
1783 newData.SnapshotID = (UUID)(String)row["SnapshotUUID"]; 1790 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"]);
1784 try 1799 try
1785 { 1800 {
1786
1787 newData.UserLocation = 1801 newData.UserLocation =
1788 new Vector3(Convert.ToSingle(row["UserLocationX"]), Convert.ToSingle(row["UserLocationY"]), 1802 new Vector3(Convert.ToSingle(row["UserLocationX"]), Convert.ToSingle(row["UserLocationY"]),
1789 Convert.ToSingle(row["UserLocationZ"])); 1803 Convert.ToSingle(row["UserLocationZ"]));
@@ -2195,12 +2209,13 @@ namespace OpenSim.Data.SQLite
2195 row["UserLookAtZ"] = land.UserLookAt.Z; 2209 row["UserLookAtZ"] = land.UserLookAt.Z;
2196 row["AuthbuyerID"] = land.AuthBuyerID.ToString(); 2210 row["AuthbuyerID"] = land.AuthBuyerID.ToString();
2197 row["OtherCleanTime"] = land.OtherCleanTime; 2211 row["OtherCleanTime"] = land.OtherCleanTime;
2212 row["Dwell"] = land.Dwell;
2198 row["MediaType"] = land.MediaType; 2213 row["MediaType"] = land.MediaType;
2199 row["MediaDescription"] = land.MediaDescription; 2214 row["MediaDescription"] = land.MediaDescription;
2200 row["MediaSize"] = land.MediaWidth.ToString() + "," + land.MediaHeight.ToString(); 2215 row["MediaSize"] = String.Format("{0},{1}", land.MediaWidth, land.MediaHeight);
2201 row["MediaLoop"] = land.MediaLoop.ToString(); 2216 row["MediaLoop"] = land.MediaLoop;
2202 row["ObscureMusic"] = land.ObscureMusic.ToString(); 2217 row["ObscureMusic"] = land.ObscureMusic;
2203 row["ObscureMedia"] = land.ObscureMedia.ToString(); 2218 row["ObscureMedia"] = land.ObscureMedia;
2204 } 2219 }
2205 2220
2206 /// <summary> 2221 /// <summary>
diff --git a/OpenSim/Framework/AssetPermissions.cs b/OpenSim/Framework/AssetPermissions.cs
new file mode 100644
index 0000000..4a905c2
--- /dev/null
+++ b/OpenSim/Framework/AssetPermissions.cs
@@ -0,0 +1,84 @@
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 c5d9641..1638541 100644
--- a/OpenSim/Framework/AvatarAppearance.cs
+++ b/OpenSim/Framework/AvatarAppearance.cs
@@ -358,6 +358,9 @@ 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>
361 public virtual void SetHeight() 364 public virtual void SetHeight()
362 { 365 {
363 // Start with shortest possible female avatar height 366 // Start with shortest possible female avatar height
diff --git a/OpenSim/Framework/Cache.cs b/OpenSim/Framework/Cache.cs
index 79e20fc..31cab4a 100644
--- a/OpenSim/Framework/Cache.cs
+++ b/OpenSim/Framework/Cache.cs
@@ -199,7 +199,14 @@ 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>
202 private List<CacheItemBase> m_Index = new List<CacheItemBase>(); 205 private List<CacheItemBase> m_Index = new List<CacheItemBase>();
206
207 /// <summary>
208 /// Must only be accessed under m_Index lock.
209 /// </summary>
203 private Dictionary<string, CacheItemBase> m_Lookup = 210 private Dictionary<string, CacheItemBase> m_Lookup =
204 new Dictionary<string, CacheItemBase>(); 211 new Dictionary<string, CacheItemBase>();
205 212
@@ -320,19 +327,19 @@ namespace OpenSim.Framework
320 { 327 {
321 if (m_Lookup.ContainsKey(index)) 328 if (m_Lookup.ContainsKey(index))
322 item = m_Lookup[index]; 329 item = m_Lookup[index];
323 }
324 330
325 if (item == null) 331 if (item == null)
326 { 332 {
333 Expire(true);
334 return null;
335 }
336
337 item.hits++;
338 item.lastUsed = DateTime.Now;
339
327 Expire(true); 340 Expire(true);
328 return null;
329 } 341 }
330 342
331 item.hits++;
332 item.lastUsed = DateTime.Now;
333
334 Expire(true);
335
336 return item; 343 return item;
337 } 344 }
338 345
@@ -385,7 +392,10 @@ namespace OpenSim.Framework
385 // 392 //
386 public Object Find(Predicate<CacheItemBase> d) 393 public Object Find(Predicate<CacheItemBase> d)
387 { 394 {
388 CacheItemBase item = m_Index.Find(d); 395 CacheItemBase item;
396
397 lock (m_Index)
398 item = m_Index.Find(d);
389 399
390 if (item == null) 400 if (item == null)
391 return null; 401 return null;
@@ -419,12 +429,12 @@ namespace OpenSim.Framework
419 public virtual void Store(string index, Object data, Type container, 429 public virtual void Store(string index, Object data, Type container,
420 Object[] parameters) 430 Object[] parameters)
421 { 431 {
422 Expire(false);
423
424 CacheItemBase item; 432 CacheItemBase item;
425 433
426 lock (m_Index) 434 lock (m_Index)
427 { 435 {
436 Expire(false);
437
428 if (m_Index.Contains(new CacheItemBase(index))) 438 if (m_Index.Contains(new CacheItemBase(index)))
429 { 439 {
430 if ((m_Flags & CacheFlags.AllowUpdate) != 0) 440 if ((m_Flags & CacheFlags.AllowUpdate) != 0)
@@ -450,9 +460,17 @@ namespace OpenSim.Framework
450 m_Index.Add(item); 460 m_Index.Add(item);
451 m_Lookup[index] = item; 461 m_Lookup[index] = item;
452 } 462 }
463
453 item.Store(data); 464 item.Store(data);
454 } 465 }
455 466
467 /// <summary>
468 /// Expire items as appropriate.
469 /// </summary>
470 /// <remarks>
471 /// Callers must lock m_Index.
472 /// </remarks>
473 /// <param name='getting'></param>
456 protected virtual void Expire(bool getting) 474 protected virtual void Expire(bool getting)
457 { 475 {
458 if (getting && (m_Strategy == CacheStrategy.Aggressive)) 476 if (getting && (m_Strategy == CacheStrategy.Aggressive))
@@ -475,12 +493,10 @@ namespace OpenSim.Framework
475 493
476 switch (m_Strategy) 494 switch (m_Strategy)
477 { 495 {
478 case CacheStrategy.Aggressive: 496 case CacheStrategy.Aggressive:
479 if (Count < Size) 497 if (Count < Size)
480 return; 498 return;
481 499
482 lock (m_Index)
483 {
484 m_Index.Sort(new SortLRU()); 500 m_Index.Sort(new SortLRU());
485 m_Index.Reverse(); 501 m_Index.Reverse();
486 502
@@ -490,7 +506,7 @@ namespace OpenSim.Framework
490 506
491 ExpireDelegate doExpire = OnExpire; 507 ExpireDelegate doExpire = OnExpire;
492 508
493 if (doExpire != null) 509 if (doExpire != null)
494 { 510 {
495 List<CacheItemBase> candidates = 511 List<CacheItemBase> candidates =
496 m_Index.GetRange(target, Count - target); 512 m_Index.GetRange(target, Count - target);
@@ -513,27 +529,34 @@ namespace OpenSim.Framework
513 foreach (CacheItemBase item in m_Index) 529 foreach (CacheItemBase item in m_Index)
514 m_Lookup[item.uuid] = item; 530 m_Lookup[item.uuid] = item;
515 } 531 }
516 } 532
517 break; 533 break;
518 default: 534
519 break; 535 default:
536 break;
520 } 537 }
521 } 538 }
522 539
523 public void Invalidate(string uuid) 540 public void Invalidate(string uuid)
524 { 541 {
525 if (!m_Lookup.ContainsKey(uuid)) 542 lock (m_Index)
526 return; 543 {
544 if (!m_Lookup.ContainsKey(uuid))
545 return;
527 546
528 CacheItemBase item = m_Lookup[uuid]; 547 CacheItemBase item = m_Lookup[uuid];
529 m_Lookup.Remove(uuid); 548 m_Lookup.Remove(uuid);
530 m_Index.Remove(item); 549 m_Index.Remove(item);
550 }
531 } 551 }
532 552
533 public void Clear() 553 public void Clear()
534 { 554 {
535 m_Index.Clear(); 555 lock (m_Index)
536 m_Lookup.Clear(); 556 {
557 m_Index.Clear();
558 m_Lookup.Clear();
559 }
537 } 560 }
538 } 561 }
539} 562} \ No newline at end of file
diff --git a/OpenSim/Framework/Client/IClientChat.cs b/OpenSim/Framework/Client/IClientChat.cs
index 078ea9b..86b1faa 100644
--- a/OpenSim/Framework/Client/IClientChat.cs
+++ b/OpenSim/Framework/Client/IClientChat.cs
@@ -33,7 +33,8 @@ namespace OpenSim.Framework.Client
33 { 33 {
34 event ChatMessage OnChatFromClient; 34 event ChatMessage OnChatFromClient;
35 35
36 void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, byte source, 36 void SendChatMessage(
37 byte audible); 37 string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, UUID ownerID, byte source,
38 byte audible);
38 } 39 }
39} 40} \ No newline at end of file
diff --git a/OpenSim/Framework/Console/ConsoleUtil.cs b/OpenSim/Framework/Console/ConsoleUtil.cs
new file mode 100644
index 0000000..16a63e0
--- /dev/null
+++ b/OpenSim/Framework/Console/ConsoleUtil.cs
@@ -0,0 +1,228 @@
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 1b1aaf2..a2eb5ee 100644
--- a/OpenSim/Framework/Constants.cs
+++ b/OpenSim/Framework/Constants.cs
@@ -31,6 +31,7 @@ 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;
34 public const byte TerrainPatchSize = 16; 35 public const byte TerrainPatchSize = 16;
35 public const string DefaultTexture = "89556747-24cb-43ed-920b-47caed15465f"; 36 public const string DefaultTexture = "89556747-24cb-43ed-920b-47caed15465f";
36 37
diff --git a/OpenSim/Framework/EstateSettings.cs b/OpenSim/Framework/EstateSettings.cs
index 9020761..e03750b 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)RegionFlags.ResetHomeOnTeleport) == (ulong)RegionFlags.ResetHomeOnTeleport); 422 ResetHomeOnTeleport = ((regionFlags & (ulong)OpenMetaverse.RegionFlags.ResetHomeOnTeleport) == (ulong)OpenMetaverse.RegionFlags.ResetHomeOnTeleport);
423 BlockDwell = ((regionFlags & (ulong)RegionFlags.BlockDwell) == (ulong)RegionFlags.BlockDwell); 423 BlockDwell = ((regionFlags & (ulong)OpenMetaverse.RegionFlags.BlockDwell) == (ulong)OpenMetaverse.RegionFlags.BlockDwell);
424 AllowLandmark = ((regionFlags & (ulong)RegionFlags.AllowLandmark) == (ulong)RegionFlags.AllowLandmark); 424 AllowLandmark = ((regionFlags & (ulong)OpenMetaverse.RegionFlags.AllowLandmark) == (ulong)OpenMetaverse.RegionFlags.AllowLandmark);
425 AllowParcelChanges = ((regionFlags & (ulong)RegionFlags.AllowParcelChanges) == (ulong)RegionFlags.AllowParcelChanges); 425 AllowParcelChanges = ((regionFlags & (ulong)OpenMetaverse.RegionFlags.AllowParcelChanges) == (ulong)OpenMetaverse.RegionFlags.AllowParcelChanges);
426 AllowSetHome = ((regionFlags & (ulong)RegionFlags.AllowSetHome) == (ulong)RegionFlags.AllowSetHome); 426 AllowSetHome = ((regionFlags & (ulong)OpenMetaverse.RegionFlags.AllowSetHome) == (ulong)OpenMetaverse.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 a6bf6e3..6ae0488 100644
--- a/OpenSim/Framework/GridInstantMessage.cs
+++ b/OpenSim/Framework/GridInstantMessage.cs
@@ -44,7 +44,6 @@ namespace OpenSim.Framework
44 public Vector3 Position; 44 public Vector3 Position;
45 public byte[] binaryBucket; 45 public byte[] binaryBucket;
46 46
47
48 public uint ParentEstateID; 47 public uint ParentEstateID;
49 public Guid RegionID; 48 public Guid RegionID;
50 public uint timestamp; 49 public uint timestamp;
@@ -58,7 +57,7 @@ namespace OpenSim.Framework
58 string _fromAgentName, UUID _toAgentID, 57 string _fromAgentName, UUID _toAgentID,
59 byte _dialog, bool _fromGroup, string _message, 58 byte _dialog, bool _fromGroup, string _message,
60 UUID _imSessionID, bool _offline, Vector3 _position, 59 UUID _imSessionID, bool _offline, Vector3 _position,
61 byte[] _binaryBucket) 60 byte[] _binaryBucket, bool addTimestamp)
62 { 61 {
63 fromAgentID = _fromAgentID.Guid; 62 fromAgentID = _fromAgentID.Guid;
64 fromAgentName = _fromAgentName; 63 fromAgentName = _fromAgentName;
@@ -79,7 +78,9 @@ namespace OpenSim.Framework
79 ParentEstateID = scene.RegionInfo.EstateSettings.ParentEstateID; 78 ParentEstateID = scene.RegionInfo.EstateSettings.ParentEstateID;
80 RegionID = scene.RegionInfo.RegionSettings.RegionUUID.Guid; 79 RegionID = scene.RegionInfo.RegionSettings.RegionUUID.Guid;
81 } 80 }
82 timestamp = (uint)Util.UnixTimeSinceEpoch(); 81
82 if (addTimestamp)
83 timestamp = (uint)Util.UnixTimeSinceEpoch();
83 } 84 }
84 85
85 public GridInstantMessage(IScene scene, UUID _fromAgentID, 86 public GridInstantMessage(IScene scene, UUID _fromAgentID,
@@ -87,7 +88,7 @@ namespace OpenSim.Framework
87 string _message, bool _offline, 88 string _message, bool _offline,
88 Vector3 _position) : this(scene, _fromAgentID, _fromAgentName, 89 Vector3 _position) : this(scene, _fromAgentID, _fromAgentName,
89 _toAgentID, _dialog, false, _message, 90 _toAgentID, _dialog, false, _message,
90 _fromAgentID ^ _toAgentID, _offline, _position, new byte[0]) 91 _fromAgentID ^ _toAgentID, _offline, _position, new byte[0], true)
91 { 92 {
92 } 93 }
93 } 94 }
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs
index 5909ce1..a1df637 100644
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -815,8 +815,23 @@ 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>
818 event UpdateAgent OnPreAgentUpdate; 825 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>
819 event UpdateAgent OnAgentUpdate; 833 event UpdateAgent OnAgentUpdate;
834
820 event AgentRequestSit OnAgentRequestSit; 835 event AgentRequestSit OnAgentRequestSit;
821 event AgentSit OnAgentSit; 836 event AgentSit OnAgentSit;
822 event AvatarPickerRequest OnAvatarPickerRequest; 837 event AvatarPickerRequest OnAvatarPickerRequest;
@@ -1046,8 +1061,21 @@ namespace OpenSim.Framework
1046 1061
1047 void InPacket(object NewPack); 1062 void InPacket(object NewPack);
1048 void ProcessInPacket(Packet NewPack); 1063 void ProcessInPacket(Packet NewPack);
1064
1065 /// <summary>
1066 /// Close this client
1067 /// </summary>
1049 void Close(); 1068 void Close();
1050 void Close(bool sendStop); 1069
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
1051 void Kick(string message); 1079 void Kick(string message);
1052 1080
1053 /// <summary> 1081 /// <summary>
@@ -1084,8 +1112,20 @@ namespace OpenSim.Framework
1084 void SendAnimations(UUID[] animID, int[] seqs, UUID sourceAgentId, UUID[] objectIDs); 1112 void SendAnimations(UUID[] animID, int[] seqs, UUID sourceAgentId, UUID[] objectIDs);
1085 void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args); 1113 void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args);
1086 1114
1087 void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, byte source, 1115 /// <summary>
1088 byte audible); 1116 /// Send chat to the viewer.
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);
1089 1129
1090 void SendInstantMessage(GridInstantMessage im); 1130 void SendInstantMessage(GridInstantMessage im);
1091 1131
diff --git a/OpenSim/Framework/InventoryFolderBase.cs b/OpenSim/Framework/InventoryFolderBase.cs
index a12183c..b3457a6 100644
--- a/OpenSim/Framework/InventoryFolderBase.cs
+++ b/OpenSim/Framework/InventoryFolderBase.cs
@@ -73,33 +73,27 @@ namespace OpenSim.Framework
73 { 73 {
74 } 74 }
75 75
76 public InventoryFolderBase(UUID id) 76 public InventoryFolderBase(UUID id) : this()
77 { 77 {
78 ID = id; 78 ID = id;
79 } 79 }
80 80
81 public InventoryFolderBase(UUID id, UUID owner) 81 public InventoryFolderBase(UUID id, UUID owner) : this(id)
82 { 82 {
83 ID = id;
84 Owner = owner; 83 Owner = owner;
85 } 84 }
86 85
87 public InventoryFolderBase(UUID id, string name, UUID owner, UUID parent) 86 public InventoryFolderBase(UUID id, string name, UUID owner, UUID parent) : this(id, owner)
88 { 87 {
89 ID = id;
90 Name = name; 88 Name = name;
91 Owner = owner;
92 ParentID = parent; 89 ParentID = parent;
93 } 90 }
94 91
95 public InventoryFolderBase(UUID id, string name, UUID owner, short type, UUID parent, ushort version) 92 public InventoryFolderBase(
93 UUID id, string name, UUID owner, short type, UUID parent, ushort version) : this(id, name, owner, parent)
96 { 94 {
97 ID = id;
98 Name = name;
99 Owner = owner;
100 Type = type; 95 Type = type;
101 ParentID = parent;
102 Version = version; 96 Version = version;
103 } 97 }
104 } 98 }
105} 99} \ No newline at end of file
diff --git a/OpenSim/Framework/LandData.cs b/OpenSim/Framework/LandData.cs
index dcaa46d..4dffd3f 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.SoundLocal | (uint) ParcelFlags.AllowVoiceChat; 72 (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,16 +97,36 @@ 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 }
100 117
101 /// <summary> 118 /// <summary>
102 /// Whether to obscure parcel media URL 119 /// Whether to obscure parcel media URL
103 /// </summary> 120 /// </summary>
104 [XmlIgnore] 121 [XmlIgnore]
105 public bool ObscureMedia { 122 public bool ObscureMedia
106 get { 123 {
124 get
125 {
107 return _obscureMedia; 126 return _obscureMedia;
108 } 127 }
109 set { 128 set
129 {
110 _obscureMedia = value; 130 _obscureMedia = value;
111 } 131 }
112 } 132 }
@@ -115,11 +135,14 @@ namespace OpenSim.Framework
115 /// Whether to obscure parcel music URL 135 /// Whether to obscure parcel music URL
116 /// </summary> 136 /// </summary>
117 [XmlIgnore] 137 [XmlIgnore]
118 public bool ObscureMusic { 138 public bool ObscureMusic
119 get { 139 {
140 get
141 {
120 return _obscureMusic; 142 return _obscureMusic;
121 } 143 }
122 set { 144 set
145 {
123 _obscureMusic = value; 146 _obscureMusic = value;
124 } 147 }
125 } 148 }
@@ -128,11 +151,14 @@ namespace OpenSim.Framework
128 /// Whether to loop parcel media 151 /// Whether to loop parcel media
129 /// </summary> 152 /// </summary>
130 [XmlIgnore] 153 [XmlIgnore]
131 public bool MediaLoop { 154 public bool MediaLoop
132 get { 155 {
156 get
157 {
133 return _mediaLoop; 158 return _mediaLoop;
134 } 159 }
135 set { 160 set
161 {
136 _mediaLoop = value; 162 _mediaLoop = value;
137 } 163 }
138 } 164 }
@@ -141,11 +167,14 @@ namespace OpenSim.Framework
141 /// Height of parcel media render 167 /// Height of parcel media render
142 /// </summary> 168 /// </summary>
143 [XmlIgnore] 169 [XmlIgnore]
144 public int MediaHeight { 170 public int MediaHeight
145 get { 171 {
172 get
173 {
146 return _mediaHeight; 174 return _mediaHeight;
147 } 175 }
148 set { 176 set
177 {
149 _mediaHeight = value; 178 _mediaHeight = value;
150 } 179 }
151 } 180 }
@@ -154,11 +183,14 @@ namespace OpenSim.Framework
154 /// Width of parcel media render 183 /// Width of parcel media render
155 /// </summary> 184 /// </summary>
156 [XmlIgnore] 185 [XmlIgnore]
157 public int MediaWidth { 186 public int MediaWidth
158 get { 187 {
188 get
189 {
159 return _mediaWidth; 190 return _mediaWidth;
160 } 191 }
161 set { 192 set
193 {
162 _mediaWidth = value; 194 _mediaWidth = value;
163 } 195 }
164 } 196 }
@@ -167,11 +199,14 @@ namespace OpenSim.Framework
167 /// Upper corner of the AABB for the parcel 199 /// Upper corner of the AABB for the parcel
168 /// </summary> 200 /// </summary>
169 [XmlIgnore] 201 [XmlIgnore]
170 public Vector3 AABBMax { 202 public Vector3 AABBMax
171 get { 203 {
204 get
205 {
172 return _AABBMax; 206 return _AABBMax;
173 } 207 }
174 set { 208 set
209 {
175 _AABBMax = value; 210 _AABBMax = value;
176 } 211 }
177 } 212 }
@@ -179,11 +214,14 @@ namespace OpenSim.Framework
179 /// Lower corner of the AABB for the parcel 214 /// Lower corner of the AABB for the parcel
180 /// </summary> 215 /// </summary>
181 [XmlIgnore] 216 [XmlIgnore]
182 public Vector3 AABBMin { 217 public Vector3 AABBMin
183 get { 218 {
219 get
220 {
184 return _AABBMin; 221 return _AABBMin;
185 } 222 }
186 set { 223 set
224 {
187 _AABBMin = value; 225 _AABBMin = value;
188 } 226 }
189 } 227 }
@@ -191,11 +229,14 @@ namespace OpenSim.Framework
191 /// <summary> 229 /// <summary>
192 /// Area in meters^2 the parcel contains 230 /// Area in meters^2 the parcel contains
193 /// </summary> 231 /// </summary>
194 public int Area { 232 public int Area
195 get { 233 {
234 get
235 {
196 return _area; 236 return _area;
197 } 237 }
198 set { 238 set
239 {
199 _area = value; 240 _area = value;
200 } 241 }
201 } 242 }
@@ -203,11 +244,14 @@ namespace OpenSim.Framework
203 /// <summary> 244 /// <summary>
204 /// ID of auction (3rd Party Integration) when parcel is being auctioned 245 /// ID of auction (3rd Party Integration) when parcel is being auctioned
205 /// </summary> 246 /// </summary>
206 public uint AuctionID { 247 public uint AuctionID
207 get { 248 {
249 get
250 {
208 return _auctionID; 251 return _auctionID;
209 } 252 }
210 set { 253 set
254 {
211 _auctionID = value; 255 _auctionID = value;
212 } 256 }
213 } 257 }
@@ -215,11 +259,14 @@ namespace OpenSim.Framework
215 /// <summary> 259 /// <summary>
216 /// UUID of authorized buyer of parcel. This is UUID.Zero if anyone can buy it. 260 /// UUID of authorized buyer of parcel. This is UUID.Zero if anyone can buy it.
217 /// </summary> 261 /// </summary>
218 public UUID AuthBuyerID { 262 public UUID AuthBuyerID
219 get { 263 {
264 get
265 {
220 return _authBuyerID; 266 return _authBuyerID;
221 } 267 }
222 set { 268 set
269 {
223 _authBuyerID = value; 270 _authBuyerID = value;
224 } 271 }
225 } 272 }
@@ -227,11 +274,14 @@ namespace OpenSim.Framework
227 /// <summary> 274 /// <summary>
228 /// Category of parcel. Used for classifying the parcel in classified listings 275 /// Category of parcel. Used for classifying the parcel in classified listings
229 /// </summary> 276 /// </summary>
230 public ParcelCategory Category { 277 public ParcelCategory Category
231 get { 278 {
279 get
280 {
232 return _category; 281 return _category;
233 } 282 }
234 set { 283 set
284 {
235 _category = value; 285 _category = value;
236 } 286 }
237 } 287 }
@@ -239,11 +289,14 @@ namespace OpenSim.Framework
239 /// <summary> 289 /// <summary>
240 /// Date that the current owner purchased or claimed the parcel 290 /// Date that the current owner purchased or claimed the parcel
241 /// </summary> 291 /// </summary>
242 public int ClaimDate { 292 public int ClaimDate
243 get { 293 {
294 get
295 {
244 return _claimDate; 296 return _claimDate;
245 } 297 }
246 set { 298 set
299 {
247 _claimDate = value; 300 _claimDate = value;
248 } 301 }
249 } 302 }
@@ -251,11 +304,14 @@ namespace OpenSim.Framework
251 /// <summary> 304 /// <summary>
252 /// The last price that the parcel was sold at 305 /// The last price that the parcel was sold at
253 /// </summary> 306 /// </summary>
254 public int ClaimPrice { 307 public int ClaimPrice
255 get { 308 {
309 get
310 {
256 return _claimPrice; 311 return _claimPrice;
257 } 312 }
258 set { 313 set
314 {
259 _claimPrice = value; 315 _claimPrice = value;
260 } 316 }
261 } 317 }
@@ -263,11 +319,14 @@ namespace OpenSim.Framework
263 /// <summary> 319 /// <summary>
264 /// Global ID for the parcel. (3rd Party Integration) 320 /// Global ID for the parcel. (3rd Party Integration)
265 /// </summary> 321 /// </summary>
266 public UUID GlobalID { 322 public UUID GlobalID
267 get { 323 {
324 get
325 {
268 return _globalID; 326 return _globalID;
269 } 327 }
270 set { 328 set
329 {
271 _globalID = value; 330 _globalID = value;
272 } 331 }
273 } 332 }
@@ -275,11 +334,14 @@ namespace OpenSim.Framework
275 /// <summary> 334 /// <summary>
276 /// Unique ID of the Group that owns 335 /// Unique ID of the Group that owns
277 /// </summary> 336 /// </summary>
278 public UUID GroupID { 337 public UUID GroupID
279 get { 338 {
339 get
340 {
280 return _groupID; 341 return _groupID;
281 } 342 }
282 set { 343 set
344 {
283 _groupID = value; 345 _groupID = value;
284 } 346 }
285 } 347 }
@@ -287,11 +349,14 @@ namespace OpenSim.Framework
287 /// <summary> 349 /// <summary>
288 /// Returns true if the Land Parcel is owned by a group 350 /// Returns true if the Land Parcel is owned by a group
289 /// </summary> 351 /// </summary>
290 public bool IsGroupOwned { 352 public bool IsGroupOwned
291 get { 353 {
354 get
355 {
292 return _isGroupOwned; 356 return _isGroupOwned;
293 } 357 }
294 set { 358 set
359 {
295 _isGroupOwned = value; 360 _isGroupOwned = value;
296 } 361 }
297 } 362 }
@@ -299,11 +364,14 @@ namespace OpenSim.Framework
299 /// <summary> 364 /// <summary>
300 /// jp2 data for the image representative of the parcel in the parcel dialog 365 /// jp2 data for the image representative of the parcel in the parcel dialog
301 /// </summary> 366 /// </summary>
302 public byte[] Bitmap { 367 public byte[] Bitmap
303 get { 368 {
369 get
370 {
304 return _bitmap; 371 return _bitmap;
305 } 372 }
306 set { 373 set
374 {
307 _bitmap = value; 375 _bitmap = value;
308 } 376 }
309 } 377 }
@@ -311,11 +379,14 @@ namespace OpenSim.Framework
311 /// <summary> 379 /// <summary>
312 /// Parcel Description 380 /// Parcel Description
313 /// </summary> 381 /// </summary>
314 public string Description { 382 public string Description
315 get { 383 {
384 get
385 {
316 return _description; 386 return _description;
317 } 387 }
318 set { 388 set
389 {
319 _description = value; 390 _description = value;
320 } 391 }
321 } 392 }
@@ -323,11 +394,14 @@ namespace OpenSim.Framework
323 /// <summary> 394 /// <summary>
324 /// Parcel settings. Access flags, Fly, NoPush, Voice, Scripts allowed, etc. ParcelFlags 395 /// Parcel settings. Access flags, Fly, NoPush, Voice, Scripts allowed, etc. ParcelFlags
325 /// </summary> 396 /// </summary>
326 public uint Flags { 397 public uint Flags
327 get { 398 {
399 get
400 {
328 return _flags; 401 return _flags;
329 } 402 }
330 set { 403 set
404 {
331 _flags = value; 405 _flags = value;
332 } 406 }
333 } 407 }
@@ -336,11 +410,14 @@ namespace OpenSim.Framework
336 /// Determines if people are able to teleport where they please on the parcel or if they 410 /// Determines if people are able to teleport where they please on the parcel or if they
337 /// get constrainted to a specific point on teleport within the parcel 411 /// get constrainted to a specific point on teleport within the parcel
338 /// </summary> 412 /// </summary>
339 public byte LandingType { 413 public byte LandingType
340 get { 414 {
415 get
416 {
341 return _landingType; 417 return _landingType;
342 } 418 }
343 set { 419 set
420 {
344 _landingType = value; 421 _landingType = value;
345 } 422 }
346 } 423 }
@@ -348,11 +425,14 @@ namespace OpenSim.Framework
348 /// <summary> 425 /// <summary>
349 /// Parcel Name 426 /// Parcel Name
350 /// </summary> 427 /// </summary>
351 public string Name { 428 public string Name
352 get { 429 {
430 get
431 {
353 return _name; 432 return _name;
354 } 433 }
355 set { 434 set
435 {
356 _name = value; 436 _name = value;
357 } 437 }
358 } 438 }
@@ -360,11 +440,14 @@ namespace OpenSim.Framework
360 /// <summary> 440 /// <summary>
361 /// Status of Parcel, Leased, Abandoned, For Sale 441 /// Status of Parcel, Leased, Abandoned, For Sale
362 /// </summary> 442 /// </summary>
363 public ParcelStatus Status { 443 public ParcelStatus Status
364 get { 444 {
445 get
446 {
365 return _status; 447 return _status;
366 } 448 }
367 set { 449 set
450 {
368 _status = value; 451 _status = value;
369 } 452 }
370 } 453 }
@@ -372,11 +455,14 @@ namespace OpenSim.Framework
372 /// <summary> 455 /// <summary>
373 /// Internal ID of the parcel. Sometimes the client will try to use this value 456 /// Internal ID of the parcel. Sometimes the client will try to use this value
374 /// </summary> 457 /// </summary>
375 public int LocalID { 458 public int LocalID
376 get { 459 {
460 get
461 {
377 return _localID; 462 return _localID;
378 } 463 }
379 set { 464 set
465 {
380 _localID = value; 466 _localID = value;
381 } 467 }
382 } 468 }
@@ -384,11 +470,14 @@ namespace OpenSim.Framework
384 /// <summary> 470 /// <summary>
385 /// Determines if we scale the media based on the surface it's on 471 /// Determines if we scale the media based on the surface it's on
386 /// </summary> 472 /// </summary>
387 public byte MediaAutoScale { 473 public byte MediaAutoScale
388 get { 474 {
475 get
476 {
389 return _mediaAutoScale; 477 return _mediaAutoScale;
390 } 478 }
391 set { 479 set
480 {
392 _mediaAutoScale = value; 481 _mediaAutoScale = value;
393 } 482 }
394 } 483 }
@@ -396,11 +485,14 @@ namespace OpenSim.Framework
396 /// <summary> 485 /// <summary>
397 /// Texture Guid to replace with the output of the media stream 486 /// Texture Guid to replace with the output of the media stream
398 /// </summary> 487 /// </summary>
399 public UUID MediaID { 488 public UUID MediaID
400 get { 489 {
490 get
491 {
401 return _mediaID; 492 return _mediaID;
402 } 493 }
403 set { 494 set
495 {
404 _mediaID = value; 496 _mediaID = value;
405 } 497 }
406 } 498 }
@@ -408,11 +500,14 @@ namespace OpenSim.Framework
408 /// <summary> 500 /// <summary>
409 /// URL to the media file to display 501 /// URL to the media file to display
410 /// </summary> 502 /// </summary>
411 public string MediaURL { 503 public string MediaURL
412 get { 504 {
505 get
506 {
413 return _mediaURL; 507 return _mediaURL;
414 } 508 }
415 set { 509 set
510 {
416 _mediaURL = value; 511 _mediaURL = value;
417 } 512 }
418 } 513 }
@@ -432,11 +527,14 @@ namespace OpenSim.Framework
432 /// <summary> 527 /// <summary>
433 /// URL to the shoutcast music stream to play on the parcel 528 /// URL to the shoutcast music stream to play on the parcel
434 /// </summary> 529 /// </summary>
435 public string MusicURL { 530 public string MusicURL
436 get { 531 {
532 get
533 {
437 return _musicURL; 534 return _musicURL;
438 } 535 }
439 set { 536 set
537 {
440 _musicURL = value; 538 _musicURL = value;
441 } 539 }
442 } 540 }
@@ -445,11 +543,14 @@ namespace OpenSim.Framework
445 /// Owner Avatar or Group of the parcel. Naturally, all land masses must be 543 /// Owner Avatar or Group of the parcel. Naturally, all land masses must be
446 /// owned by someone 544 /// owned by someone
447 /// </summary> 545 /// </summary>
448 public UUID OwnerID { 546 public UUID OwnerID
449 get { 547 {
548 get
549 {
450 return _ownerID; 550 return _ownerID;
451 } 551 }
452 set { 552 set
553 {
453 _ownerID = value; 554 _ownerID = value;
454 } 555 }
455 } 556 }
@@ -457,11 +558,14 @@ namespace OpenSim.Framework
457 /// <summary> 558 /// <summary>
458 /// List of access data for the parcel. User data, some bitflags, and a time 559 /// List of access data for the parcel. User data, some bitflags, and a time
459 /// </summary> 560 /// </summary>
460 public List<LandAccessEntry> ParcelAccessList { 561 public List<LandAccessEntry> ParcelAccessList
461 get { 562 {
563 get
564 {
462 return _parcelAccessList; 565 return _parcelAccessList;
463 } 566 }
464 set { 567 set
568 {
465 _parcelAccessList = value; 569 _parcelAccessList = value;
466 } 570 }
467 } 571 }
@@ -469,11 +573,14 @@ namespace OpenSim.Framework
469 /// <summary> 573 /// <summary>
470 /// How long in hours a Pass to the parcel is given 574 /// How long in hours a Pass to the parcel is given
471 /// </summary> 575 /// </summary>
472 public float PassHours { 576 public float PassHours
473 get { 577 {
578 get
579 {
474 return _passHours; 580 return _passHours;
475 } 581 }
476 set { 582 set
583 {
477 _passHours = value; 584 _passHours = value;
478 } 585 }
479 } 586 }
@@ -481,11 +588,14 @@ namespace OpenSim.Framework
481 /// <summary> 588 /// <summary>
482 /// Price to purchase a Pass to a restricted parcel 589 /// Price to purchase a Pass to a restricted parcel
483 /// </summary> 590 /// </summary>
484 public int PassPrice { 591 public int PassPrice
485 get { 592 {
593 get
594 {
486 return _passPrice; 595 return _passPrice;
487 } 596 }
488 set { 597 set
598 {
489 _passPrice = value; 599 _passPrice = value;
490 } 600 }
491 } 601 }
@@ -493,11 +603,14 @@ namespace OpenSim.Framework
493 /// <summary> 603 /// <summary>
494 /// When the parcel is being sold, this is the price to purchase the parcel 604 /// When the parcel is being sold, this is the price to purchase the parcel
495 /// </summary> 605 /// </summary>
496 public int SalePrice { 606 public int SalePrice
497 get { 607 {
608 get
609 {
498 return _salePrice; 610 return _salePrice;
499 } 611 }
500 set { 612 set
613 {
501 _salePrice = value; 614 _salePrice = value;
502 } 615 }
503 } 616 }
@@ -506,11 +619,14 @@ namespace OpenSim.Framework
506 /// Number of meters^2 in the Simulator 619 /// Number of meters^2 in the Simulator
507 /// </summary> 620 /// </summary>
508 [XmlIgnore] 621 [XmlIgnore]
509 public int SimwideArea { 622 public int SimwideArea
510 get { 623 {
624 get
625 {
511 return _simwideArea; 626 return _simwideArea;
512 } 627 }
513 set { 628 set
629 {
514 _simwideArea = value; 630 _simwideArea = value;
515 } 631 }
516 } 632 }
@@ -519,11 +635,14 @@ namespace OpenSim.Framework
519 /// Number of SceneObjectPart in the Simulator 635 /// Number of SceneObjectPart in the Simulator
520 /// </summary> 636 /// </summary>
521 [XmlIgnore] 637 [XmlIgnore]
522 public int SimwidePrims { 638 public int SimwidePrims
523 get { 639 {
640 get
641 {
524 return _simwidePrims; 642 return _simwidePrims;
525 } 643 }
526 set { 644 set
645 {
527 _simwidePrims = value; 646 _simwidePrims = value;
528 } 647 }
529 } 648 }
@@ -531,11 +650,14 @@ namespace OpenSim.Framework
531 /// <summary> 650 /// <summary>
532 /// ID of the snapshot used in the client parcel dialog of the parcel 651 /// ID of the snapshot used in the client parcel dialog of the parcel
533 /// </summary> 652 /// </summary>
534 public UUID SnapshotID { 653 public UUID SnapshotID
535 get { 654 {
655 get
656 {
536 return _snapshotID; 657 return _snapshotID;
537 } 658 }
538 set { 659 set
660 {
539 _snapshotID = value; 661 _snapshotID = value;
540 } 662 }
541 } 663 }
@@ -544,11 +666,14 @@ namespace OpenSim.Framework
544 /// When teleporting is restricted to a certain point, this is the location 666 /// When teleporting is restricted to a certain point, this is the location
545 /// that the user will be redirected to 667 /// that the user will be redirected to
546 /// </summary> 668 /// </summary>
547 public Vector3 UserLocation { 669 public Vector3 UserLocation
548 get { 670 {
671 get
672 {
549 return _userLocation; 673 return _userLocation;
550 } 674 }
551 set { 675 set
676 {
552 _userLocation = value; 677 _userLocation = value;
553 } 678 }
554 } 679 }
@@ -557,11 +682,14 @@ namespace OpenSim.Framework
557 /// When teleporting is restricted to a certain point, this is the rotation 682 /// When teleporting is restricted to a certain point, this is the rotation
558 /// that the user will be positioned 683 /// that the user will be positioned
559 /// </summary> 684 /// </summary>
560 public Vector3 UserLookAt { 685 public Vector3 UserLookAt
561 get { 686 {
687 get
688 {
562 return _userLookAt; 689 return _userLookAt;
563 } 690 }
564 set { 691 set
692 {
565 _userLookAt = value; 693 _userLookAt = value;
566 } 694 }
567 } 695 }
@@ -570,11 +698,14 @@ namespace OpenSim.Framework
570 /// Autoreturn number of minutes to return SceneObjectGroup that are owned by someone who doesn't own 698 /// Autoreturn number of minutes to return SceneObjectGroup that are owned by someone who doesn't own
571 /// the parcel and isn't set to the same 'group' as the parcel. 699 /// the parcel and isn't set to the same 'group' as the parcel.
572 /// </summary> 700 /// </summary>
573 public int OtherCleanTime { 701 public int OtherCleanTime
574 get { 702 {
703 get
704 {
575 return _otherCleanTime; 705 return _otherCleanTime;
576 } 706 }
577 set { 707 set
708 {
578 _otherCleanTime = value; 709 _otherCleanTime = value;
579 } 710 }
580 } 711 }
@@ -582,11 +713,14 @@ namespace OpenSim.Framework
582 /// <summary> 713 /// <summary>
583 /// parcel media description 714 /// parcel media description
584 /// </summary> 715 /// </summary>
585 public string MediaDescription { 716 public string MediaDescription
586 get { 717 {
718 get
719 {
587 return _mediaDescription; 720 return _mediaDescription;
588 } 721 }
589 set { 722 set
723 {
590 _mediaDescription = value; 724 _mediaDescription = value;
591 } 725 }
592 } 726 }
@@ -622,7 +756,7 @@ namespace OpenSim.Framework
622 landData._mediaURL = _mediaURL; 756 landData._mediaURL = _mediaURL;
623 landData._musicURL = _musicURL; 757 landData._musicURL = _musicURL;
624 landData._ownerID = _ownerID; 758 landData._ownerID = _ownerID;
625 landData._bitmap = (byte[]) _bitmap.Clone(); 759 landData._bitmap = (byte[])_bitmap.Clone();
626 landData._description = _description; 760 landData._description = _description;
627 landData._flags = _flags; 761 landData._flags = _flags;
628 landData._name = _name; 762 landData._name = _name;
@@ -643,6 +777,7 @@ namespace OpenSim.Framework
643 landData._obscureMedia = _obscureMedia; 777 landData._obscureMedia = _obscureMedia;
644 landData._simwideArea = _simwideArea; 778 landData._simwideArea = _simwideArea;
645 landData._simwidePrims = _simwidePrims; 779 landData._simwidePrims = _simwidePrims;
780 landData._dwell = _dwell;
646 781
647 landData._parcelAccessList.Clear(); 782 landData._parcelAccessList.Clear();
648 foreach (LandAccessEntry entry in _parcelAccessList) 783 foreach (LandAccessEntry entry in _parcelAccessList)
diff --git a/OpenSim/Framework/Monitoring/BaseStatsCollector.cs b/OpenSim/Framework/Monitoring/BaseStatsCollector.cs
index 9ee0876..446e3c0 100644
--- a/OpenSim/Framework/Monitoring/BaseStatsCollector.cs
+++ b/OpenSim/Framework/Monitoring/BaseStatsCollector.cs
@@ -43,27 +43,32 @@ 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.Append( 46 sb.AppendFormat(
47 string.Format(
48 "Allocated to OpenSim objects: {0} MB\n", 47 "Allocated to OpenSim objects: {0} MB\n",
49 Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0))); 48 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));
50 57
51 Process myprocess = Process.GetCurrentProcess(); 58 Process myprocess = Process.GetCurrentProcess();
52 if (!myprocess.HasExited) 59 if (!myprocess.HasExited)
53 { 60 {
54 myprocess.Refresh(); 61 myprocess.Refresh();
55 sb.Append( 62 sb.AppendFormat(
56 string.Format(
57 "Process memory: Physical {0} MB \t Paged {1} MB \t Virtual {2} MB\n", 63 "Process memory: Physical {0} MB \t Paged {1} MB \t Virtual {2} MB\n",
58 Math.Round(Process.GetCurrentProcess().WorkingSet64 / 1024.0 / 1024.0), 64 Math.Round(Process.GetCurrentProcess().WorkingSet64 / 1024.0 / 1024.0),
59 Math.Round(Process.GetCurrentProcess().PagedMemorySize64 / 1024.0 / 1024.0), 65 Math.Round(Process.GetCurrentProcess().PagedMemorySize64 / 1024.0 / 1024.0),
60 Math.Round(Process.GetCurrentProcess().VirtualMemorySize64 / 1024.0 / 1024.0))); 66 Math.Round(Process.GetCurrentProcess().VirtualMemorySize64 / 1024.0 / 1024.0));
61 sb.Append( 67 sb.AppendFormat(
62 string.Format(
63 "Peak process memory: Physical {0} MB \t Paged {1} MB \t Virtual {2} MB\n", 68 "Peak process memory: Physical {0} MB \t Paged {1} MB \t Virtual {2} MB\n",
64 Math.Round(Process.GetCurrentProcess().PeakWorkingSet64 / 1024.0 / 1024.0), 69 Math.Round(Process.GetCurrentProcess().PeakWorkingSet64 / 1024.0 / 1024.0),
65 Math.Round(Process.GetCurrentProcess().PeakPagedMemorySize64 / 1024.0 / 1024.0), 70 Math.Round(Process.GetCurrentProcess().PeakPagedMemorySize64 / 1024.0 / 1024.0),
66 Math.Round(Process.GetCurrentProcess().PeakVirtualMemorySize64 / 1024.0 / 1024.0))); 71 Math.Round(Process.GetCurrentProcess().PeakVirtualMemorySize64 / 1024.0 / 1024.0));
67 } 72 }
68 else 73 else
69 sb.Append("Process reported as Exited \n"); 74 sb.Append("Process reported as Exited \n");
diff --git a/OpenSim/Framework/Monitoring/MemoryWatchdog.cs b/OpenSim/Framework/Monitoring/MemoryWatchdog.cs
index a23cf1f..c6010cd 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 /// Average memory churn in bytes per millisecond. 63 /// Last memory churn in bytes per millisecond.
64 /// </summary> 64 /// </summary>
65 public static double AverageMemoryChurn 65 public static double AverageMemoryChurn
66 { 66 {
@@ -68,6 +68,14 @@ 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>
71 /// Maximum number of statistical samples. 79 /// Maximum number of statistical samples.
72 /// </summary> 80 /// </summary>
73 /// <remarks> 81 /// <remarks>
diff --git a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs
index cdd7cc7..aa86202 100644
--- a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs
+++ b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs
@@ -355,10 +355,25 @@ 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}", 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",
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 sb.Append(Environment.NewLine); 361
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 }
362 377
363 /* 378 /*
364 sb.Append(Environment.NewLine); 379 sb.Append(Environment.NewLine);
diff --git a/OpenSim/Framework/Monitoring/StatsManager.cs b/OpenSim/Framework/Monitoring/StatsManager.cs
index d78fa6a..4844336 100644
--- a/OpenSim/Framework/Monitoring/StatsManager.cs
+++ b/OpenSim/Framework/Monitoring/StatsManager.cs
@@ -25,6 +25,9 @@
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
28namespace OpenSim.Framework.Monitoring 31namespace OpenSim.Framework.Monitoring
29{ 32{
30 /// <summary> 33 /// <summary>
@@ -32,6 +35,24 @@ namespace OpenSim.Framework.Monitoring
32 /// </summary> 35 /// </summary>
33 public class StatsManager 36 public class StatsManager
34 { 37 {
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
35 private static AssetStatsCollector assetStats; 56 private static AssetStatsCollector assetStats;
36 private static UserStatsCollector userStats; 57 private static UserStatsCollector userStats;
37 private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector(); 58 private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector();
@@ -40,6 +61,75 @@ namespace OpenSim.Framework.Monitoring
40 public static UserStatsCollector UserStats { get { return userStats; } } 61 public static UserStatsCollector UserStats { get { return userStats; } }
41 public static SimExtraStatsCollector SimExtraStats { get { return simExtraStats; } } 62 public static SimExtraStatsCollector SimExtraStats { get { return simExtraStats; } }
42 63
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
43 /// <summary> 133 /// <summary>
44 /// Start collecting statistics related to assets. 134 /// Start collecting statistics related to assets.
45 /// Should only be called once. 135 /// Should only be called once.
@@ -61,5 +151,275 @@ namespace OpenSim.Framework.Monitoring
61 151
62 return userStats; 152 return userStats;
63 } 153 }
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 }
64 } 424 }
65} \ No newline at end of file 425} \ No newline at end of file
diff --git a/OpenSim/Framework/Monitoring/Watchdog.cs b/OpenSim/Framework/Monitoring/Watchdog.cs
index b709baa..28d6d5c 100644
--- a/OpenSim/Framework/Monitoring/Watchdog.cs
+++ b/OpenSim/Framework/Monitoring/Watchdog.cs
@@ -89,6 +89,17 @@ 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 }
92 } 103 }
93 104
94 /// <summary> 105 /// <summary>
@@ -220,7 +231,25 @@ namespace OpenSim.Framework.Monitoring
220 private static bool RemoveThread(int threadID) 231 private static bool RemoveThread(int threadID)
221 { 232 {
222 lock (m_threads) 233 lock (m_threads)
223 return m_threads.Remove(threadID); 234 {
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 }
224 } 253 }
225 254
226 public static bool AbortThread(int threadID) 255 public static bool AbortThread(int threadID)
@@ -335,7 +364,9 @@ namespace OpenSim.Framework.Monitoring
335 if (callbackInfos == null) 364 if (callbackInfos == null)
336 callbackInfos = new List<ThreadWatchdogInfo>(); 365 callbackInfos = new List<ThreadWatchdogInfo>();
337 366
338 callbackInfos.Add(threadInfo); 367 // Send a copy of the watchdog info to prevent race conditions where the watchdog
368 // thread updates the monitoring info after an alarm has been sent out.
369 callbackInfos.Add(new ThreadWatchdogInfo(threadInfo));
339 } 370 }
340 } 371 }
341 } 372 }
diff --git a/OpenSim/Framework/Pool.cs b/OpenSim/Framework/Pool.cs
new file mode 100644
index 0000000..5484f5c
--- /dev/null
+++ b/OpenSim/Framework/Pool.cs
@@ -0,0 +1,91 @@
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
new file mode 100644
index 0000000..a3089b0
--- /dev/null
+++ b/OpenSim/Framework/RegionFlags.cs
@@ -0,0 +1,53 @@
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 4bde7be..e7bed6a 100644
--- a/OpenSim/Framework/RegionInfo.cs
+++ b/OpenSim/Framework/RegionInfo.cs
@@ -122,10 +122,13 @@ 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;
125 private int m_nonphysPrimMax = 0; 126 private int m_nonphysPrimMax = 0;
127 private float m_physPrimMin = 0;
126 private int m_physPrimMax = 0; 128 private int m_physPrimMax = 0;
127 private bool m_clampPrimSize = false; 129 private bool m_clampPrimSize = false;
128 private int m_objectCapacity = 0; 130 private int m_objectCapacity = 0;
131 private int m_linksetCapacity = 0;
129 private int m_agentCapacity = 0; 132 private int m_agentCapacity = 0;
130 private string m_regionType = String.Empty; 133 private string m_regionType = String.Empty;
131 private RegionLightShareData m_windlight = new RegionLightShareData(); 134 private RegionLightShareData m_windlight = new RegionLightShareData();
@@ -287,11 +290,21 @@ namespace OpenSim.Framework
287 set { m_windlight = value; } 290 set { m_windlight = value; }
288 } 291 }
289 292
293 public float NonphysPrimMin
294 {
295 get { return m_nonphysPrimMin; }
296 }
297
290 public int NonphysPrimMax 298 public int NonphysPrimMax
291 { 299 {
292 get { return m_nonphysPrimMax; } 300 get { return m_nonphysPrimMax; }
293 } 301 }
294 302
303 public float PhysPrimMin
304 {
305 get { return m_physPrimMin; }
306 }
307
295 public int PhysPrimMax 308 public int PhysPrimMax
296 { 309 {
297 get { return m_physPrimMax; } 310 get { return m_physPrimMax; }
@@ -307,6 +320,11 @@ namespace OpenSim.Framework
307 get { return m_objectCapacity; } 320 get { return m_objectCapacity; }
308 } 321 }
309 322
323 public int LinksetCapacity
324 {
325 get { return m_linksetCapacity; }
326 }
327
310 public int AgentCapacity 328 public int AgentCapacity
311 { 329 {
312 get { return m_agentCapacity; } 330 get { return m_agentCapacity; }
@@ -625,16 +643,31 @@ namespace OpenSim.Framework
625 m_regionType = config.GetString("RegionType", String.Empty); 643 m_regionType = config.GetString("RegionType", String.Empty);
626 allKeys.Remove("RegionType"); 644 allKeys.Remove("RegionType");
627 645
628 // Prim stuff 646 #region Prim stuff
629 // 647
630 m_nonphysPrimMax = config.GetInt("NonphysicalPrimMax", 0); 648 m_nonphysPrimMin = config.GetFloat("NonPhysicalPrimMin", 0);
631 allKeys.Remove("NonphysicalPrimMax"); 649 allKeys.Remove("NonPhysicalPrimMin");
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
632 m_physPrimMax = config.GetInt("PhysicalPrimMax", 0); 657 m_physPrimMax = config.GetInt("PhysicalPrimMax", 0);
633 allKeys.Remove("PhysicalPrimMax"); 658 allKeys.Remove("PhysicalPrimMax");
659
634 m_clampPrimSize = config.GetBoolean("ClampPrimSize", false); 660 m_clampPrimSize = config.GetBoolean("ClampPrimSize", false);
635 allKeys.Remove("ClampPrimSize"); 661 allKeys.Remove("ClampPrimSize");
662
636 m_objectCapacity = config.GetInt("MaxPrims", 15000); 663 m_objectCapacity = config.GetInt("MaxPrims", 15000);
637 allKeys.Remove("MaxPrims"); 664 allKeys.Remove("MaxPrims");
665
666 m_linksetCapacity = config.GetInt("LinksetPrims", 0);
667 allKeys.Remove("LinksetPrims");
668
669 #endregion
670
638 m_agentCapacity = config.GetInt("MaxAgents", 100); 671 m_agentCapacity = config.GetInt("MaxAgents", 100);
639 allKeys.Remove("MaxAgents"); 672 allKeys.Remove("MaxAgents");
640 673
@@ -673,16 +706,27 @@ namespace OpenSim.Framework
673 706
674 config.Set("ExternalHostName", m_externalHostName); 707 config.Set("ExternalHostName", m_externalHostName);
675 708
676 if (m_nonphysPrimMax != 0) 709 if (m_nonphysPrimMin > 0)
710 config.Set("NonphysicalPrimMax", m_nonphysPrimMin);
711
712 if (m_nonphysPrimMax > 0)
677 config.Set("NonphysicalPrimMax", m_nonphysPrimMax); 713 config.Set("NonphysicalPrimMax", m_nonphysPrimMax);
678 if (m_physPrimMax != 0) 714
715 if (m_physPrimMin > 0)
716 config.Set("PhysicalPrimMax", m_physPrimMin);
717
718 if (m_physPrimMax > 0)
679 config.Set("PhysicalPrimMax", m_physPrimMax); 719 config.Set("PhysicalPrimMax", m_physPrimMax);
720
680 config.Set("ClampPrimSize", m_clampPrimSize.ToString()); 721 config.Set("ClampPrimSize", m_clampPrimSize.ToString());
681 722
682 if (m_objectCapacity != 0) 723 if (m_objectCapacity > 0)
683 config.Set("MaxPrims", m_objectCapacity); 724 config.Set("MaxPrims", m_objectCapacity);
684 725
685 if (m_agentCapacity != 0) 726 if (m_linksetCapacity > 0)
727 config.Set("LinksetPrims", m_linksetCapacity);
728
729 if (m_agentCapacity > 0)
686 config.Set("MaxAgents", m_agentCapacity); 730 config.Set("MaxAgents", m_agentCapacity);
687 731
688 if (ScopeID != UUID.Zero) 732 if (ScopeID != UUID.Zero)
@@ -759,9 +803,15 @@ namespace OpenSim.Framework
759 configMember.addConfigurationOption("lastmap_refresh", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, 803 configMember.addConfigurationOption("lastmap_refresh", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY,
760 "Last Map Refresh", Util.UnixTimeSinceEpoch().ToString(), true); 804 "Last Map Refresh", Util.UnixTimeSinceEpoch().ToString(), true);
761 805
806 configMember.addConfigurationOption("nonphysical_prim_min", ConfigurationOption.ConfigurationTypes.TYPE_FLOAT,
807 "Minimum size for nonphysical prims", m_nonphysPrimMin.ToString(), true);
808
762 configMember.addConfigurationOption("nonphysical_prim_max", ConfigurationOption.ConfigurationTypes.TYPE_INT32, 809 configMember.addConfigurationOption("nonphysical_prim_max", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
763 "Maximum size for nonphysical prims", m_nonphysPrimMax.ToString(), true); 810 "Maximum size for nonphysical prims", m_nonphysPrimMax.ToString(), true);
764 811
812 configMember.addConfigurationOption("physical_prim_min", ConfigurationOption.ConfigurationTypes.TYPE_FLOAT,
813 "Minimum size for nonphysical prims", m_physPrimMin.ToString(), true);
814
765 configMember.addConfigurationOption("physical_prim_max", ConfigurationOption.ConfigurationTypes.TYPE_INT32, 815 configMember.addConfigurationOption("physical_prim_max", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
766 "Maximum size for physical prims", m_physPrimMax.ToString(), true); 816 "Maximum size for physical prims", m_physPrimMax.ToString(), true);
767 817
@@ -771,6 +821,9 @@ namespace OpenSim.Framework
771 configMember.addConfigurationOption("object_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32, 821 configMember.addConfigurationOption("object_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
772 "Max objects this sim will hold", m_objectCapacity.ToString(), true); 822 "Max objects this sim will hold", m_objectCapacity.ToString(), true);
773 823
824 configMember.addConfigurationOption("linkset_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
825 "Max prims an object will hold", m_linksetCapacity.ToString(), true);
826
774 configMember.addConfigurationOption("agent_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32, 827 configMember.addConfigurationOption("agent_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
775 "Max avatars this sim will hold", m_agentCapacity.ToString(), true); 828 "Max avatars this sim will hold", m_agentCapacity.ToString(), true);
776 829
@@ -892,6 +945,9 @@ namespace OpenSim.Framework
892 case "object_capacity": 945 case "object_capacity":
893 m_objectCapacity = (int)configuration_result; 946 m_objectCapacity = (int)configuration_result;
894 break; 947 break;
948 case "linkset_capacity":
949 m_linksetCapacity = (int)configuration_result;
950 break;
895 case "agent_capacity": 951 case "agent_capacity":
896 m_agentCapacity = (int)configuration_result; 952 m_agentCapacity = (int)configuration_result;
897 break; 953 break;
diff --git a/OpenSim/Framework/Serialization/ArchiveConstants.cs b/OpenSim/Framework/Serialization/ArchiveConstants.cs
index 2c5e001..48f1c4f 100644
--- a/OpenSim/Framework/Serialization/ArchiveConstants.cs
+++ b/OpenSim/Framework/Serialization/ArchiveConstants.cs
@@ -53,6 +53,11 @@ 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>
56 /// Path for the prims file 61 /// Path for the prims file
57 /// </value> 62 /// </value>
58 public const string OBJECTS_PATH = "objects/"; 63 public const string OBJECTS_PATH = "objects/";
diff --git a/OpenSim/Framework/Serialization/External/OspResolver.cs b/OpenSim/Framework/Serialization/External/OspResolver.cs
index d31d27c..fa7160f 100644
--- a/OpenSim/Framework/Serialization/External/OspResolver.cs
+++ b/OpenSim/Framework/Serialization/External/OspResolver.cs
@@ -65,9 +65,14 @@ 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 {
68 return MakeOspa(account.FirstName, account.LastName); 69 return MakeOspa(account.FirstName, account.LastName);
70 }
69// else 71// else
72// {
70// m_log.WarnFormat("[OSP RESOLVER]: No user account for {0}", userId); 73// m_log.WarnFormat("[OSP RESOLVER]: No user account for {0}", userId);
74// System.Console.WriteLine("[OSP RESOLVER]: No user account for {0}", userId);
75// }
71 76
72 return null; 77 return null;
73 } 78 }
@@ -79,10 +84,13 @@ namespace OpenSim.Framework.Serialization
79 /// <returns></returns> 84 /// <returns></returns>
80 public static string MakeOspa(string firstName, string lastName) 85 public static string MakeOspa(string firstName, string lastName)
81 { 86 {
82// m_log.DebugFormat("[OSP RESOLVER]: Making OSPA for {0} {1}", firstName, lastName); 87 string ospa
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);
83 92
84 return 93 return ospa;
85 OSPA_PREFIX + OSPA_NAME_KEY + OSPA_PAIR_SEPARATOR + firstName + OSPA_NAME_VALUE_SEPARATOR + lastName;
86 } 94 }
87 95
88 /// <summary> 96 /// <summary>
diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
index cf19002..605909d 100644
--- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs
+++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs
@@ -96,11 +96,6 @@ 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
104 public BaseOpenSimServer() 99 public BaseOpenSimServer()
105 { 100 {
106 m_startuptime = DateTime.Now; 101 m_startuptime = DateTime.Now;
@@ -177,10 +172,6 @@ namespace OpenSim.Framework.Servers
177 "show info", 172 "show info",
178 "Show general information about the server", HandleShow); 173 "Show general information about the server", HandleShow);
179 174
180 m_console.Commands.AddCommand("General", false, "show stats",
181 "show stats",
182 "Show statistics", HandleShow);
183
184 m_console.Commands.AddCommand("General", false, "show threads", 175 m_console.Commands.AddCommand("General", false, "show threads",
185 "show threads", 176 "show threads",
186 "Show thread status", HandleShow); 177 "Show thread status", HandleShow);
@@ -201,8 +192,19 @@ namespace OpenSim.Framework.Servers
201 "threads show", 192 "threads show",
202 "Show thread status. Synonym for \"show threads\"", 193 "Show thread status. Synonym for \"show threads\"",
203 (string module, string[] args) => Notice(GetThreadsReport())); 194 (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);
204 } 200 }
205 } 201 }
202
203 private void HandleForceGc(string module, string[] args)
204 {
205 MainConsole.Instance.Output("Manually invoking runtime garbage collection");
206 GC.Collect();
207 }
206 208
207 /// <summary> 209 /// <summary>
208 /// Should be overriden and referenced by descendents if they need to perform extra shutdown processing 210 /// Should be overriden and referenced by descendents if they need to perform extra shutdown processing
@@ -226,12 +228,7 @@ namespace OpenSim.Framework.Servers
226 { 228 {
227 StringBuilder sb = new StringBuilder("DIAGNOSTICS\n\n"); 229 StringBuilder sb = new StringBuilder("DIAGNOSTICS\n\n");
228 sb.Append(GetUptimeReport()); 230 sb.Append(GetUptimeReport());
229 231 sb.Append(StatsManager.SimExtraStats.Report());
230 if (m_stats != null)
231 {
232 sb.Append(m_stats.Report());
233 }
234
235 sb.Append(Environment.NewLine); 232 sb.Append(Environment.NewLine);
236 sb.Append(GetThreadsReport()); 233 sb.Append(GetThreadsReport());
237 234
@@ -382,10 +379,6 @@ namespace OpenSim.Framework.Servers
382 { 379 {
383 Notice("set log level [level] - change the console logging level only. For example, off or debug."); 380 Notice("set log level [level] - change the console logging level only. For example, off or debug.");
384 Notice("show info - show server information (e.g. startup path)."); 381 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
389 Notice("show threads - list tracked threads"); 382 Notice("show threads - list tracked threads");
390 Notice("show uptime - show server startup time and uptime."); 383 Notice("show uptime - show server startup time and uptime.");
391 Notice("show version - show server version."); 384 Notice("show version - show server version.");
@@ -409,11 +402,6 @@ namespace OpenSim.Framework.Servers
409 ShowInfo(); 402 ShowInfo();
410 break; 403 break;
411 404
412 case "stats":
413 if (m_stats != null)
414 Notice(m_stats.Report());
415 break;
416
417 case "threads": 405 case "threads":
418 Notice(GetThreadsReport()); 406 Notice(GetThreadsReport());
419 break; 407 break;
@@ -604,8 +592,7 @@ namespace OpenSim.Framework.Servers
604 592
605 public string osSecret { 593 public string osSecret {
606 // Secret uuid for the simulator 594 // Secret uuid for the simulator
607 get { return m_osSecret; } 595 get { return m_osSecret; }
608
609 } 596 }
610 597
611 public string StatReport(IOSHttpRequest httpRequest) 598 public string StatReport(IOSHttpRequest httpRequest)
@@ -613,11 +600,11 @@ namespace OpenSim.Framework.Servers
613 // If we catch a request for "callback", wrap the response in the value for jsonp 600 // If we catch a request for "callback", wrap the response in the value for jsonp
614 if (httpRequest.Query.ContainsKey("callback")) 601 if (httpRequest.Query.ContainsKey("callback"))
615 { 602 {
616 return httpRequest.Query["callback"].ToString() + "(" + m_stats.XReport((DateTime.Now - m_startuptime).ToString() , m_version) + ");"; 603 return httpRequest.Query["callback"].ToString() + "(" + StatsManager.SimExtraStats.XReport((DateTime.Now - m_startuptime).ToString() , m_version) + ");";
617 } 604 }
618 else 605 else
619 { 606 {
620 return m_stats.XReport((DateTime.Now - m_startuptime).ToString() , m_version); 607 return StatsManager.SimExtraStats.XReport((DateTime.Now - m_startuptime).ToString() , m_version);
621 } 608 }
622 } 609 }
623 610
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
index 788a0b9..3198891 100644
--- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
+++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs
@@ -54,8 +54,23 @@ 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>
57 public int DebugLevel { get; set; } 63 public int DebugLevel { get; set; }
58 64
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
59 private volatile int NotSocketErrors = 0; 74 private volatile int NotSocketErrors = 0;
60 public volatile bool HTTPDRunning = false; 75 public volatile bool HTTPDRunning = false;
61 76
@@ -67,7 +82,7 @@ namespace OpenSim.Framework.Servers.HttpServer
67 protected Dictionary<string, LLSDMethod> m_llsdHandlers = new Dictionary<string, LLSDMethod>(); 82 protected Dictionary<string, LLSDMethod> m_llsdHandlers = new Dictionary<string, LLSDMethod>();
68 protected Dictionary<string, IRequestHandler> m_streamHandlers = new Dictionary<string, IRequestHandler>(); 83 protected Dictionary<string, IRequestHandler> m_streamHandlers = new Dictionary<string, IRequestHandler>();
69 protected Dictionary<string, GenericHTTPMethod> m_HTTPHandlers = new Dictionary<string, GenericHTTPMethod>(); 84 protected Dictionary<string, GenericHTTPMethod> m_HTTPHandlers = new Dictionary<string, GenericHTTPMethod>();
70 protected Dictionary<string, IHttpAgentHandler> m_agentHandlers = new Dictionary<string, IHttpAgentHandler>(); 85// protected Dictionary<string, IHttpAgentHandler> m_agentHandlers = new Dictionary<string, IHttpAgentHandler>();
71 protected Dictionary<string, PollServiceEventArgs> m_pollHandlers = 86 protected Dictionary<string, PollServiceEventArgs> m_pollHandlers =
72 new Dictionary<string, PollServiceEventArgs>(); 87 new Dictionary<string, PollServiceEventArgs>();
73 88
@@ -245,29 +260,29 @@ namespace OpenSim.Framework.Servers.HttpServer
245 return new List<string>(m_pollHandlers.Keys); 260 return new List<string>(m_pollHandlers.Keys);
246 } 261 }
247 262
248 // Note that the agent string is provided simply to differentiate 263// // Note that the agent string is provided simply to differentiate
249 // the handlers - it is NOT required to be an actual agent header 264// // the handlers - it is NOT required to be an actual agent header
250 // value. 265// // value.
251 public bool AddAgentHandler(string agent, IHttpAgentHandler handler) 266// public bool AddAgentHandler(string agent, IHttpAgentHandler handler)
252 { 267// {
253 lock (m_agentHandlers) 268// lock (m_agentHandlers)
254 { 269// {
255 if (!m_agentHandlers.ContainsKey(agent)) 270// if (!m_agentHandlers.ContainsKey(agent))
256 { 271// {
257 m_agentHandlers.Add(agent, handler); 272// m_agentHandlers.Add(agent, handler);
258 return true; 273// return true;
259 } 274// }
260 } 275// }
261 276//
262 //must already have a handler for that path so return false 277// //must already have a handler for that path so return false
263 return false; 278// return false;
264 } 279// }
265 280//
266 public List<string> GetAgentHandlerKeys() 281// public List<string> GetAgentHandlerKeys()
267 { 282// {
268 lock (m_agentHandlers) 283// lock (m_agentHandlers)
269 return new List<string>(m_agentHandlers.Keys); 284// return new List<string>(m_agentHandlers.Keys);
270 } 285// }
271 286
272 public bool AddLLSDHandler(string path, LLSDMethod handler) 287 public bool AddLLSDHandler(string path, LLSDMethod handler)
273 { 288 {
@@ -296,6 +311,8 @@ namespace OpenSim.Framework.Servers.HttpServer
296 311
297 private void OnRequest(object source, RequestEventArgs args) 312 private void OnRequest(object source, RequestEventArgs args)
298 { 313 {
314 RequestNumber++;
315
299 try 316 try
300 { 317 {
301 IHttpClientContext context = (IHttpClientContext)source; 318 IHttpClientContext context = (IHttpClientContext)source;
@@ -406,7 +423,6 @@ namespace OpenSim.Framework.Servers.HttpServer
406 string requestMethod = request.HttpMethod; 423 string requestMethod = request.HttpMethod;
407 string uriString = request.RawUrl; 424 string uriString = request.RawUrl;
408 425
409// string reqnum = "unknown";
410 int requestStartTick = Environment.TickCount; 426 int requestStartTick = Environment.TickCount;
411 427
412 // Will be adjusted later on. 428 // Will be adjusted later on.
@@ -423,22 +439,22 @@ namespace OpenSim.Framework.Servers.HttpServer
423 439
424 Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", true); 440 Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", true);
425 441
426 // This is the REST agent interface. We require an agent to properly identify 442// // This is the REST agent interface. We require an agent to properly identify
427 // itself. If the REST handler recognizes the prefix it will attempt to 443// // itself. If the REST handler recognizes the prefix it will attempt to
428 // satisfy the request. If it is not recognizable, and no damage has occurred 444// // satisfy the request. If it is not recognizable, and no damage has occurred
429 // the request can be passed through to the other handlers. This is a low 445// // the request can be passed through to the other handlers. This is a low
430 // probability event; if a request is matched it is normally expected to be 446// // probability event; if a request is matched it is normally expected to be
431 // handled 447// // handled
432 IHttpAgentHandler agentHandler; 448// IHttpAgentHandler agentHandler;
433 449//
434 if (TryGetAgentHandler(request, response, out agentHandler)) 450// if (TryGetAgentHandler(request, response, out agentHandler))
435 { 451// {
436 if (HandleAgentRequest(agentHandler, request, response)) 452// if (HandleAgentRequest(agentHandler, request, response))
437 { 453// {
438 requestEndTick = Environment.TickCount; 454// requestEndTick = Environment.TickCount;
439 return; 455// return;
440 } 456// }
441 } 457// }
442 458
443 //response.KeepAlive = true; 459 //response.KeepAlive = true;
444 response.SendChunked = false; 460 response.SendChunked = false;
@@ -450,9 +466,7 @@ namespace OpenSim.Framework.Servers.HttpServer
450 if (TryGetStreamHandler(handlerKey, out requestHandler)) 466 if (TryGetStreamHandler(handlerKey, out requestHandler))
451 { 467 {
452 if (DebugLevel >= 3) 468 if (DebugLevel >= 3)
453 m_log.DebugFormat( 469 LogIncomingToStreamHandler(request, requestHandler);
454 "[BASE HTTP SERVER]: Found stream handler for {0} {1} {2} {3}",
455 request.HttpMethod, request.Url.PathAndQuery, requestHandler.Name, requestHandler.Description);
456 470
457 response.ContentType = requestHandler.ContentType; // Lets do this defaulting before in case handler has varying content type. 471 response.ContentType = requestHandler.ContentType; // Lets do this defaulting before in case handler has varying content type.
458 472
@@ -529,11 +543,8 @@ namespace OpenSim.Framework.Servers.HttpServer
529 { 543 {
530 case null: 544 case null:
531 case "text/html": 545 case "text/html":
532
533 if (DebugLevel >= 3) 546 if (DebugLevel >= 3)
534 m_log.DebugFormat( 547 LogIncomingToContentTypeHandler(request);
535 "[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
536 request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
537 548
538 buffer = HandleHTTPRequest(request, response); 549 buffer = HandleHTTPRequest(request, response);
539 break; 550 break;
@@ -541,11 +552,8 @@ namespace OpenSim.Framework.Servers.HttpServer
541 case "application/llsd+xml": 552 case "application/llsd+xml":
542 case "application/xml+llsd": 553 case "application/xml+llsd":
543 case "application/llsd+json": 554 case "application/llsd+json":
544
545 if (DebugLevel >= 3) 555 if (DebugLevel >= 3)
546 m_log.DebugFormat( 556 LogIncomingToContentTypeHandler(request);
547 "[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
548 request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
549 557
550 buffer = HandleLLSDRequests(request, response); 558 buffer = HandleLLSDRequests(request, response);
551 break; 559 break;
@@ -564,9 +572,7 @@ namespace OpenSim.Framework.Servers.HttpServer
564 if (DoWeHaveALLSDHandler(request.RawUrl)) 572 if (DoWeHaveALLSDHandler(request.RawUrl))
565 { 573 {
566 if (DebugLevel >= 3) 574 if (DebugLevel >= 3)
567 m_log.DebugFormat( 575 LogIncomingToContentTypeHandler(request);
568 "[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
569 request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
570 576
571 buffer = HandleLLSDRequests(request, response); 577 buffer = HandleLLSDRequests(request, response);
572 } 578 }
@@ -574,18 +580,14 @@ namespace OpenSim.Framework.Servers.HttpServer
574 else if (DoWeHaveAHTTPHandler(request.RawUrl)) 580 else if (DoWeHaveAHTTPHandler(request.RawUrl))
575 { 581 {
576 if (DebugLevel >= 3) 582 if (DebugLevel >= 3)
577 m_log.DebugFormat( 583 LogIncomingToContentTypeHandler(request);
578 "[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
579 request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
580 584
581 buffer = HandleHTTPRequest(request, response); 585 buffer = HandleHTTPRequest(request, response);
582 } 586 }
583 else 587 else
584 { 588 {
585 if (DebugLevel >= 3) 589 if (DebugLevel >= 3)
586 m_log.DebugFormat( 590 LogIncomingToXmlRpcHandler(request);
587 "[BASE HTTP SERVER]: Assuming a generic XMLRPC request for {0} {1}",
588 request.HttpMethod, request.Url.PathAndQuery);
589 591
590 // generic login request. 592 // generic login request.
591 buffer = HandleXmlRpcRequests(request, response); 593 buffer = HandleXmlRpcRequests(request, response);
@@ -629,11 +631,11 @@ namespace OpenSim.Framework.Servers.HttpServer
629 } 631 }
630 catch (IOException e) 632 catch (IOException e)
631 { 633 {
632 m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.Message), e); 634 m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.StackTrace), e);
633 } 635 }
634 catch (Exception e) 636 catch (Exception e)
635 { 637 {
636 m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.Message), e); 638 m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.StackTrace), e);
637 SendHTML500(response); 639 SendHTML500(response);
638 } 640 }
639 finally 641 finally
@@ -644,17 +646,93 @@ namespace OpenSim.Framework.Servers.HttpServer
644 if (tickdiff > 3000 && (requestHandler == null || requestHandler.Name == null || requestHandler.Name != "GetTexture")) 646 if (tickdiff > 3000 && (requestHandler == null || requestHandler.Name == null || requestHandler.Name != "GetTexture"))
645 { 647 {
646 m_log.InfoFormat( 648 m_log.InfoFormat(
647 "[BASE HTTP SERVER]: Slow handling of {0} {1} {2} {3} from {4} took {5}ms", 649 "[BASE HTTP SERVER]: Slow handling of {0} {1} {2} {3} {4} from {5} took {6}ms",
650 RequestNumber,
648 requestMethod, 651 requestMethod,
649 uriString, 652 uriString,
650 requestHandler != null ? requestHandler.Name : "", 653 requestHandler != null ? requestHandler.Name : "",
651 requestHandler != null ? requestHandler.Description : "", 654 requestHandler != null ? requestHandler.Description : "",
652 request.RemoteIPEndPoint.ToString(), 655 request.RemoteIPEndPoint,
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,
653 tickdiff); 664 tickdiff);
654 } 665 }
655 } 666 }
656 } 667 }
657 668
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
658 private bool TryGetStreamHandler(string handlerKey, out IRequestHandler streamHandler) 736 private bool TryGetStreamHandler(string handlerKey, out IRequestHandler streamHandler)
659 { 737 {
660 string bestMatch = null; 738 string bestMatch = null;
@@ -747,24 +825,24 @@ namespace OpenSim.Framework.Servers.HttpServer
747 } 825 }
748 } 826 }
749 827
750 private bool TryGetAgentHandler(OSHttpRequest request, OSHttpResponse response, out IHttpAgentHandler agentHandler) 828// private bool TryGetAgentHandler(OSHttpRequest request, OSHttpResponse response, out IHttpAgentHandler agentHandler)
751 { 829// {
752 agentHandler = null; 830// agentHandler = null;
753 831//
754 lock (m_agentHandlers) 832// lock (m_agentHandlers)
755 { 833// {
756 foreach (IHttpAgentHandler handler in m_agentHandlers.Values) 834// foreach (IHttpAgentHandler handler in m_agentHandlers.Values)
757 { 835// {
758 if (handler.Match(request, response)) 836// if (handler.Match(request, response))
759 { 837// {
760 agentHandler = handler; 838// agentHandler = handler;
761 return true; 839// return true;
762 } 840// }
763 } 841// }
764 } 842// }
765 843//
766 return false; 844// return false;
767 } 845// }
768 846
769 /// <summary> 847 /// <summary>
770 /// Try all the registered xmlrpc handlers when an xmlrpc request is received. 848 /// Try all the registered xmlrpc handlers when an xmlrpc request is received.
@@ -1737,21 +1815,21 @@ namespace OpenSim.Framework.Servers.HttpServer
1737 m_pollHandlers.Remove(path); 1815 m_pollHandlers.Remove(path);
1738 } 1816 }
1739 1817
1740 public bool RemoveAgentHandler(string agent, IHttpAgentHandler handler) 1818// public bool RemoveAgentHandler(string agent, IHttpAgentHandler handler)
1741 { 1819// {
1742 lock (m_agentHandlers) 1820// lock (m_agentHandlers)
1743 { 1821// {
1744 IHttpAgentHandler foundHandler; 1822// IHttpAgentHandler foundHandler;
1745 1823//
1746 if (m_agentHandlers.TryGetValue(agent, out foundHandler) && foundHandler == handler) 1824// if (m_agentHandlers.TryGetValue(agent, out foundHandler) && foundHandler == handler)
1747 { 1825// {
1748 m_agentHandlers.Remove(agent); 1826// m_agentHandlers.Remove(agent);
1749 return true; 1827// return true;
1750 } 1828// }
1751 } 1829// }
1752 1830//
1753 return false; 1831// return false;
1754 } 1832// }
1755 1833
1756 public void RemoveXmlRPCHandler(string method) 1834 public void RemoveXmlRPCHandler(string method)
1757 { 1835 {
diff --git a/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs
index db58f6f..0bd3aae 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 8dc0e3a..ae7d515 100644
--- a/OpenSim/Framework/Servers/MainServer.cs
+++ b/OpenSim/Framework/Servers/MainServer.cs
@@ -29,6 +29,7 @@ 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;
32using log4net; 33using log4net;
33using OpenSim.Framework; 34using OpenSim.Framework;
34using OpenSim.Framework.Console; 35using OpenSim.Framework.Console;
@@ -47,9 +48,12 @@ namespace OpenSim.Framework.Servers
47 /// Control the printing of certain debug messages. 48 /// Control the printing of certain debug messages.
48 /// </summary> 49 /// </summary>
49 /// <remarks> 50 /// <remarks>
50 /// If DebugLevel >= 1, then short warnings are logged when receiving bad input data. 51 /// If DebugLevel >= 1 then short warnings are logged when receiving bad input data.
51 /// If DebugLevel >= 2, then long warnings are logged when receiving bad input data. 52 /// If DebugLevel >= 2 then long warnings are logged when receiving bad input data.
52 /// If DebugLevel >= 3, then short notices about all incoming non-poll HTTP requests are logged. 53 /// 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.
53 /// </remarks> 57 /// </remarks>
54 public static int DebugLevel 58 public static int DebugLevel
55 { 59 {
@@ -101,17 +105,28 @@ namespace OpenSim.Framework.Servers
101 get { return new Dictionary<uint, BaseHttpServer>(m_Servers); } 105 get { return new Dictionary<uint, BaseHttpServer>(m_Servers); }
102 } 106 }
103 107
104
105 public static void RegisterHttpConsoleCommands(ICommandConsole console) 108 public static void RegisterHttpConsoleCommands(ICommandConsole console)
106 { 109 {
107 console.Commands.AddCommand( 110 console.Commands.AddCommand(
108 "Debug", false, "debug http", "debug http [<level>]", 111 "Comms", false, "show http-handlers",
109 "Turn on inbound non-poll http request debugging.", 112 "show http-handlers",
110 "If level <= 0, then no extra logging is done.\n" 113 "Show all registered http handlers", HandleShowHttpHandlersCommand);
111 + "If level >= 1, then short warnings are logged when receiving bad input data.\n" 114
112 + "If level >= 2, then long warnings are logged when receiving bad input data.\n" 115 console.Commands.AddCommand(
113 + "If level >= 3, then short notices about all incoming non-poll HTTP requests are logged.\n" 116 "Debug", false, "debug http", "debug http <in|out|all> [<level>]",
114 + "If no level is specified then the current level is returned.", 117 "Turn on http request logging.",
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",
115 HandleDebugHttpCommand); 130 HandleDebugHttpCommand);
116 } 131 }
117 132
@@ -119,25 +134,120 @@ namespace OpenSim.Framework.Servers
119 /// Turn on some debugging values for OpenSim. 134 /// Turn on some debugging values for OpenSim.
120 /// </summary> 135 /// </summary>
121 /// <param name="args"></param> 136 /// <param name="args"></param>
122 private static void HandleDebugHttpCommand(string module, string[] args) 137 private static void HandleDebugHttpCommand(string module, string[] cmdparams)
123 { 138 {
124 if (args.Length == 3) 139 if (cmdparams.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
125 { 164 {
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];
126 int newDebug; 172 int newDebug;
127 if (int.TryParse(args[2], out newDebug)) 173
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)
128 { 187 {
129 MainServer.DebugLevel = newDebug; 188 MainServer.DebugLevel = newDebug;
130 MainConsole.Instance.OutputFormat("Debug http level set to {0}", newDebug); 189 MainConsole.Instance.OutputFormat("IN debug 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);
131 } 196 }
132 } 197 }
133 else if (args.Length == 2) 198 else
134 { 199 {
135 MainConsole.Instance.OutputFormat("Current debug http level is {0}", MainServer.DebugLevel); 200 if (allReqs || inReqs)
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);
136 } 205 }
137 else 206 }
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)
138 { 219 {
139 MainConsole.Instance.Output("Usage: debug http 0..3"); 220 foreach (BaseHttpServer httpServer in m_Servers.Values)
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 }
140 } 248 }
249
250 MainConsole.Instance.Output(handlers.ToString());
141 } 251 }
142 252
143 /// <summary> 253 /// <summary>
diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs
index 016a174..bb094ed 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.4CM"; 32 private const string VERSION_NUMBER = "0.7.5CM";
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 4d07746..62ecbd1 100644
--- a/OpenSim/Framework/TaskInventoryDictionary.cs
+++ b/OpenSim/Framework/TaskInventoryDictionary.cs
@@ -39,10 +39,12 @@ using OpenMetaverse;
39namespace OpenSim.Framework 39namespace OpenSim.Framework
40{ 40{
41 /// <summary> 41 /// <summary>
42 /// A dictionary for task inventory. 42 /// A dictionary containing task inventory items. Indexed by item UUID.
43 /// </summary> 43 /// </summary>
44 /// <remarks>
44 /// This class is not thread safe. Callers must synchronize on Dictionary methods or Clone() this object before 45 /// This class is not thread safe. Callers must synchronize on Dictionary methods or Clone() this object before
45 /// iterating over it. 46 /// iterating over it.
47 /// </remarks>
46 public class TaskInventoryDictionary : Dictionary<UUID, TaskInventoryItem>, 48 public class TaskInventoryDictionary : Dictionary<UUID, TaskInventoryItem>,
47 ICloneable, IXmlSerializable 49 ICloneable, IXmlSerializable
48 { 50 {
diff --git a/OpenSim/Framework/TaskInventoryItem.cs b/OpenSim/Framework/TaskInventoryItem.cs
index fb818ee..574ee56 100644
--- a/OpenSim/Framework/TaskInventoryItem.cs
+++ b/OpenSim/Framework/TaskInventoryItem.cs
@@ -73,9 +73,6 @@ 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
79 public UUID AssetID { 76 public UUID AssetID {
80 get { 77 get {
81 return _assetID; 78 return _assetID;
@@ -353,14 +350,13 @@ namespace OpenSim.Framework
353 } 350 }
354 } 351 }
355 352
356 public bool ScriptRunning { 353 /// <summary>
357 get { 354 /// This used ONLY during copy. It can't be relied on at other times!
358 return _scriptRunning; 355 /// </summary>
359 } 356 /// <remarks>
360 set { 357 /// For true script running status, use IEntityInventory.TryGetScriptInstanceRunning() for now.
361 _scriptRunning = value; 358 /// </remarks>
362 } 359 public bool ScriptRunning { get; set; }
363 }
364 360
365 // See ICloneable 361 // See ICloneable
366 362
@@ -388,6 +384,7 @@ namespace OpenSim.Framework
388 384
389 public TaskInventoryItem() 385 public TaskInventoryItem()
390 { 386 {
387 ScriptRunning = true;
391 CreationDate = (uint)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; 388 CreationDate = (uint)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
392 } 389 }
393 } 390 }
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index 384f716..e76a37b 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -546,6 +546,19 @@ 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>
549 /// Are the co-ordinates of the new region visible from the old region? 562 /// Are the co-ordinates of the new region visible from the old region?
550 /// </summary> 563 /// </summary>
551 /// <param name="oldx">Old region x-coord</param> 564 /// <param name="oldx">Old region x-coord</param>
@@ -862,6 +875,12 @@ namespace OpenSim.Framework
862 return Math.Min(Math.Max(x, min), max); 875 return Math.Min(Math.Max(x, min), max);
863 } 876 }
864 877
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
865 /// <summary> 884 /// <summary>
866 /// Convert an UUID to a raw uuid string. Right now this is a string without hyphens. 885 /// Convert an UUID to a raw uuid string. Right now this is a string without hyphens.
867 /// </summary> 886 /// </summary>
@@ -1013,6 +1032,38 @@ namespace OpenSim.Framework
1013 } 1032 }
1014 } 1033 }
1015 1034
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
1016 public static XmlRpcResponse XmlRpcCommand(string url, string methodName, params object[] args) 1067 public static XmlRpcResponse XmlRpcCommand(string url, string methodName, params object[] args)
1017 { 1068 {
1018 return SendXmlRpcCommand(url, methodName, args); 1069 return SendXmlRpcCommand(url, methodName, args);
diff --git a/OpenSim/Framework/WebUtil.cs b/OpenSim/Framework/WebUtil.cs
index 30a8c28..b85d93d 100644
--- a/OpenSim/Framework/WebUtil.cs
+++ b/OpenSim/Framework/WebUtil.cs
@@ -54,9 +54,17 @@ 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>
57 /// Request number for diagnostic purposes. 65 /// Request number for diagnostic purposes.
58 /// </summary> 66 /// </summary>
59 public static int RequestNumber = 0; 67 public static int RequestNumber { get; internal set; }
60 68
61 /// <summary> 69 /// <summary>
62 /// this is the header field used to communicate the local request id 70 /// this is the header field used to communicate the local request id
@@ -146,7 +154,11 @@ namespace OpenSim.Framework
146 private static OSDMap ServiceOSDRequestWorker(string url, OSDMap data, string method, int timeout, bool compressed) 154 private static OSDMap ServiceOSDRequestWorker(string url, OSDMap data, string method, int timeout, bool compressed)
147 { 155 {
148 int reqnum = RequestNumber++; 156 int reqnum = RequestNumber++;
149 // m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method); 157
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);
150 162
151 string errorMessage = "unknown error"; 163 string errorMessage = "unknown error";
152 int tickstart = Util.EnvironmentTickCount(); 164 int tickstart = Util.EnvironmentTickCount();
@@ -230,7 +242,7 @@ namespace OpenSim.Framework
230 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart); 242 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
231 if (tickdiff > LongCallTime) 243 if (tickdiff > LongCallTime)
232 m_log.InfoFormat( 244 m_log.InfoFormat(
233 "[OSD REQUEST]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}", 245 "[WEB UTIL]: Slow ServiceOSD request {0} {1} {2} took {3}ms, {4}ms writing, {5}",
234 reqnum, 246 reqnum,
235 method, 247 method,
236 url, 248 url,
@@ -239,10 +251,14 @@ namespace OpenSim.Framework
239 strBuffer != null 251 strBuffer != null
240 ? (strBuffer.Length > MaxRequestDiagLength ? strBuffer.Remove(MaxRequestDiagLength) : strBuffer) 252 ? (strBuffer.Length > MaxRequestDiagLength ? strBuffer.Remove(MaxRequestDiagLength) : strBuffer)
241 : ""); 253 : "");
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);
242 } 258 }
243 259
244 m_log.DebugFormat( 260 m_log.DebugFormat(
245 "[WEB UTIL]: <{0}> osd request for {1}, method {2} FAILED: {3}", reqnum, url, method, errorMessage); 261 "[WEB UTIL]: ServiceOSD request {0} {1} {2} FAILED: {3}", reqnum, url, method, errorMessage);
246 262
247 return ErrorResponseMap(errorMessage); 263 return ErrorResponseMap(errorMessage);
248 } 264 }
@@ -318,7 +334,11 @@ namespace OpenSim.Framework
318 { 334 {
319 int reqnum = RequestNumber++; 335 int reqnum = RequestNumber++;
320 string method = (data != null && data["RequestMethod"] != null) ? data["RequestMethod"] : "unknown"; 336 string method = (data != null && data["RequestMethod"] != null) ? data["RequestMethod"] : "unknown";
321 // m_log.DebugFormat("[WEB UTIL]: <{0}> start form request for {1}, method {2}",reqnum,url,method); 337
338 if (DebugLevel >= 3)
339 m_log.DebugFormat(
340 "[WEB UTIL]: HTTP OUT {0} ServiceForm {1} {2} (timeout {3})",
341 reqnum, method, url, timeout);
322 342
323 string errorMessage = "unknown error"; 343 string errorMessage = "unknown error";
324 int tickstart = Util.EnvironmentTickCount(); 344 int tickstart = Util.EnvironmentTickCount();
@@ -381,7 +401,7 @@ namespace OpenSim.Framework
381 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart); 401 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
382 if (tickdiff > LongCallTime) 402 if (tickdiff > LongCallTime)
383 m_log.InfoFormat( 403 m_log.InfoFormat(
384 "[SERVICE FORM]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}", 404 "[WEB UTIL]: Slow ServiceForm request {0} {1} {2} took {3}ms, {4}ms writing, {5}",
385 reqnum, 405 reqnum,
386 method, 406 method,
387 url, 407 url,
@@ -390,9 +410,13 @@ namespace OpenSim.Framework
390 queryString != null 410 queryString != null
391 ? (queryString.Length > MaxRequestDiagLength) ? queryString.Remove(MaxRequestDiagLength) : queryString 411 ? (queryString.Length > MaxRequestDiagLength) ? queryString.Remove(MaxRequestDiagLength) : queryString
392 : ""); 412 : "");
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);
393 } 417 }
394 418
395 m_log.WarnFormat("[SERVICE FORM]: <{0}> form request to {1} failed: {2}", reqnum, url, errorMessage); 419 m_log.WarnFormat("[WEB UTIL]: ServiceForm request {0} {1} {2} failed: {2}", reqnum, method, url, errorMessage);
396 420
397 return ErrorResponseMap(errorMessage); 421 return ErrorResponseMap(errorMessage);
398 } 422 }
@@ -644,7 +668,6 @@ namespace OpenSim.Framework
644 /// <returns></returns> 668 /// <returns></returns>
645 public static string[] GetPreferredImageTypes(string accept) 669 public static string[] GetPreferredImageTypes(string accept)
646 { 670 {
647
648 if (accept == null || accept == string.Empty) 671 if (accept == null || accept == string.Empty)
649 return new string[0]; 672 return new string[0];
650 673
@@ -703,14 +726,16 @@ namespace OpenSim.Framework
703 int maxConnections) 726 int maxConnections)
704 { 727 {
705 int reqnum = WebUtil.RequestNumber++; 728 int reqnum = WebUtil.RequestNumber++;
706 // m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method); 729
730 if (WebUtil.DebugLevel >= 3)
731 m_log.DebugFormat(
732 "[WEB UTIL]: HTTP OUT {0} AsynchronousRequestObject {1} {2}",
733 reqnum, verb, requestUrl);
707 734
708 int tickstart = Util.EnvironmentTickCount(); 735 int tickstart = Util.EnvironmentTickCount();
709// int tickdata = 0; 736// int tickdata = 0;
710 int tickdiff = 0; 737 int tickdiff = 0;
711 738
712// m_log.DebugFormat("[ASYNC REQUEST]: Starting {0} {1}", verb, requestUrl);
713
714 Type type = typeof(TRequest); 739 Type type = typeof(TRequest);
715 740
716 WebRequest request = WebRequest.Create(requestUrl); 741 WebRequest request = WebRequest.Create(requestUrl);
@@ -868,7 +893,7 @@ namespace OpenSim.Framework
868 } 893 }
869 894
870 m_log.InfoFormat( 895 m_log.InfoFormat(
871 "[ASYNC REQUEST]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}", 896 "[ASYNC REQUEST]: Slow request {0} {1} {2} took {3}ms, {4}ms writing, {5}",
872 reqnum, 897 reqnum,
873 verb, 898 verb,
874 requestUrl, 899 requestUrl,
@@ -883,6 +908,12 @@ namespace OpenSim.Framework
883 requestUrl, 908 requestUrl,
884 tickdiff); 909 tickdiff);
885 } 910 }
911 else if (WebUtil.DebugLevel >= 4)
912 {
913 m_log.DebugFormat(
914 "[WEB UTIL]: HTTP OUT {0} took {1}ms",
915 reqnum, tickdiff);
916 }
886 } 917 }
887 } 918 }
888 919
@@ -903,7 +934,11 @@ namespace OpenSim.Framework
903 public static string MakeRequest(string verb, string requestUrl, string obj) 934 public static string MakeRequest(string verb, string requestUrl, string obj)
904 { 935 {
905 int reqnum = WebUtil.RequestNumber++; 936 int reqnum = WebUtil.RequestNumber++;
906 // m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method); 937
938 if (WebUtil.DebugLevel >= 3)
939 m_log.DebugFormat(
940 "[WEB UTIL]: HTTP OUT {0} SynchronousRestForms {1} {2}",
941 reqnum, verb, requestUrl);
907 942
908 int tickstart = Util.EnvironmentTickCount(); 943 int tickstart = Util.EnvironmentTickCount();
909 int tickdata = 0; 944 int tickdata = 0;
@@ -990,7 +1025,7 @@ namespace OpenSim.Framework
990 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart); 1025 int tickdiff = Util.EnvironmentTickCountSubtract(tickstart);
991 if (tickdiff > WebUtil.LongCallTime) 1026 if (tickdiff > WebUtil.LongCallTime)
992 m_log.InfoFormat( 1027 m_log.InfoFormat(
993 "[FORMS]: Slow request to <{0}> {1} {2} took {3}ms {4}ms writing {5}", 1028 "[FORMS]: Slow request {0} {1} {2} took {3}ms, {4}ms writing, {5}",
994 reqnum, 1029 reqnum,
995 verb, 1030 verb,
996 requestUrl, 1031 requestUrl,
@@ -998,6 +1033,10 @@ namespace OpenSim.Framework
998 tickset, 1033 tickset,
999 tickdata, 1034 tickdata,
1000 obj.Length > WebUtil.MaxRequestDiagLength ? obj.Remove(WebUtil.MaxRequestDiagLength) : obj); 1035 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);
1001 1040
1002 return respstring; 1041 return respstring;
1003 } 1042 }
@@ -1032,7 +1071,11 @@ namespace OpenSim.Framework
1032 public static TResponse MakeRequest<TRequest, TResponse>(string verb, string requestUrl, TRequest obj, int pTimeout, int maxConnections) 1071 public static TResponse MakeRequest<TRequest, TResponse>(string verb, string requestUrl, TRequest obj, int pTimeout, int maxConnections)
1033 { 1072 {
1034 int reqnum = WebUtil.RequestNumber++; 1073 int reqnum = WebUtil.RequestNumber++;
1035 // m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method); 1074
1075 if (WebUtil.DebugLevel >= 3)
1076 m_log.DebugFormat(
1077 "[WEB UTIL]: HTTP OUT {0} SynchronousRestObject {1} {2}",
1078 reqnum, verb, requestUrl);
1036 1079
1037 int tickstart = Util.EnvironmentTickCount(); 1080 int tickstart = Util.EnvironmentTickCount();
1038 int tickdata = 0; 1081 int tickdata = 0;
@@ -1151,7 +1194,7 @@ namespace OpenSim.Framework
1151 } 1194 }
1152 1195
1153 m_log.InfoFormat( 1196 m_log.InfoFormat(
1154 "[SynchronousRestObjectRequester]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}", 1197 "[SynchronousRestObjectRequester]: Slow request {0} {1} {2} took {3}ms, {4}ms writing, {5}",
1155 reqnum, 1198 reqnum,
1156 verb, 1199 verb,
1157 requestUrl, 1200 requestUrl,
@@ -1159,6 +1202,12 @@ namespace OpenSim.Framework
1159 tickdata, 1202 tickdata,
1160 originalRequest); 1203 originalRequest);
1161 } 1204 }
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 }
1162 1211
1163 return deserial; 1212 return deserial;
1164 } 1213 }
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index 6255515..5f07272 100644
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -35,6 +35,7 @@ using System.Text;
35using System.Text.RegularExpressions; 35using System.Text.RegularExpressions;
36using System.Timers; 36using System.Timers;
37using log4net; 37using log4net;
38using NDesk.Options;
38using Nini.Config; 39using Nini.Config;
39using OpenMetaverse; 40using OpenMetaverse;
40using OpenSim.Framework; 41using OpenSim.Framework;
@@ -253,8 +254,14 @@ namespace OpenSim
253 m_console.Commands.AddCommand("Debug", false, "debug teleport", "debug teleport", "Toggle teleport route debugging", Debug); 254 m_console.Commands.AddCommand("Debug", false, "debug teleport", "debug teleport", "Toggle teleport route debugging", Debug);
254 255
255 m_console.Commands.AddCommand("Debug", false, "debug scene", 256 m_console.Commands.AddCommand("Debug", false, "debug scene",
256 "debug scene <scripting> <collisions> <physics>", 257 "debug scene active|collisions|physics|scripting|teleport true|false",
257 "Turn on scene debugging", Debug); 258 "Turn on scene debugging.",
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);
258 265
259 m_console.Commands.AddCommand("General", false, "change region", 266 m_console.Commands.AddCommand("General", false, "change region",
260 "change region <region name>", 267 "change region <region name>",
@@ -291,7 +298,7 @@ namespace OpenSim
291 298
292 m_console.Commands.AddCommand("Archiving", false, "save oar", 299 m_console.Commands.AddCommand("Archiving", false, "save oar",
293 //"save oar [-v|--version=<N>] [-p|--profile=<url>] [<OAR path>]", 300 //"save oar [-v|--version=<N>] [-p|--profile=<url>] [<OAR path>]",
294 "save oar [-h|--home=<url>] [--noassets] [--publish] [--perm=<permissions>] [<OAR path>]", 301 "save oar [-h|--home=<url>] [--noassets] [--publish] [--perm=<permissions>] [--all] [<OAR path>]",
295 "Save a region's data to an OAR archive.", 302 "Save a region's data to an OAR archive.",
296// "-v|--version=<N> generates scene objects as per older versions of the serialization (e.g. -v=0)" + Environment.NewLine 303// "-v|--version=<N> generates scene objects as per older versions of the serialization (e.g. -v=0)" + Environment.NewLine
297 "-h|--home=<url> adds the url of the profile service to the saved user information.\n" 304 "-h|--home=<url> adds the url of the profile service to the saved user information.\n"
@@ -301,6 +308,7 @@ namespace OpenSim
301 + " this is useful if you're making oars generally available that might be reloaded to the same grid from which you published\n" 308 + " this is useful if you're making oars generally available that might be reloaded to the same grid from which you published\n"
302 + "--perm=<permissions> stops objects with insufficient permissions from being saved to the OAR.\n" 309 + "--perm=<permissions> stops objects with insufficient permissions from being saved to the OAR.\n"
303 + " <permissions> can contain one or more of these characters: \"C\" = Copy, \"T\" = Transfer\n" 310 + " <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"
304 + "The OAR path must be a filesystem path." 312 + "The OAR path must be a filesystem path."
305 + " If this is not given then the oar is saved to region.oar in the current directory.", 313 + " If this is not given then the oar is saved to region.oar in the current directory.",
306 SaveOar); 314 SaveOar);
@@ -310,8 +318,11 @@ namespace OpenSim
310 "Change the scale of a named prim", HandleEditScale); 318 "Change the scale of a named prim", HandleEditScale);
311 319
312 m_console.Commands.AddCommand("Users", false, "kick user", 320 m_console.Commands.AddCommand("Users", false, "kick user",
313 "kick user <first> <last> [message]", 321 "kick user <first> <last> [--force] [message]",
314 "Kick a user off the simulator", KickUserCommand); 322 "Kick a user off the simulator",
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);
315 326
316 m_console.Commands.AddCommand("Users", false, "show users", 327 m_console.Commands.AddCommand("Users", false, "show users",
317 "show users [full]", 328 "show users [full]",
@@ -328,10 +339,6 @@ namespace OpenSim
328 "show circuits", 339 "show circuits",
329 "Show agent circuit data", HandleShow); 340 "Show agent circuit data", HandleShow);
330 341
331 m_console.Commands.AddCommand("Comms", false, "show http-handlers",
332 "show http-handlers",
333 "Show all registered http handlers", HandleShow);
334
335 m_console.Commands.AddCommand("Comms", false, "show pending-objects", 342 m_console.Commands.AddCommand("Comms", false, "show pending-objects",
336 "show pending-objects", 343 "show pending-objects",
337 "Show # of objects on the pending queues of all scene viewers", HandleShow); 344 "Show # of objects on the pending queues of all scene viewers", HandleShow);
@@ -416,6 +423,7 @@ namespace OpenSim
416 { 423 {
417 RunCommandScript(m_shutdownCommandsFile); 424 RunCommandScript(m_shutdownCommandsFile);
418 } 425 }
426
419 base.ShutdownSpecific(); 427 base.ShutdownSpecific();
420 } 428 }
421 429
@@ -453,11 +461,17 @@ namespace OpenSim
453 /// <param name="cmdparams">name of avatar to kick</param> 461 /// <param name="cmdparams">name of avatar to kick</param>
454 private void KickUserCommand(string module, string[] cmdparams) 462 private void KickUserCommand(string module, string[] cmdparams)
455 { 463 {
456 if (cmdparams.Length < 4) 464 bool force = false;
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)
457 return; 471 return;
458 472
459 string alert = null; 473 string alert = null;
460 if (cmdparams.Length > 4) 474 if (mainParams.Count > 4)
461 alert = String.Format("\n{0}\n", String.Join(" ", cmdparams, 4, cmdparams.Length - 4)); 475 alert = String.Format("\n{0}\n", String.Join(" ", cmdparams, 4, cmdparams.Length - 4));
462 476
463 IList agents = SceneManager.GetCurrentSceneAvatars(); 477 IList agents = SceneManager.GetCurrentSceneAvatars();
@@ -466,8 +480,8 @@ namespace OpenSim
466 { 480 {
467 RegionInfo regionInfo = presence.Scene.RegionInfo; 481 RegionInfo regionInfo = presence.Scene.RegionInfo;
468 482
469 if (presence.Firstname.ToLower().Contains(cmdparams[2].ToLower()) && 483 if (presence.Firstname.ToLower().Contains(mainParams[2].ToLower()) &&
470 presence.Lastname.ToLower().Contains(cmdparams[3].ToLower())) 484 presence.Lastname.ToLower().Contains(mainParams[3].ToLower()))
471 { 485 {
472 MainConsole.Instance.Output( 486 MainConsole.Instance.Output(
473 String.Format( 487 String.Format(
@@ -480,7 +494,7 @@ namespace OpenSim
480 else 494 else
481 presence.ControllingClient.Kick("\nYou have been logged out by an administrator.\n"); 495 presence.ControllingClient.Kick("\nYou have been logged out by an administrator.\n");
482 496
483 presence.Scene.IncomingCloseAgent(presence.UUID); 497 presence.Scene.IncomingCloseAgent(presence.UUID, force);
484 } 498 }
485 } 499 }
486 500
@@ -922,7 +936,8 @@ namespace OpenSim
922 } 936 }
923 else 937 else
924 { 938 {
925 MainConsole.Instance.Output("Usage: debug scene scripting|collisions|physics|teleport true|false"); 939 MainConsole.Instance.Output(
940 "Usage: debug scene active|scripting|collisions|physics|teleport true|false");
926 } 941 }
927 942
928 break; 943 break;
@@ -1002,33 +1017,6 @@ namespace OpenSim
1002 HandleShowCircuits(); 1017 HandleShowCircuits();
1003 break; 1018 break;
1004 1019
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
1032 case "modules": 1020 case "modules":
1033 MainConsole.Instance.Output("The currently loaded shared modules are:"); 1021 MainConsole.Instance.Output("The currently loaded shared modules are:");
1034 foreach (IRegionModule module in m_moduleLoader.GetLoadedSharedModules) 1022 foreach (IRegionModule module in m_moduleLoader.GetLoadedSharedModules)
@@ -1123,7 +1111,7 @@ namespace OpenSim
1123 aCircuit.Name, 1111 aCircuit.Name,
1124 aCircuit.child ? "child" : "root", 1112 aCircuit.child ? "child" : "root",
1125 aCircuit.circuitcode.ToString(), 1113 aCircuit.circuitcode.ToString(),
1126 aCircuit.IPAddress.ToString(), 1114 aCircuit.IPAddress != null ? aCircuit.IPAddress.ToString() : "not set",
1127 aCircuit.Viewer); 1115 aCircuit.Viewer);
1128 }); 1116 });
1129 1117
diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs
index d107b7a..7232383 100644
--- a/OpenSim/Region/Application/OpenSimBase.cs
+++ b/OpenSim/Region/Application/OpenSimBase.cs
@@ -232,8 +232,6 @@ namespace OpenSim
232 232
233 base.StartupSpecific(); 233 base.StartupSpecific();
234 234
235 m_stats = StatsManager.SimExtraStats;
236
237 // Create a ModuleLoader instance 235 // Create a ModuleLoader instance
238 m_moduleLoader = new ModuleLoader(m_config.Source); 236 m_moduleLoader = new ModuleLoader(m_config.Source);
239 237
@@ -249,51 +247,51 @@ namespace OpenSim
249 plugin.PostInitialise(); 247 plugin.PostInitialise();
250 } 248 }
251 249
252 AddPluginCommands(); 250 if (m_console != null)
251 {
252 StatsManager.RegisterConsoleCommands(m_console);
253 AddPluginCommands(m_console);
254 }
253 } 255 }
254 256
255 protected virtual void AddPluginCommands() 257 protected virtual void AddPluginCommands(CommandConsole console)
256 { 258 {
257 // If console exists add plugin commands. 259 List<string> topics = GetHelpTopics();
258 if (m_console != null)
259 {
260 List<string> topics = GetHelpTopics();
261 260
262 foreach (string topic in topics) 261 foreach (string topic in topics)
263 { 262 {
264 string capitalizedTopic = char.ToUpper(topic[0]) + topic.Substring(1); 263 string capitalizedTopic = char.ToUpper(topic[0]) + topic.Substring(1);
265 264
266 // This is a hack to allow the user to enter the help command in upper or lowercase. This will go 265 // 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. 266 // away at some point.
268 m_console.Commands.AddCommand(capitalizedTopic, false, "help " + topic, 267 console.Commands.AddCommand(capitalizedTopic, false, "help " + topic,
269 "help " + capitalizedTopic, 268 "help " + capitalizedTopic,
270 "Get help on plugin command '" + topic + "'", 269 "Get help on plugin command '" + topic + "'",
271 HandleCommanderHelp); 270 HandleCommanderHelp);
272 m_console.Commands.AddCommand(capitalizedTopic, false, "help " + capitalizedTopic, 271 console.Commands.AddCommand(capitalizedTopic, false, "help " + capitalizedTopic,
273 "help " + capitalizedTopic, 272 "help " + capitalizedTopic,
274 "Get help on plugin command '" + topic + "'", 273 "Get help on plugin command '" + topic + "'",
275 HandleCommanderHelp); 274 HandleCommanderHelp);
276 275
277 ICommander commander = null; 276 ICommander commander = null;
278 277
279 Scene s = SceneManager.CurrentOrFirstScene; 278 Scene s = SceneManager.CurrentOrFirstScene;
280 279
281 if (s != null && s.GetCommanders() != null) 280 if (s != null && s.GetCommanders() != null)
282 { 281 {
283 if (s.GetCommanders().ContainsKey(topic)) 282 if (s.GetCommanders().ContainsKey(topic))
284 commander = s.GetCommanders()[topic]; 283 commander = s.GetCommanders()[topic];
285 } 284 }
286 285
287 if (commander == null) 286 if (commander == null)
288 continue; 287 continue;
289 288
290 foreach (string command in commander.Commands.Keys) 289 foreach (string command in commander.Commands.Keys)
291 { 290 {
292 m_console.Commands.AddCommand(capitalizedTopic, false, 291 console.Commands.AddCommand(capitalizedTopic, false,
293 topic + " " + command, 292 topic + " " + command,
294 topic + " " + commander.Commands[command].ShortHelp(), 293 topic + " " + commander.Commands[command].ShortHelp(),
295 String.Empty, HandleCommanderCommand); 294 String.Empty, HandleCommanderCommand);
296 }
297 } 295 }
298 } 296 }
299 } 297 }
@@ -623,7 +621,7 @@ namespace OpenSim
623 if (account == null) 621 if (account == null)
624 { 622 {
625 m_log.ErrorFormat( 623 m_log.ErrorFormat(
626 "[OPENSIM]: Unable to store account. If this simulator is connected to a grid, you must create the estate owner account first."); 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.");
627 } 625 }
628 else 626 else
629 { 627 {
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
index 650cd50..f6146a9 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,11 +337,12 @@ 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.Debug("[CAPS]: Seed Caps Request in region: " + m_regionName); 340 m_log.DebugFormat(
341 "[CAPS]: Received SEED caps request in {0} for agent {1}", m_regionName, m_HostCapsObj.AgentID);
341 342
342 if (!m_Scene.CheckClient(m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint)) 343 if (!m_Scene.CheckClient(m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint))
343 { 344 {
344 m_log.DebugFormat( 345 m_log.WarnFormat(
345 "[CAPS]: Unauthorized CAPS client {0} from {1}", 346 "[CAPS]: Unauthorized CAPS client {0} from {1}",
346 m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint); 347 m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint);
347 348
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
index e113c60..5bbdce8 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,6 +102,7 @@ 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
105 scene.EventManager.OnMakeChildAgent += MakeChildAgent; 106 scene.EventManager.OnMakeChildAgent += MakeChildAgent;
106 scene.EventManager.OnRegisterCaps += OnRegisterCaps; 107 scene.EventManager.OnRegisterCaps += OnRegisterCaps;
107 108
@@ -110,10 +111,10 @@ namespace OpenSim.Region.ClientStack.Linden
110 false, 111 false,
111 "debug eq", 112 "debug eq",
112 "debug eq [0|1|2]", 113 "debug eq [0|1|2]",
113 "Turn on event queue debugging" 114 "Turn on event queue debugging\n"
114 + "<= 0 - turns off all event queue logging" 115 + " <= 0 - turns off all event queue logging\n"
115 + ">= 1 - turns on outgoing event logging" 116 + " >= 1 - turns on outgoing event logging\n"
116 + ">= 2 - turns on poll notification", 117 + " >= 2 - turns on poll notification",
117 HandleDebugEq); 118 HandleDebugEq);
118 } 119 }
119 else 120 else
@@ -226,16 +227,6 @@ namespace OpenSim.Region.ClientStack.Linden
226 227
227 #endregion 228 #endregion
228 229
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
239 private void ClientClosed(UUID agentID, Scene scene) 230 private void ClientClosed(UUID agentID, Scene scene)
240 { 231 {
241// m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", agentID, m_scene.RegionInfo.RegionName); 232// 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 cd70410..d604cf6 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); 97 m_scene.IncomingCloseAgent(spId, false);
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 0a5ad0f..fcac182 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 1b8535c..e22670b 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs
@@ -45,7 +45,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
45 public Packet Packet; 45 public Packet Packet;
46 46
47 /// <summary> 47 /// <summary>
48 /// Default constructor 48 /// No arg constructor.
49 /// </summary>
50 public IncomingPacket() {}
51
52 /// <summary>
53 /// Constructor
49 /// </summary> 54 /// </summary>
50 /// <param name="client">Reference to the client this packet came from</param> 55 /// <param name="client">Reference to the client this packet came from</param>
51 /// <param name="packet">Packet data</param> 56 /// <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 ee28914..1f6af4a 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -47,6 +47,7 @@ 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;
50using Nini.Config; 51using Nini.Config;
51 52
52using System.IO; 53using System.IO;
@@ -354,7 +355,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
354 private bool m_deliverPackets = true; 355 private bool m_deliverPackets = true;
355 private int m_animationSequenceNumber = 1; 356 private int m_animationSequenceNumber = 1;
356 private bool m_SendLogoutPacketWhenClosing = true; 357 private bool m_SendLogoutPacketWhenClosing = true;
357 private AgentUpdateArgs lastarg; 358
359 /// <summary>
360 /// We retain a single AgentUpdateArgs so that we can constantly reuse it rather than construct a new one for
361 /// every single incoming AgentUpdate. Every client sends 10 AgentUpdate UDP messages per second, even if it
362 /// is doing absolutely nothing.
363 /// </summary>
364 /// <remarks>
365 /// This does mean that agent updates must be processed synchronously, at least for each client, and called methods
366 /// cannot retain a reference to it outside of that method.
367 /// </remarks>
368 private AgentUpdateArgs m_lastAgentUpdateArgs;
358 369
359 protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>(); 370 protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>();
360 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers 371 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers
@@ -509,19 +520,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
509 /// </summary> 520 /// </summary>
510 public void Close() 521 public void Close()
511 { 522 {
512 Close(true); 523 Close(true, false);
513 } 524 }
514 525
515 /// <summary> 526 public void Close(bool sendStop, bool force)
516 /// Shut down the client view
517 /// </summary>
518 public void Close(bool sendStop)
519 { 527 {
520 // We lock here to prevent race conditions between two threads calling close simultaneously (e.g. 528 // We lock here to prevent race conditions between two threads calling close simultaneously (e.g.
521 // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection. 529 // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection.
522 lock (CloseSyncLock) 530 lock (CloseSyncLock)
523 { 531 {
524 if (!IsActive) 532 // We still perform a force close inside the sync lock since this is intended to attempt close where
533 // there is some unidentified connection problem, not where we have issues due to deadlock
534 if (!IsActive && !force)
525 return; 535 return;
526 536
527 IsActive = false; 537 IsActive = false;
@@ -836,8 +846,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
836 OutPacket(mov, ThrottleOutPacketType.Unknown); 846 OutPacket(mov, ThrottleOutPacketType.Unknown);
837 } 847 }
838 848
839 public void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, 849 public void SendChatMessage(
840 UUID fromAgentID, byte source, byte audible) 850 string message, byte type, Vector3 fromPos, string fromName,
851 UUID fromAgentID, UUID ownerID, byte source, byte audible)
841 { 852 {
842 ChatFromSimulatorPacket reply = (ChatFromSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.ChatFromSimulator); 853 ChatFromSimulatorPacket reply = (ChatFromSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.ChatFromSimulator);
843 reply.ChatData.Audible = audible; 854 reply.ChatData.Audible = audible;
@@ -846,7 +857,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
846 reply.ChatData.SourceType = source; 857 reply.ChatData.SourceType = source;
847 reply.ChatData.Position = fromPos; 858 reply.ChatData.Position = fromPos;
848 reply.ChatData.FromName = Util.StringToBytes256(fromName); 859 reply.ChatData.FromName = Util.StringToBytes256(fromName);
849 reply.ChatData.OwnerID = fromAgentID; 860 reply.ChatData.OwnerID = ownerID;
850 reply.ChatData.SourceID = fromAgentID; 861 reply.ChatData.SourceID = fromAgentID;
851 862
852 OutPacket(reply, ThrottleOutPacketType.Unknown); 863 OutPacket(reply, ThrottleOutPacketType.Unknown);
@@ -3984,7 +3995,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3984 { 3995 {
3985 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value; 3996 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value;
3986 3997
3987 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); 3998 ImprovedTerseObjectUpdatePacket packet
3999 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
3988 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 4000 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3989 packet.RegionData.TimeDilation = timeDilation; 4001 packet.RegionData.TimeDilation = timeDilation;
3990 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; 4002 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
@@ -4029,7 +4041,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4029 { 4041 {
4030 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value; 4042 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
4031 4043
4032 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); 4044 ImprovedTerseObjectUpdatePacket packet
4045 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
4046 PacketType.ImprovedTerseObjectUpdate);
4033 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 4047 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4034 packet.RegionData.TimeDilation = timeDilation; 4048 packet.RegionData.TimeDilation = timeDilation;
4035 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; 4049 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
@@ -4037,7 +4051,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4037 for (int i = 0; i < blocks.Count; i++) 4051 for (int i = 0; i < blocks.Count; i++)
4038 packet.ObjectData[i] = blocks[i]; 4052 packet.ObjectData[i] = blocks[i];
4039 4053
4040 OutPacket(packet, ThrottleOutPacketType.Task, true); 4054 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); });
4041 } 4055 }
4042 4056
4043 #endregion Packet Sending 4057 #endregion Packet Sending
@@ -4534,7 +4548,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4534 { 4548 {
4535 returnblock[j] = new EstateOwnerMessagePacket.ParamListBlock(); 4549 returnblock[j] = new EstateOwnerMessagePacket.ParamListBlock();
4536 } 4550 }
4537 j = 0; 4551 j = 0;
4538 4552
4539 returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++; 4553 returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++;
4540 returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++; 4554 returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++;
@@ -5038,7 +5052,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5038 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Y, -64.0f, 64.0f), data, pos); pos += 2; 5052 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Y, -64.0f, 64.0f), data, pos); pos += 2;
5039 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Z, -64.0f, 64.0f), data, pos); pos += 2; 5053 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Z, -64.0f, 64.0f), data, pos); pos += 2;
5040 5054
5041 ImprovedTerseObjectUpdatePacket.ObjectDataBlock block = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock(); 5055 ImprovedTerseObjectUpdatePacket.ObjectDataBlock block
5056 = PacketPool.Instance.GetDataBlock<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
5057
5042 block.Data = data; 5058 block.Data = data;
5043 5059
5044 if (textureEntry != null && textureEntry.Length > 0) 5060 if (textureEntry != null && textureEntry.Length > 0)
@@ -5288,14 +5304,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5288 protected virtual void RegisterLocalPacketHandlers() 5304 protected virtual void RegisterLocalPacketHandlers()
5289 { 5305 {
5290 AddLocalPacketHandler(PacketType.LogoutRequest, HandleLogout); 5306 AddLocalPacketHandler(PacketType.LogoutRequest, HandleLogout);
5307
5308 // If AgentUpdate is ever handled asynchronously, then we will also need to construct a new AgentUpdateArgs
5309 // for each AgentUpdate packet.
5291 AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate, false); 5310 AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate, false);
5311
5292 AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect, false); 5312 AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect, false);
5293 AddLocalPacketHandler(PacketType.AgentCachedTexture, HandleAgentTextureCached, false); 5313 AddLocalPacketHandler(PacketType.AgentCachedTexture, HandleAgentTextureCached, false);
5294 AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false); 5314 AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false);
5295 AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest, false); 5315 AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest, false);
5296 AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest, false); 5316 AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest, false);
5297 AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest, false); 5317 AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest);
5298 AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest, false); 5318 AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest);
5299 AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage); 5319 AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage);
5300 AddLocalPacketHandler(PacketType.AvatarPropertiesRequest, HandleAvatarPropertiesRequest); 5320 AddLocalPacketHandler(PacketType.AvatarPropertiesRequest, HandleAvatarPropertiesRequest);
5301 AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer); 5321 AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer);
@@ -5517,81 +5537,84 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5517 5537
5518 #region Scene/Avatar 5538 #region Scene/Avatar
5519 5539
5520 private bool HandleAgentUpdate(IClientAPI sener, Packet Pack) 5540 private bool HandleAgentUpdate(IClientAPI sener, Packet packet)
5521 { 5541 {
5522 if (OnAgentUpdate != null) 5542 if (OnAgentUpdate != null)
5523 { 5543 {
5524 bool update = false; 5544 AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet;
5525 AgentUpdatePacket agenUpdate = (AgentUpdatePacket)Pack;
5526 5545
5527 #region Packet Session and User Check 5546 #region Packet Session and User Check
5528 if (agenUpdate.AgentData.SessionID != SessionId || agenUpdate.AgentData.AgentID != AgentId) 5547 if (agentUpdate.AgentData.SessionID != SessionId || agentUpdate.AgentData.AgentID != AgentId)
5548 {
5549 PacketPool.Instance.ReturnPacket(packet);
5529 return false; 5550 return false;
5551 }
5530 #endregion 5552 #endregion
5531 5553
5532 AgentUpdatePacket.AgentDataBlock x = agenUpdate.AgentData; 5554 bool update = false;
5533 5555 AgentUpdatePacket.AgentDataBlock x = agentUpdate.AgentData;
5534 // We can only check when we have something to check
5535 // against.
5536 5556
5537 if (lastarg != null) 5557 if (m_lastAgentUpdateArgs != null)
5538 { 5558 {
5559 // These should be ordered from most-likely to
5560 // least likely to change. I've made an initial
5561 // guess at that.
5539 update = 5562 update =
5540 ( 5563 (
5541 (x.BodyRotation != lastarg.BodyRotation) || 5564 (x.BodyRotation != m_lastAgentUpdateArgs.BodyRotation) ||
5542 (x.CameraAtAxis != lastarg.CameraAtAxis) || 5565 (x.CameraAtAxis != m_lastAgentUpdateArgs.CameraAtAxis) ||
5543 (x.CameraCenter != lastarg.CameraCenter) || 5566 (x.CameraCenter != m_lastAgentUpdateArgs.CameraCenter) ||
5544 (x.CameraLeftAxis != lastarg.CameraLeftAxis) || 5567 (x.CameraLeftAxis != m_lastAgentUpdateArgs.CameraLeftAxis) ||
5545 (x.CameraUpAxis != lastarg.CameraUpAxis) || 5568 (x.CameraUpAxis != m_lastAgentUpdateArgs.CameraUpAxis) ||
5546 (x.ControlFlags != lastarg.ControlFlags) || 5569 (x.ControlFlags != m_lastAgentUpdateArgs.ControlFlags) ||
5547 (x.ControlFlags != 0) || 5570 (x.ControlFlags != 0) ||
5548 (x.Far != lastarg.Far) || 5571 (x.Far != m_lastAgentUpdateArgs.Far) ||
5549 (x.Flags != lastarg.Flags) || 5572 (x.Flags != m_lastAgentUpdateArgs.Flags) ||
5550 (x.State != lastarg.State) || 5573 (x.State != m_lastAgentUpdateArgs.State) ||
5551 (x.HeadRotation != lastarg.HeadRotation) || 5574 (x.HeadRotation != m_lastAgentUpdateArgs.HeadRotation) ||
5552 (x.SessionID != lastarg.SessionID) || 5575 (x.SessionID != m_lastAgentUpdateArgs.SessionID) ||
5553 (x.AgentID != lastarg.AgentID) 5576 (x.AgentID != m_lastAgentUpdateArgs.AgentID)
5554 ); 5577 );
5555 } 5578 }
5556 else 5579 else
5557 { 5580 {
5581 m_lastAgentUpdateArgs = new AgentUpdateArgs();
5558 update = true; 5582 update = true;
5559 } 5583 }
5560 5584
5561 // These should be ordered from most-likely to
5562 // least likely to change. I've made an initial
5563 // guess at that.
5564
5565 if (update) 5585 if (update)
5566 { 5586 {
5567// m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name); 5587// m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name);
5568 5588
5569 AgentUpdateArgs arg = new AgentUpdateArgs(); 5589 m_lastAgentUpdateArgs.AgentID = x.AgentID;
5570 arg.AgentID = x.AgentID; 5590 m_lastAgentUpdateArgs.BodyRotation = x.BodyRotation;
5571 arg.BodyRotation = x.BodyRotation; 5591 m_lastAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis;
5572 arg.CameraAtAxis = x.CameraAtAxis; 5592 m_lastAgentUpdateArgs.CameraCenter = x.CameraCenter;
5573 arg.CameraCenter = x.CameraCenter; 5593 m_lastAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis;
5574 arg.CameraLeftAxis = x.CameraLeftAxis; 5594 m_lastAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis;
5575 arg.CameraUpAxis = x.CameraUpAxis; 5595 m_lastAgentUpdateArgs.ControlFlags = x.ControlFlags;
5576 arg.ControlFlags = x.ControlFlags; 5596 m_lastAgentUpdateArgs.Far = x.Far;
5577 arg.Far = x.Far; 5597 m_lastAgentUpdateArgs.Flags = x.Flags;
5578 arg.Flags = x.Flags; 5598 m_lastAgentUpdateArgs.HeadRotation = x.HeadRotation;
5579 arg.HeadRotation = x.HeadRotation; 5599 m_lastAgentUpdateArgs.SessionID = x.SessionID;
5580 arg.SessionID = x.SessionID; 5600 m_lastAgentUpdateArgs.State = x.State;
5581 arg.State = x.State; 5601
5582 UpdateAgent handlerAgentUpdate = OnAgentUpdate; 5602 UpdateAgent handlerAgentUpdate = OnAgentUpdate;
5583 UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate; 5603 UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate;
5584 lastarg = arg; // save this set of arguments for nexttime 5604
5585 if (handlerPreAgentUpdate != null) 5605 if (handlerPreAgentUpdate != null)
5586 OnPreAgentUpdate(this, arg); 5606 OnPreAgentUpdate(this, m_lastAgentUpdateArgs);
5607
5587 if (handlerAgentUpdate != null) 5608 if (handlerAgentUpdate != null)
5588 OnAgentUpdate(this, arg); 5609 OnAgentUpdate(this, m_lastAgentUpdateArgs);
5589 5610
5590 handlerAgentUpdate = null; 5611 handlerAgentUpdate = null;
5591 handlerPreAgentUpdate = null; 5612 handlerPreAgentUpdate = null;
5592 } 5613 }
5593 } 5614 }
5594 5615
5616 PacketPool.Instance.ReturnPacket(packet);
5617
5595 return true; 5618 return true;
5596 } 5619 }
5597 5620
@@ -5963,7 +5986,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5963 msgpack.MessageBlock.ID, 5986 msgpack.MessageBlock.ID,
5964 msgpack.MessageBlock.Offline != 0 ? true : false, 5987 msgpack.MessageBlock.Offline != 0 ? true : false,
5965 msgpack.MessageBlock.Position, 5988 msgpack.MessageBlock.Position,
5966 msgpack.MessageBlock.BinaryBucket); 5989 msgpack.MessageBlock.BinaryBucket,
5990 true);
5967 5991
5968 handlerInstantMessage(this, im); 5992 handlerInstantMessage(this, im);
5969 } 5993 }
@@ -9245,7 +9269,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9245 } 9269 }
9246 #endregion 9270 #endregion
9247 9271
9248 switch (Utils.BytesToString(messagePacket.MethodData.Method)) 9272 string method = Utils.BytesToString(messagePacket.MethodData.Method);
9273
9274 switch (method)
9249 { 9275 {
9250 case "getinfo": 9276 case "getinfo":
9251 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) 9277 if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false))
@@ -9561,7 +9587,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9561 return true; 9587 return true;
9562 9588
9563 default: 9589 default:
9564 m_log.Error("EstateOwnerMessage: Unknown method requested\n" + messagePacket); 9590 m_log.WarnFormat(
9591 "[LLCLIENTVIEW]: EstateOwnerMessage: Unknown method {0} requested for {1} in {2}",
9592 method, Name, Scene.Name);
9593
9594 for (int i = 0; i < messagePacket.ParamList.Length; i++)
9595 {
9596 EstateOwnerMessagePacket.ParamListBlock block = messagePacket.ParamList[i];
9597 string data = (string)Utils.BytesToString(block.Parameter);
9598 m_log.DebugFormat("[LLCLIENTVIEW]: Param {0}={1}", i, data);
9599 }
9600
9565 return true; 9601 return true;
9566 } 9602 }
9567 9603
@@ -11949,7 +11985,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11949 logPacket = false; 11985 logPacket = false;
11950 11986
11951 if (DebugPacketLevel <= 50 11987 if (DebugPacketLevel <= 50
11952 & (packet.Type == PacketType.ImprovedTerseObjectUpdate || packet.Type == PacketType.ObjectUpdate)) 11988 && (packet.Type == PacketType.ImprovedTerseObjectUpdate || packet.Type == PacketType.ObjectUpdate))
11953 logPacket = false; 11989 logPacket = false;
11954 11990
11955 if (DebugPacketLevel <= 25 && packet.Type == PacketType.ObjectPropertiesFamily) 11991 if (DebugPacketLevel <= 25 && packet.Type == PacketType.ObjectPropertiesFamily)
@@ -12023,8 +12059,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12023 12059
12024 if (!ProcessPacketMethod(packet)) 12060 if (!ProcessPacketMethod(packet))
12025 m_log.Warn("[CLIENT]: unhandled packet " + packet.Type); 12061 m_log.Warn("[CLIENT]: unhandled packet " + packet.Type);
12026
12027 PacketPool.Instance.ReturnPacket(packet);
12028 } 12062 }
12029 12063
12030 private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket) 12064 private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket)
@@ -12193,7 +12227,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12193 { 12227 {
12194 Kick(reason); 12228 Kick(reason);
12195 Thread.Sleep(1000); 12229 Thread.Sleep(1000);
12196 Close(); 12230 Disconnect();
12197 } 12231 }
12198 12232
12199 public void Disconnect() 12233 public void Disconnect()
@@ -12481,7 +12515,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12481 ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f); 12515 ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f);
12482 12516
12483 12517
12484 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); 12518 ImprovedTerseObjectUpdatePacket packet
12519 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
12520 PacketType.ImprovedTerseObjectUpdate);
12521
12485 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 12522 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
12486 packet.RegionData.TimeDilation = timeDilation; 12523 packet.RegionData.TimeDilation = timeDilation;
12487 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; 12524 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 d6513c5..b8951d9 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -37,6 +37,7 @@ using log4net;
37using Nini.Config; 37using Nini.Config;
38using OpenMetaverse.Packets; 38using OpenMetaverse.Packets;
39using OpenSim.Framework; 39using OpenSim.Framework;
40using OpenSim.Framework.Console;
40using OpenSim.Framework.Monitoring; 41using OpenSim.Framework.Monitoring;
41using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
42using OpenMetaverse; 43using OpenMetaverse;
@@ -100,9 +101,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
100 101
101 /// <summary>The measured resolution of Environment.TickCount</summary> 102 /// <summary>The measured resolution of Environment.TickCount</summary>
102 public readonly float TickCountResolution; 103 public readonly float TickCountResolution;
104
103 /// <summary>Number of prim updates to put on the queue each time the 105 /// <summary>Number of prim updates to put on the queue each time the
104 /// OnQueueEmpty event is triggered for updates</summary> 106 /// OnQueueEmpty event is triggered for updates</summary>
105 public readonly int PrimUpdatesPerCallback; 107 public readonly int PrimUpdatesPerCallback;
108
106 /// <summary>Number of texture packets to put on the queue each time the 109 /// <summary>Number of texture packets to put on the queue each time the
107 /// OnQueueEmpty event is triggered for textures</summary> 110 /// OnQueueEmpty event is triggered for textures</summary>
108 public readonly int TextureSendLimit; 111 public readonly int TextureSendLimit;
@@ -124,28 +127,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP
124 127
125 /// <summary>Manages authentication for agent circuits</summary> 128 /// <summary>Manages authentication for agent circuits</summary>
126 private AgentCircuitManager m_circuitManager; 129 private AgentCircuitManager m_circuitManager;
130
127 /// <summary>Reference to the scene this UDP server is attached to</summary> 131 /// <summary>Reference to the scene this UDP server is attached to</summary>
128 protected Scene m_scene; 132 protected Scene m_scene;
133
129 /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary> 134 /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary>
130 private Location m_location; 135 private Location m_location;
136
131 /// <summary>The size of the receive buffer for the UDP socket. This value 137 /// <summary>The size of the receive buffer for the UDP socket. This value
132 /// is passed up to the operating system and used in the system networking 138 /// is passed up to the operating system and used in the system networking
133 /// stack. Use zero to leave this value as the default</summary> 139 /// stack. Use zero to leave this value as the default</summary>
134 private int m_recvBufferSize; 140 private int m_recvBufferSize;
141
135 /// <summary>Flag to process packets asynchronously or synchronously</summary> 142 /// <summary>Flag to process packets asynchronously or synchronously</summary>
136 private bool m_asyncPacketHandling; 143 private bool m_asyncPacketHandling;
144
137 /// <summary>Tracks whether or not a packet was sent each round so we know 145 /// <summary>Tracks whether or not a packet was sent each round so we know
138 /// whether or not to sleep</summary> 146 /// whether or not to sleep</summary>
139 private bool m_packetSent; 147 private bool m_packetSent;
140 148
141 /// <summary>Environment.TickCount of the last time that packet stats were reported to the scene</summary> 149 /// <summary>Environment.TickCount of the last time that packet stats were reported to the scene</summary>
142 private int m_elapsedMSSinceLastStatReport = 0; 150 private int m_elapsedMSSinceLastStatReport = 0;
151
143 /// <summary>Environment.TickCount of the last time the outgoing packet handler executed</summary> 152 /// <summary>Environment.TickCount of the last time the outgoing packet handler executed</summary>
144 private int m_tickLastOutgoingPacketHandler; 153 private int m_tickLastOutgoingPacketHandler;
154
145 /// <summary>Keeps track of the number of elapsed milliseconds since the last time the outgoing packet handler looped</summary> 155 /// <summary>Keeps track of the number of elapsed milliseconds since the last time the outgoing packet handler looped</summary>
146 private int m_elapsedMSOutgoingPacketHandler; 156 private int m_elapsedMSOutgoingPacketHandler;
157
147 /// <summary>Keeps track of the number of 100 millisecond periods elapsed in the outgoing packet handler executed</summary> 158 /// <summary>Keeps track of the number of 100 millisecond periods elapsed in the outgoing packet handler executed</summary>
148 private int m_elapsed100MSOutgoingPacketHandler; 159 private int m_elapsed100MSOutgoingPacketHandler;
160
149 /// <summary>Keeps track of the number of 500 millisecond periods elapsed in the outgoing packet handler executed</summary> 161 /// <summary>Keeps track of the number of 500 millisecond periods elapsed in the outgoing packet handler executed</summary>
150 private int m_elapsed500MSOutgoingPacketHandler; 162 private int m_elapsed500MSOutgoingPacketHandler;
151 163
@@ -159,6 +171,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
159 protected bool m_sendPing; 171 protected bool m_sendPing;
160 172
161 private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>(); 173 private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>();
174 private Pool<IncomingPacket> m_incomingPacketPool;
175
176 private Stat m_incomingPacketPoolStat;
162 177
163 private int m_defaultRTO = 0; 178 private int m_defaultRTO = 0;
164 private int m_maxRTO = 0; 179 private int m_maxRTO = 0;
@@ -180,7 +195,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
180 /// </summary> 195 /// </summary>
181 private IClientAPI m_currentIncomingClient; 196 private IClientAPI m_currentIncomingClient;
182 197
183 public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager) 198 public LLUDPServer(
199 IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port,
200 IConfigSource configSource, AgentCircuitManager circuitManager)
184 : base(listenIP, (int)port) 201 : base(listenIP, (int)port)
185 { 202 {
186 #region Environment.TickCount Measurement 203 #region Environment.TickCount Measurement
@@ -202,6 +219,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
202 219
203 m_circuitManager = circuitManager; 220 m_circuitManager = circuitManager;
204 int sceneThrottleBps = 0; 221 int sceneThrottleBps = 0;
222 bool usePools = false;
205 223
206 IConfig config = configSource.Configs["ClientStack.LindenUDP"]; 224 IConfig config = configSource.Configs["ClientStack.LindenUDP"];
207 if (config != null) 225 if (config != null)
@@ -227,6 +245,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
227 m_pausedAckTimeout = 1000 * 300; // 5 minutes 245 m_pausedAckTimeout = 1000 * 300; // 5 minutes
228 } 246 }
229 247
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
230 #region BinaryStats 258 #region BinaryStats
231 config = configSource.Configs["Statistics.Binary"]; 259 config = configSource.Configs["Statistics.Binary"];
232 m_shouldCollectStats = false; 260 m_shouldCollectStats = false;
@@ -254,20 +282,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP
254 282
255 m_throttle = new TokenBucket(null, sceneThrottleBps); 283 m_throttle = new TokenBucket(null, sceneThrottleBps);
256 ThrottleRates = new ThrottleRates(configSource); 284 ThrottleRates = new ThrottleRates(configSource);
285
286 if (usePools)
287 EnablePools();
257 } 288 }
258 289
259 public void Start() 290 public void Start()
260 { 291 {
261 if (m_scene == null) 292 StartInbound();
262 throw new InvalidOperationException("[LLUDPSERVER]: Cannot LLUDPServer.Start() without an IScene reference"); 293 StartOutbound();
263 294
295 m_elapsedMSSinceLastStatReport = Environment.TickCount;
296 }
297
298 private void StartInbound()
299 {
264 m_log.InfoFormat( 300 m_log.InfoFormat(
265 "[LLUDPSERVER]: Starting the LLUDP server in {0} mode", 301 "[LLUDPSERVER]: Starting inbound packet processing for the LLUDP server in {0} mode with UsePools = {1}",
266 m_asyncPacketHandling ? "asynchronous" : "synchronous"); 302 m_asyncPacketHandling ? "asynchronous" : "synchronous", UsePools);
267 303
268 base.Start(m_recvBufferSize, m_asyncPacketHandling); 304 base.StartInbound(m_recvBufferSize, m_asyncPacketHandling);
269 305
270 // Start the packet processing threads 306 // This thread will process the packets received that are placed on the packetInbox
271 Watchdog.StartThread( 307 Watchdog.StartThread(
272 IncomingPacketHandler, 308 IncomingPacketHandler,
273 string.Format("Incoming Packets ({0})", m_scene.RegionInfo.RegionName), 309 string.Format("Incoming Packets ({0})", m_scene.RegionInfo.RegionName),
@@ -276,6 +312,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
276 true, 312 true,
277 GetWatchdogIncomingAlarmData, 313 GetWatchdogIncomingAlarmData,
278 Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); 314 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();
279 322
280 Watchdog.StartThread( 323 Watchdog.StartThread(
281 OutgoingPacketHandler, 324 OutgoingPacketHandler,
@@ -285,8 +328,57 @@ namespace OpenSim.Region.ClientStack.LindenUDP
285 true, 328 true,
286 GetWatchdogOutgoingAlarmData, 329 GetWatchdogOutgoingAlarmData,
287 Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); 330 Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS);
331 }
288 332
289 m_elapsedMSSinceLastStatReport = Environment.TickCount; 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
340 protected override bool EnablePools()
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;
290 } 382 }
291 383
292 /// <summary> 384 /// <summary>
@@ -311,12 +403,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
311 m_currentOutgoingClient != null ? m_currentOutgoingClient.Name : "none"); 403 m_currentOutgoingClient != null ? m_currentOutgoingClient.Name : "none");
312 } 404 }
313 405
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
320 public void AddScene(IScene scene) 406 public void AddScene(IScene scene)
321 { 407 {
322 if (m_scene != null) 408 if (m_scene != null)
@@ -333,6 +419,117 @@ namespace OpenSim.Region.ClientStack.LindenUDP
333 419
334 m_scene = (Scene)scene; 420 m_scene = (Scene)scene;
335 m_location = new Location(m_scene.RegionInfo.RegionHandle); 421 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");
336 } 533 }
337 534
338 public bool HandlesRegion(Location x) 535 public bool HandlesRegion(Location x)
@@ -416,6 +613,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
416 byte[] data = packet.ToBytes(); 613 byte[] data = packet.ToBytes();
417 SendPacketData(udpClient, data, packet.Type, category, method); 614 SendPacketData(udpClient, data, packet.Type, category, method);
418 } 615 }
616
617 PacketPool.Instance.ReturnPacket(packet);
419 } 618 }
420 619
421 /// <summary> 620 /// <summary>
@@ -700,7 +899,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
700 LLUDPClient udpClient = null; 899 LLUDPClient udpClient = null;
701 Packet packet = null; 900 Packet packet = null;
702 int packetEnd = buffer.DataLength - 1; 901 int packetEnd = buffer.DataLength - 1;
703 IPEndPoint address = (IPEndPoint)buffer.RemoteEndPoint; 902 IPEndPoint endPoint = (IPEndPoint)buffer.RemoteEndPoint;
704 903
705 #region Decoding 904 #region Decoding
706 905
@@ -710,7 +909,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
710// "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}", 909// "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}",
711// buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); 910// buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName);
712 911
713 return; // Drop undersizd packet 912 return; // Drop undersized packet
714 } 913 }
715 914
716 int headerLen = 7; 915 int headerLen = 7;
@@ -733,7 +932,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
733 932
734 try 933 try
735 { 934 {
736 packet = Packet.BuildPacket(buffer.Data, ref packetEnd, 935// 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,
737 // Only allocate a buffer for zerodecoding if the packet is zerocoded 942 // Only allocate a buffer for zerodecoding if the packet is zerocoded
738 ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); 943 ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null);
739 } 944 }
@@ -748,11 +953,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
748 953
749 return; // Drop short packet 954 return; // Drop short packet
750 } 955 }
751 catch(Exception e) 956 catch (Exception e)
752 { 957 {
753 if (m_malformedCount < 100) 958 if (m_malformedCount < 100)
754 m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString()); 959 m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString());
960
755 m_malformedCount++; 961 m_malformedCount++;
962
756 if ((m_malformedCount % 100000) == 0) 963 if ((m_malformedCount % 100000) == 0)
757 m_log.DebugFormat("[LLUDPSERVER]: Received {0} malformed packets so far, probable network attack.", m_malformedCount); 964 m_log.DebugFormat("[LLUDPSERVER]: Received {0} malformed packets so far, probable network attack.", m_malformedCount);
758 } 965 }
@@ -772,7 +979,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
772 979
773 // If there is already a client for this endpoint, don't process UseCircuitCode 980 // If there is already a client for this endpoint, don't process UseCircuitCode
774 IClientAPI client = null; 981 IClientAPI client = null;
775 if (!m_scene.TryGetClient(address, out client)) 982 if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView))
776 { 983 {
777 // UseCircuitCode handling 984 // UseCircuitCode handling
778 if (packet.Type == PacketType.UseCircuitCode) 985 if (packet.Type == PacketType.UseCircuitCode)
@@ -780,13 +987,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
780 // And if there is a UseCircuitCode pending, also drop it 987 // And if there is a UseCircuitCode pending, also drop it
781 lock (m_pendingCache) 988 lock (m_pendingCache)
782 { 989 {
783 if (m_pendingCache.Contains(address)) 990 if (m_pendingCache.Contains(endPoint))
784 return; 991 return;
785 992
786 m_pendingCache.AddOrUpdate(address, new Queue<UDPPacketBuffer>(), 60); 993 m_pendingCache.AddOrUpdate(endPoint, new Queue<UDPPacketBuffer>(), 60);
787 } 994 }
788 995
789 object[] array = new object[] { buffer, packet }; 996 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the
997 // buffer.
998 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
790 999
791 Util.FireAndForget(HandleUseCircuitCode, array); 1000 Util.FireAndForget(HandleUseCircuitCode, array);
792 1001
@@ -798,7 +1007,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
798 lock (m_pendingCache) 1007 lock (m_pendingCache)
799 { 1008 {
800 Queue<UDPPacketBuffer> queue; 1009 Queue<UDPPacketBuffer> queue;
801 if (m_pendingCache.TryGetValue(address, out queue)) 1010 if (m_pendingCache.TryGetValue(endPoint, out queue))
802 { 1011 {
803 //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type); 1012 //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type);
804 queue.Enqueue(buffer); 1013 queue.Enqueue(buffer);
@@ -834,6 +1043,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
834 // Handle appended ACKs 1043 // Handle appended ACKs
835 if (packet.Header.AppendedAcks && packet.Header.AckList != null) 1044 if (packet.Header.AppendedAcks && packet.Header.AckList != null)
836 { 1045 {
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
837 for (int i = 0; i < packet.Header.AckList.Length; i++) 1050 for (int i = 0; i < packet.Header.AckList.Length; i++)
838 udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent); 1051 udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent);
839 } 1052 }
@@ -843,6 +1056,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
843 { 1056 {
844 PacketAckPacket ackPacket = (PacketAckPacket)packet; 1057 PacketAckPacket ackPacket = (PacketAckPacket)packet;
845 1058
1059// m_log.DebugFormat(
1060// "[LLUDPSERVER]: Handling {0} packet acks for {1} in {2}",
1061// ackPacket.Packets.Length, client.Name, m_scene.Name);
1062
846 for (int i = 0; i < ackPacket.Packets.Length; i++) 1063 for (int i = 0; i < ackPacket.Packets.Length; i++)
847 udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent); 1064 udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent);
848 1065
@@ -856,6 +1073,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
856 1073
857 if (packet.Header.Reliable) 1074 if (packet.Header.Reliable)
858 { 1075 {
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
859 udpClient.PendingAcks.Enqueue(packet.Header.Sequence); 1080 udpClient.PendingAcks.Enqueue(packet.Header.Sequence);
860 1081
861 // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out, 1082 // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out,
@@ -902,6 +1123,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
902 1123
903 if (packet.Type == PacketType.StartPingCheck) 1124 if (packet.Type == PacketType.StartPingCheck)
904 { 1125 {
1126// m_log.DebugFormat("[LLUDPSERVER]: Handling ping from {0} in {1}", client.Name, m_scene.Name);
1127
905 // We don't need to do anything else with ping checks 1128 // We don't need to do anything else with ping checks
906 StartPingCheckPacket startPing = (StartPingCheckPacket)packet; 1129 StartPingCheckPacket startPing = (StartPingCheckPacket)packet;
907 CompletePing(udpClient, startPing.PingID.PingID); 1130 CompletePing(udpClient, startPing.PingID.PingID);
@@ -921,13 +1144,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP
921 1144
922 #endregion Ping Check Handling 1145 #endregion Ping Check Handling
923 1146
1147 IncomingPacket incomingPacket;
1148
924 // Inbox insertion 1149 // Inbox insertion
925 if (packet.Type == PacketType.AgentUpdate || 1150 if (UsePools)
926 packet.Type == PacketType.ChatFromViewer) 1151 {
927 packetInbox.EnqueueHigh(new IncomingPacket((LLClientView)client, packet)); 1152 incomingPacket = m_incomingPacketPool.GetObject();
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);
928 else 1164 else
929 packetInbox.EnqueueLow(new IncomingPacket((LLClientView)client, packet)); 1165 packetInbox.EnqueueLow(incomingPacket);
930// packetInbox.Enqueue(new IncomingPacket((LLClientView)client, packet));
931 } 1166 }
932 1167
933 #region BinaryStats 1168 #region BinaryStats
@@ -1013,21 +1248,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1013 1248
1014 private void HandleUseCircuitCode(object o) 1249 private void HandleUseCircuitCode(object o)
1015 { 1250 {
1016 IPEndPoint remoteEndPoint = null; 1251 IPEndPoint endPoint = null;
1017 IClientAPI client = null; 1252 IClientAPI client = null;
1018 1253
1019 try 1254 try
1020 { 1255 {
1021 // DateTime startTime = DateTime.Now; 1256 // DateTime startTime = DateTime.Now;
1022 object[] array = (object[])o; 1257 object[] array = (object[])o;
1023 UDPPacketBuffer buffer = (UDPPacketBuffer)array[0]; 1258 endPoint = (IPEndPoint)array[0];
1024 UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1]; 1259 UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1];
1025 1260
1026 m_log.DebugFormat( 1261 m_log.DebugFormat(
1027 "[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}", 1262 "[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}",
1028 uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, buffer.RemoteEndPoint); 1263 uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, endPoint);
1029
1030 remoteEndPoint = (IPEndPoint)buffer.RemoteEndPoint;
1031 1264
1032 AuthenticateResponse sessionInfo; 1265 AuthenticateResponse sessionInfo;
1033 if (IsClientAuthorized(uccp, out sessionInfo)) 1266 if (IsClientAuthorized(uccp, out sessionInfo))
@@ -1038,13 +1271,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1038 uccp.CircuitCode.Code, 1271 uccp.CircuitCode.Code,
1039 uccp.CircuitCode.ID, 1272 uccp.CircuitCode.ID,
1040 uccp.CircuitCode.SessionID, 1273 uccp.CircuitCode.SessionID,
1041 remoteEndPoint, 1274 endPoint,
1042 sessionInfo); 1275 sessionInfo);
1043 1276
1044 // Send ack straight away to let the viewer know that the connection is active. 1277 // Send ack straight away to let the viewer know that the connection is active.
1045 // The client will be null if it already exists (e.g. if on a region crossing the client sends a use 1278 // The client will be null if it already exists (e.g. if on a region crossing the client sends a use
1046 // circuit code to the existing child agent. This is not particularly obvious. 1279 // circuit code to the existing child agent. This is not particularly obvious.
1047 SendAckImmediate(remoteEndPoint, uccp.Header.Sequence); 1280 SendAckImmediate(endPoint, uccp.Header.Sequence);
1048 1281
1049 // We only want to send initial data to new clients, not ones which are being converted from child to root. 1282 // We only want to send initial data to new clients, not ones which are being converted from child to root.
1050 if (client != null) 1283 if (client != null)
@@ -1058,12 +1291,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1058 1291
1059 lock (m_pendingCache) 1292 lock (m_pendingCache)
1060 { 1293 {
1061 if (!m_pendingCache.TryGetValue(remoteEndPoint, out queue)) 1294 if (!m_pendingCache.TryGetValue(endPoint, out queue))
1062 { 1295 {
1063 m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present"); 1296 m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present");
1064 return; 1297 return;
1065 } 1298 }
1066 m_pendingCache.Remove(remoteEndPoint); 1299 m_pendingCache.Remove(endPoint);
1067 } 1300 }
1068 1301
1069 m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count); 1302 m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count);
@@ -1081,9 +1314,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1081 // Don't create clients for unauthorized requesters. 1314 // Don't create clients for unauthorized requesters.
1082 m_log.WarnFormat( 1315 m_log.WarnFormat(
1083 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", 1316 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}",
1084 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, remoteEndPoint); 1317 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint);
1085 lock (m_pendingCache) 1318 lock (m_pendingCache)
1086 m_pendingCache.Remove(remoteEndPoint); 1319 m_pendingCache.Remove(endPoint);
1087 } 1320 }
1088 1321
1089 // m_log.DebugFormat( 1322 // m_log.DebugFormat(
@@ -1095,7 +1328,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1095 { 1328 {
1096 m_log.ErrorFormat( 1329 m_log.ErrorFormat(
1097 "[LLUDPSERVER]: UseCircuitCode handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}", 1330 "[LLUDPSERVER]: UseCircuitCode handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}",
1098 remoteEndPoint != null ? remoteEndPoint.ToString() : "n/a", 1331 endPoint != null ? endPoint.ToString() : "n/a",
1099 client != null ? client.Name : "unknown", 1332 client != null ? client.Name : "unknown",
1100 client != null ? client.AgentId.ToString() : "unknown", 1333 client != null ? client.AgentId.ToString() : "unknown",
1101 e.Message, 1334 e.Message,
@@ -1160,20 +1393,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1160 { 1393 {
1161 IClientAPI client = null; 1394 IClientAPI client = null;
1162 1395
1163 // In priciple there shouldn't be more than one thread here, ever. 1396 // We currently synchronize this code across the whole scene to avoid issues such as
1164 // But in case that happens, we need to synchronize this piece of code 1397 // http://opensimulator.org/mantis/view.php?id=5365 However, once locking per agent circuit can be done
1165 // because it's too important 1398 // consistently, this lock could probably be removed.
1166 lock (this) 1399 lock (this)
1167 { 1400 {
1168 if (!m_scene.TryGetClient(agentID, out client)) 1401 if (!m_scene.TryGetClient(agentID, out client))
1169 { 1402 {
1170 LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); 1403 LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO);
1171 1404
1172 client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); 1405 client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode);
1173 client.OnLogout += LogoutHandler; 1406 client.OnLogout += LogoutHandler;
1174 1407
1175 ((LLClientView)client).DisableFacelights = m_disableFacelights; 1408 ((LLClientView)client).DisableFacelights = m_disableFacelights;
1176 1409
1177 client.Start(); 1410 client.Start();
1178 } 1411 }
1179 } 1412 }
@@ -1212,7 +1445,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1212 // on to en-US to avoid number parsing issues 1445 // on to en-US to avoid number parsing issues
1213 Culture.SetCurrentCulture(); 1446 Culture.SetCurrentCulture();
1214 1447
1215 while (base.IsRunning) 1448 while (IsRunningInbound)
1216 { 1449 {
1217 m_scene.ThreadAlive(1); 1450 m_scene.ThreadAlive(1);
1218 try 1451 try
@@ -1228,7 +1461,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1228 } 1461 }
1229 1462
1230 if (packetInbox.Dequeue(100, ref incomingPacket)) 1463 if (packetInbox.Dequeue(100, ref incomingPacket))
1464 {
1231 ProcessInPacket(incomingPacket);//, incomingPacket); Util.FireAndForget(ProcessInPacket, incomingPacket); 1465 ProcessInPacket(incomingPacket);//, incomingPacket); Util.FireAndForget(ProcessInPacket, incomingPacket);
1466
1467 if (UsePools)
1468 m_incomingPacketPool.ReturnObject(incomingPacket);
1469 }
1232 } 1470 }
1233 catch (Exception ex) 1471 catch (Exception ex)
1234 { 1472 {
@@ -1255,7 +1493,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1255 // Action generic every round 1493 // Action generic every round
1256 Action<IClientAPI> clientPacketHandler = ClientOutgoingPacketHandler; 1494 Action<IClientAPI> clientPacketHandler = ClientOutgoingPacketHandler;
1257 1495
1258 while (base.IsRunning) 1496 while (base.IsRunningOutbound)
1259 { 1497 {
1260 m_scene.ThreadAlive(2); 1498 m_scene.ThreadAlive(2);
1261 try 1499 try
@@ -1523,7 +1761,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1523 if (!client.IsLoggingOut) 1761 if (!client.IsLoggingOut)
1524 { 1762 {
1525 client.IsLoggingOut = true; 1763 client.IsLoggingOut = true;
1526 client.Close(false); 1764 client.Close(false, false);
1527 } 1765 }
1528 } 1766 }
1529 } 1767 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
index cfe7c9d..8bd3461 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
@@ -30,6 +30,8 @@ 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;
33 35
34namespace OpenMetaverse 36namespace OpenMetaverse
35{ 37{
@@ -58,17 +60,31 @@ namespace OpenMetaverse
58 /// <summary>Flag to process packets asynchronously or synchronously</summary> 60 /// <summary>Flag to process packets asynchronously or synchronously</summary>
59 private bool m_asyncPacketHandling; 61 private bool m_asyncPacketHandling;
60 62
61 /// <summary>The all important shutdown flag</summary> 63 /// <summary>
62 private volatile bool m_shutdownFlag = true; 64 /// Pool to use for handling data. May be null if UsePools = false;
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; }
63 75
64 /// <summary>Returns true if the server is currently listening, otherwise false</summary> 76 /// <summary>Returns true if the server is currently sending outbound packets, otherwise false</summary>
65 public bool IsRunning { get { return !m_shutdownFlag; } } 77 /// <remarks>If IsRunningOut = false, then any request to send a packet is simply dropped.</remarks>
78 public bool IsRunningOutbound { get; private set; }
79
80 private Stat m_poolCountStat;
66 81
67 /// <summary> 82 /// <summary>
68 /// Default constructor 83 /// Default constructor
69 /// </summary> 84 /// </summary>
70 /// <param name="bindAddress">Local IP address to bind the server to</param> 85 /// <param name="bindAddress">Local IP address to bind the server to</param>
71 /// <param name="port">Port to listening for incoming UDP packets on</param> 86 /// <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>
72 public OpenSimUDPBase(IPAddress bindAddress, int port) 88 public OpenSimUDPBase(IPAddress bindAddress, int port)
73 { 89 {
74 m_localBindAddress = bindAddress; 90 m_localBindAddress = bindAddress;
@@ -76,7 +92,7 @@ namespace OpenMetaverse
76 } 92 }
77 93
78 /// <summary> 94 /// <summary>
79 /// Start the UDP server 95 /// Start inbound UDP packet handling.
80 /// </summary> 96 /// </summary>
81 /// <param name="recvBufferSize">The size of the receive buffer for 97 /// <param name="recvBufferSize">The size of the receive buffer for
82 /// the UDP socket. This value is passed up to the operating system 98 /// the UDP socket. This value is passed up to the operating system
@@ -91,11 +107,11 @@ namespace OpenMetaverse
91 /// manner (not throwing an exception when the remote side resets the 107 /// manner (not throwing an exception when the remote side resets the
92 /// connection). This call is ignored on Mono where the flag is not 108 /// connection). This call is ignored on Mono where the flag is not
93 /// necessary</remarks> 109 /// necessary</remarks>
94 public void Start(int recvBufferSize, bool asyncPacketHandling) 110 public void StartInbound(int recvBufferSize, bool asyncPacketHandling)
95 { 111 {
96 m_asyncPacketHandling = asyncPacketHandling; 112 m_asyncPacketHandling = asyncPacketHandling;
97 113
98 if (m_shutdownFlag) 114 if (!IsRunningInbound)
99 { 115 {
100 const int SIO_UDP_CONNRESET = -1744830452; 116 const int SIO_UDP_CONNRESET = -1744830452;
101 117
@@ -123,8 +139,7 @@ namespace OpenMetaverse
123 139
124 m_udpSocket.Bind(ipep); 140 m_udpSocket.Bind(ipep);
125 141
126 // we're not shutting down, we're starting up 142 IsRunningInbound = true;
127 m_shutdownFlag = false;
128 143
129 // kick off an async receive. The Start() method will return, the 144 // kick off an async receive. The Start() method will return, the
130 // actual receives will occur asynchronously and will be caught in 145 // actual receives will occur asynchronously and will be caught in
@@ -134,28 +149,84 @@ namespace OpenMetaverse
134 } 149 }
135 150
136 /// <summary> 151 /// <summary>
137 /// Stops the UDP server 152 /// Start outbound UDP packet handling.
138 /// </summary> 153 /// </summary>
139 public void Stop() 154 public void StartOutbound()
155 {
156 IsRunningOutbound = true;
157 }
158
159 public void StopInbound()
140 { 160 {
141 if (!m_shutdownFlag) 161 if (IsRunningInbound)
142 { 162 {
143 // wait indefinitely for a writer lock. Once this is called, the .NET runtime 163 // wait indefinitely for a writer lock. Once this is called, the .NET runtime
144 // will deny any more reader locks, in effect blocking all other send/receive 164 // will deny any more reader locks, in effect blocking all other send/receive
145 // threads. Once we have the lock, we set shutdownFlag to inform the other 165 // threads. Once we have the lock, we set IsRunningInbound = false to inform the other
146 // threads that the socket is closed. 166 // threads that the socket is closed.
147 m_shutdownFlag = true; 167 IsRunningInbound = false;
148 m_udpSocket.Close(); 168 m_udpSocket.Close();
149 } 169 }
150 } 170 }
151 171
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
152 private void AsyncBeginReceive() 220 private void AsyncBeginReceive()
153 { 221 {
154 // allocate a packet buffer 222 UDPPacketBuffer buf;
155 //WrappedObject<UDPPacketBuffer> wrappedBuffer = Pool.CheckOut(); 223
156 UDPPacketBuffer buf = new UDPPacketBuffer(); 224 if (UsePools)
225 buf = m_pool.GetObject();
226 else
227 buf = new UDPPacketBuffer();
157 228
158 if (!m_shutdownFlag) 229 if (IsRunningInbound)
159 { 230 {
160 try 231 try
161 { 232 {
@@ -208,7 +279,7 @@ namespace OpenMetaverse
208 { 279 {
209 // Asynchronous receive operations will complete here through the call 280 // Asynchronous receive operations will complete here through the call
210 // to AsyncBeginReceive 281 // to AsyncBeginReceive
211 if (!m_shutdownFlag) 282 if (IsRunningInbound)
212 { 283 {
213 // Asynchronous mode will start another receive before the 284 // Asynchronous mode will start another receive before the
214 // callback for this packet is even fired. Very parallel :-) 285 // callback for this packet is even fired. Very parallel :-)
@@ -217,8 +288,6 @@ namespace OpenMetaverse
217 288
218 // get the buffer that was created in AsyncBeginReceive 289 // get the buffer that was created in AsyncBeginReceive
219 // this is the received data 290 // this is the received data
220 //WrappedObject<UDPPacketBuffer> wrappedBuffer = (WrappedObject<UDPPacketBuffer>)iar.AsyncState;
221 //UDPPacketBuffer buffer = wrappedBuffer.Instance;
222 UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState; 291 UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState;
223 292
224 try 293 try
@@ -235,7 +304,8 @@ namespace OpenMetaverse
235 catch (ObjectDisposedException) { } 304 catch (ObjectDisposedException) { }
236 finally 305 finally
237 { 306 {
238 //wrappedBuffer.Dispose(); 307 if (UsePools)
308 m_pool.ReturnObject(buffer);
239 309
240 // Synchronous mode waits until the packet callback completes 310 // Synchronous mode waits until the packet callback completes
241 // before starting the receive to fetch another packet 311 // before starting the receive to fetch another packet
@@ -248,7 +318,7 @@ namespace OpenMetaverse
248 318
249 public void AsyncBeginSend(UDPPacketBuffer buf) 319 public void AsyncBeginSend(UDPPacketBuffer buf)
250 { 320 {
251 if (!m_shutdownFlag) 321 if (IsRunningOutbound)
252 { 322 {
253 try 323 try
254 { 324 {
diff --git a/OpenSim/Framework/PacketPool.cs b/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs
index 41d17c5..9f22fb4 100644
--- a/OpenSim/Framework/PacketPool.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/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;
34 35
35namespace OpenSim.Framework 36namespace OpenSim.Region.ClientStack.LindenUDP
36{ 37{
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,14 +44,32 @@ namespace OpenSim.Framework
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>
47 private readonly Dictionary<PacketType, Stack<Packet>> pool = new Dictionary<PacketType, Stack<Packet>>(); 70 private readonly Dictionary<PacketType, Stack<Packet>> pool = new Dictionary<PacketType, Stack<Packet>>();
48 71
49 private static Dictionary<Type, Stack<Object>> DataBlocks = 72 private static Dictionary<Type, Stack<Object>> DataBlocks = new Dictionary<Type, Stack<Object>>();
50 new Dictionary<Type, Stack<Object>>();
51
52 static PacketPool()
53 {
54 }
55 73
56 public static PacketPool Instance 74 public static PacketPool Instance
57 { 75 {
@@ -70,8 +88,45 @@ namespace OpenSim.Framework
70 get { return dataBlockPoolEnabled; } 88 get { return dataBlockPoolEnabled; }
71 } 89 }
72 90
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>
73 public Packet GetPacket(PacketType type) 126 public Packet GetPacket(PacketType type)
74 { 127 {
128 m_packetsReusedStat.Consequent++;
129
75 Packet packet; 130 Packet packet;
76 131
77 if (!packetPoolEnabled) 132 if (!packetPoolEnabled)
@@ -81,13 +136,19 @@ namespace OpenSim.Framework
81 { 136 {
82 if (!pool.ContainsKey(type) || pool[type] == null || (pool[type]).Count == 0) 137 if (!pool.ContainsKey(type) || pool[type] == null || (pool[type]).Count == 0)
83 { 138 {
139// m_log.DebugFormat("[PACKETPOOL]: Building {0} packet", type);
140
84 // Creating a new packet if we cannot reuse an old package 141 // Creating a new packet if we cannot reuse an old package
85 packet = Packet.BuildPacket(type); 142 packet = Packet.BuildPacket(type);
86 } 143 }
87 else 144 else
88 { 145 {
146// m_log.DebugFormat("[PACKETPOOL]: Pulling {0} packet", type);
147
89 // Recycle old packages 148 // Recycle old packages
90 packet = (pool[type]).Pop(); 149 m_packetsReusedStat.Antecedent++;
150
151 packet = pool[type].Pop();
91 } 152 }
92 } 153 }
93 154
@@ -136,7 +197,7 @@ namespace OpenSim.Framework
136 { 197 {
137 PacketType type = GetType(bytes); 198 PacketType type = GetType(bytes);
138 199
139 Array.Clear(zeroBuffer, 0, zeroBuffer.Length); 200// Array.Clear(zeroBuffer, 0, zeroBuffer.Length);
140 201
141 int i = 0; 202 int i = 0;
142 Packet packet = GetPacket(type); 203 Packet packet = GetPacket(type);
@@ -183,6 +244,7 @@ namespace OpenSim.Framework
183 switch (packet.Type) 244 switch (packet.Type)
184 { 245 {
185 // List pooling packets here 246 // List pooling packets here
247 case PacketType.AgentUpdate:
186 case PacketType.PacketAck: 248 case PacketType.PacketAck:
187 case PacketType.ObjectUpdate: 249 case PacketType.ObjectUpdate:
188 case PacketType.ImprovedTerseObjectUpdate: 250 case PacketType.ImprovedTerseObjectUpdate:
@@ -197,7 +259,9 @@ namespace OpenSim.Framework
197 259
198 if ((pool[type]).Count < 50) 260 if ((pool[type]).Count < 50)
199 { 261 {
200 (pool[type]).Push(packet); 262// m_log.DebugFormat("[PACKETPOOL]: Pushing {0} packet", type);
263
264 pool[type].Push(packet);
201 } 265 }
202 } 266 }
203 break; 267 break;
@@ -209,16 +273,21 @@ namespace OpenSim.Framework
209 } 273 }
210 } 274 }
211 275
212 public static T GetDataBlock<T>() where T: new() 276 public T GetDataBlock<T>() where T: new()
213 { 277 {
214 lock (DataBlocks) 278 lock (DataBlocks)
215 { 279 {
280 m_blocksReusedStat.Consequent++;
281
216 Stack<Object> s; 282 Stack<Object> s;
217 283
218 if (DataBlocks.TryGetValue(typeof(T), out s)) 284 if (DataBlocks.TryGetValue(typeof(T), out s))
219 { 285 {
220 if (s.Count > 0) 286 if (s.Count > 0)
287 {
288 m_blocksReusedStat.Antecedent++;
221 return (T)s.Pop(); 289 return (T)s.Pop();
290 }
222 } 291 }
223 else 292 else
224 { 293 {
@@ -229,7 +298,7 @@ namespace OpenSim.Framework
229 } 298 }
230 } 299 }
231 300
232 public static void ReturnDataBlock<T>(T block) where T: new() 301 public void ReturnDataBlock<T>(T block) where T: new()
233 { 302 {
234 if (block == null) 303 if (block == null)
235 return; 304 return;
@@ -244,4 +313,4 @@ namespace OpenSim.Framework
244 } 313 }
245 } 314 }
246 } 315 }
247} 316} \ No newline at end of file
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs
index 109a8e1..556df30 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 46 public class BasicCircuitTests : OpenSimTestCase
47 { 47 {
48 private Scene m_scene; 48 private Scene m_scene;
49 private TestLLUDPServer m_udpServer; 49 private TestLLUDPServer m_udpServer;
@@ -65,8 +65,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
65 } 65 }
66 66
67 [SetUp] 67 [SetUp]
68 public void SetUp() 68 public override void SetUp()
69 { 69 {
70 base.SetUp();
70 m_scene = new SceneHelpers().SetupScene(); 71 m_scene = new SceneHelpers().SetupScene();
71 } 72 }
72 73
@@ -143,7 +144,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
143 public void TestAddClient() 144 public void TestAddClient()
144 { 145 {
145 TestHelpers.InMethod(); 146 TestHelpers.InMethod();
146// XmlConfigurator.Configure(); 147// TestHelpers.EnableLogging();
147 148
148 AddUdpServer(); 149 AddUdpServer();
149 150
diff --git a/OpenSim/Region/ClientStack/RegionApplicationBase.cs b/OpenSim/Region/ClientStack/RegionApplicationBase.cs
index 4672f8a..853b72d 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 = new SceneManager(); 79 SceneManager = SceneManager.Instance;
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 8a4fd8f..da1ff2e 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs
@@ -57,39 +57,36 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
57 } 57 }
58 58
59 /// <summary> 59 /// <summary>
60 /// Return a xfer uploader if one does not already exist. 60 /// Return the xfer uploader for the given transaction.
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>
62 /// <param name="transactionID"></param> 66 /// <param name="transactionID"></param>
63 /// <param name="assetID"> 67 /// <returns>The asset xfer uploader</returns>
64 /// We must transfer the new asset ID into the uploader on creation, otherwise 68 public AssetXferUploader RequestXferUploader(UUID transactionID)
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)
74 { 69 {
70 AssetXferUploader uploader;
71
75 lock (XferUploaders) 72 lock (XferUploaders)
76 { 73 {
77 if (!XferUploaders.ContainsKey(transactionID)) 74 if (!XferUploaders.ContainsKey(transactionID))
78 { 75 {
79 AssetXferUploader uploader = new AssetXferUploader(this, m_Scene, assetID, m_dumpAssetsToFile); 76 uploader = new AssetXferUploader(this, m_Scene, transactionID, m_dumpAssetsToFile);
80 77
81// m_log.DebugFormat( 78// m_log.DebugFormat(
82// "[AGENT ASSETS TRANSACTIONS]: Adding asset xfer uploader {0} since it didn't previously exist", transactionID); 79// "[AGENT ASSETS TRANSACTIONS]: Adding asset xfer uploader {0} since it didn't previously exist", transactionID);
83 80
84 XferUploaders.Add(transactionID, uploader); 81 XferUploaders.Add(transactionID, uploader);
85 82 }
86 return uploader; 83 else
84 {
85 uploader = XferUploaders[transactionID];
87 } 86 }
88 } 87 }
89 88
90 m_log.WarnFormat("[AGENT ASSETS TRANSACTIONS]: Ignoring request for asset xfer uploader {0} since it already exists", transactionID); 89 return uploader;
91
92 return null;
93 } 90 }
94 91
95 public void HandleXfer(ulong xferID, uint packetID, byte[] data) 92 public void HandleXfer(ulong xferID, uint packetID, byte[] data)
@@ -151,117 +148,30 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
151 string description, string name, sbyte invType, 148 string description, string name, sbyte invType,
152 sbyte type, byte wearableType, uint nextOwnerMask) 149 sbyte type, byte wearableType, uint nextOwnerMask)
153 { 150 {
154 AssetXferUploader uploader = null; 151 AssetXferUploader uploader = RequestXferUploader(transactionID);
155
156 lock (XferUploaders)
157 {
158 if (XferUploaders.ContainsKey(transactionID))
159 uploader = XferUploaders[transactionID];
160 }
161 152
162 if (uploader != null) 153 uploader.RequestCreateInventoryItem(
163 { 154 remoteClient, folderID, callbackID,
164 uploader.RequestCreateInventoryItem( 155 description, name, invType, type, wearableType, nextOwnerMask);
165 remoteClient, transactionID, folderID,
166 callbackID, description, name, invType, type,
167 wearableType, nextOwnerMask);
168 156
169 return true; 157 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;
196 } 158 }
197 159
198 public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient, 160 public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient,
199 SceneObjectPart part, UUID transactionID, 161 SceneObjectPart part, UUID transactionID,
200 TaskInventoryItem item) 162 TaskInventoryItem item)
201 { 163 {
202 AssetXferUploader uploader = null; 164 AssetXferUploader uploader = RequestXferUploader(transactionID);
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;
220 165
221 if (asset != null) 166 uploader.RequestUpdateTaskInventoryItem(remoteClient, item);
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 }
242 } 167 }
243 168
244 public void RequestUpdateInventoryItem(IClientAPI remoteClient, 169 public void RequestUpdateInventoryItem(IClientAPI remoteClient,
245 UUID transactionID, InventoryItemBase item) 170 UUID transactionID, InventoryItemBase item)
246 { 171 {
247 AssetXferUploader uploader = null; 172 AssetXferUploader uploader = RequestXferUploader(transactionID);
248
249 lock (XferUploaders)
250 {
251 if (XferUploaders.ContainsKey(transactionID))
252 uploader = XferUploaders[transactionID];
253 }
254 173
255 if (uploader != null) 174 uploader.RequestUpdateInventoryItem(remoteClient, item);
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 }
265 } 175 }
266 } 176 }
267} 177}
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
index 441c4ff..4bb8986 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 "[TRANSACTIONS MANAGER] Called HandleTaskItemUpdateFromTransaction with item {0} in {1} for {2} in {3}", 218 "[ASSET TRANSACTION MODULE] 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,13 +274,8 @@ 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, assetID); 277 AssetXferUploader uploader = transactions.RequestXferUploader(transaction);
278 278 uploader.StartUpload(remoteClient, assetID, transaction, type, data, storeLocal, tempFile);
279 if (uploader != null)
280 {
281 uploader.Initialise(remoteClient, assetID, transaction, type,
282 data, storeLocal, tempFile);
283 }
284 } 279 }
285 280
286 /// <summary> 281 /// <summary>
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
index 4cedfe6..f6dd5af 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
@@ -49,39 +49,75 @@ 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>
52 /// Reference to the object that holds this uploader. Used to remove ourselves from it's list if we 65 /// Reference to the object that holds this uploader. Used to remove ourselves from it's list if we
53 /// are performing a delayed update. 66 /// are performing a delayed update.
54 /// </summary> 67 /// </summary>
55 AgentAssetTransactions m_transactions; 68 AgentAssetTransactions m_transactions;
56 69
70 private UploadState m_uploadState = UploadState.New;
71
57 private AssetBase m_asset; 72 private AssetBase m_asset;
58 private UUID InventFolder = UUID.Zero; 73 private UUID InventFolder = UUID.Zero;
59 private sbyte invType = 0; 74 private sbyte invType = 0;
60 75
61 private bool m_createItem = false; 76 private bool m_createItem;
62 private uint m_createItemCallback = 0; 77 private uint m_createItemCallback;
63 private bool m_updateItem = false; 78
79 private bool m_updateItem;
64 private InventoryItemBase m_updateItemData; 80 private InventoryItemBase m_updateItemData;
65 81
82 private bool m_updateTaskItem;
83 private TaskInventoryItem m_updateTaskItemData;
84
66 private string m_description = String.Empty; 85 private string m_description = String.Empty;
67 private bool m_dumpAssetToFile; 86 private bool m_dumpAssetToFile;
68 private bool m_finished = false;
69 private string m_name = String.Empty; 87 private string m_name = String.Empty;
70 private bool m_storeLocal; 88// private bool m_storeLocal;
71 private uint nextPerm = 0; 89 private uint nextPerm = 0;
72 private IClientAPI ourClient; 90 private IClientAPI ourClient;
73 private UUID TransactionID = UUID.Zero; 91
92 private UUID m_transactionID;
93
74 private sbyte type = 0; 94 private sbyte type = 0;
75 private byte wearableType = 0; 95 private byte wearableType = 0;
76 private byte[] m_oldData = null; 96 private byte[] m_oldData = null;
77 public ulong XferID; 97 public ulong XferID;
78 private Scene m_Scene; 98 private Scene m_Scene;
79 99
80 public AssetXferUploader(AgentAssetTransactions transactions, Scene scene, UUID assetID, bool dumpAssetToFile) 100 /// <summary>
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)
81 { 115 {
116 m_asset = new AssetBase();
117
82 m_transactions = transactions; 118 m_transactions = transactions;
119 m_transactionID = transactionID;
83 m_Scene = scene; 120 m_Scene = scene;
84 m_asset = new AssetBase() { FullID = assetID };
85 m_dumpAssetToFile = dumpAssetToFile; 121 m_dumpAssetToFile = dumpAssetToFile;
86 } 122 }
87 123
@@ -127,30 +163,50 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
127 } 163 }
128 164
129 /// <summary> 165 /// <summary>
130 /// Initialise asset transfer from the client 166 /// Start asset transfer from the client
131 /// </summary> 167 /// </summary>
132 /// <param name="xferID"></param> 168 /// <param name="remoteClient"></param>
133 /// <param name="packetID"></param> 169 /// <param name="assetID"></param>
134 /// <param name="data"></param> 170 /// <param name="transaction"></param>
135 public void Initialise(IClientAPI remoteClient, UUID assetID, 171 /// <param name="type"></param>
136 UUID transaction, sbyte type, byte[] data, bool storeLocal, 172 /// <param name="data">
137 bool tempFile) 173 /// Optional data. If present then the asset is created immediately with this data
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)
138 { 181 {
139// m_log.DebugFormat( 182// m_log.DebugFormat(
140// "[ASSET XFER UPLOADER]: Initialised xfer from {0}, asset {1}, transaction {2}, type {3}, storeLocal {4}, tempFile {5}, already received data length {6}", 183// "[ASSET XFER UPLOADER]: Initialised xfer from {0}, asset {1}, transaction {2}, type {3}, storeLocal {4}, tempFile {5}, already received data length {6}",
141// remoteClient.Name, assetID, transaction, type, storeLocal, tempFile, data.Length); 184// remoteClient.Name, assetID, transaction, type, storeLocal, tempFile, data.Length);
142 185
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
143 ourClient = remoteClient; 200 ourClient = remoteClient;
144 m_asset.Name = "blank"; 201
145 m_asset.Description = "empty"; 202 m_asset.FullID = assetID;
146 m_asset.Type = type; 203 m_asset.Type = type;
147 m_asset.CreatorID = remoteClient.AgentId.ToString(); 204 m_asset.CreatorID = remoteClient.AgentId.ToString();
148 m_asset.Data = data; 205 m_asset.Data = data;
149 m_asset.Local = storeLocal; 206 m_asset.Local = storeLocal;
150 m_asset.Temporary = tempFile; 207 m_asset.Temporary = tempFile;
151 208
152 TransactionID = transaction; 209// m_storeLocal = storeLocal;
153 m_storeLocal = storeLocal;
154 210
155 if (m_asset.Data.Length > 2) 211 if (m_asset.Data.Length > 2)
156 { 212 {
@@ -175,36 +231,35 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
175 231
176 protected void SendCompleteMessage() 232 protected void SendCompleteMessage()
177 { 233 {
178 ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true,
179 m_asset.FullID);
180
181 // We must lock in order to avoid a race with a separate thread dealing with an inventory item or create 234 // We must lock in order to avoid a race with a separate thread dealing with an inventory item or create
182 // message from other client UDP. 235 // message from other client UDP.
183 lock (this) 236 lock (this)
184 { 237 {
185 m_finished = true; 238 m_uploadState = UploadState.Complete;
239
240 ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true, m_asset.FullID);
241
186 if (m_createItem) 242 if (m_createItem)
187 { 243 {
188 DoCreateItem(m_createItemCallback); 244 CompleteCreateItem(m_createItemCallback);
189 } 245 }
190 else if (m_updateItem) 246 else if (m_updateItem)
191 { 247 {
192 StoreAssetForItemUpdate(m_updateItemData); 248 CompleteItemUpdate(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);
198 } 249 }
199 else if (m_storeLocal) 250 else if (m_updateTaskItem)
200 { 251 {
201 m_Scene.AssetService.Store(m_asset); 252 CompleteTaskItemUpdate(m_updateTaskItemData);
202 } 253 }
254// else if (m_storeLocal)
255// {
256// m_Scene.AssetService.Store(m_asset);
257// }
203 } 258 }
204 259
205 m_log.DebugFormat( 260 m_log.DebugFormat(
206 "[ASSET XFER UPLOADER]: Uploaded asset {0} for transaction {1}", 261 "[ASSET XFER UPLOADER]: Uploaded asset {0} for transaction {1}",
207 m_asset.FullID, TransactionID); 262 m_asset.FullID, m_transactionID);
208 263
209 if (m_dumpAssetToFile) 264 if (m_dumpAssetToFile)
210 { 265 {
@@ -232,40 +287,37 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
232 } 287 }
233 288
234 public void RequestCreateInventoryItem(IClientAPI remoteClient, 289 public void RequestCreateInventoryItem(IClientAPI remoteClient,
235 UUID transactionID, UUID folderID, uint callbackID, 290 UUID folderID, uint callbackID,
236 string description, string name, sbyte invType, 291 string description, string name, sbyte invType,
237 sbyte type, byte wearableType, uint nextOwnerMask) 292 sbyte type, byte wearableType, uint nextOwnerMask)
238 { 293 {
239 if (TransactionID == transactionID) 294 InventFolder = folderID;
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)
240 { 307 {
241 InventFolder = folderID; 308 if (m_uploadState == UploadState.Complete)
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)
254 { 309 {
255 if (m_finished) 310 CompleteCreateItem(callbackID);
256 { 311 }
257 DoCreateItem(callbackID); 312 else
258 } 313 {
259 else 314 m_createItem = true; //set flag so the inventory item is created when upload is complete
260 { 315 m_createItemCallback = callbackID;
261 m_createItem = true; //set flag so the inventory item is created when upload is complete
262 m_createItemCallback = callbackID;
263 }
264 } 316 }
265 } 317 }
266 } 318 }
267 319
268 public void RequestUpdateInventoryItem(IClientAPI remoteClient, UUID transactionID, InventoryItemBase item) 320 public void RequestUpdateInventoryItem(IClientAPI remoteClient, InventoryItemBase item)
269 { 321 {
270 // We must lock to avoid a race with a separate thread uploading the asset. 322 // We must lock to avoid a race with a separate thread uploading the asset.
271 lock (this) 323 lock (this)
@@ -280,9 +332,9 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
280 item.AssetID = m_asset.FullID; 332 item.AssetID = m_asset.FullID;
281 m_Scene.InventoryService.UpdateItem(item); 333 m_Scene.InventoryService.UpdateItem(item);
282 334
283 if (m_finished) 335 if (m_uploadState == UploadState.Complete)
284 { 336 {
285 StoreAssetForItemUpdate(item); 337 CompleteItemUpdate(item);
286 } 338 }
287 else 339 else
288 { 340 {
@@ -296,20 +348,59 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
296 } 348 }
297 } 349 }
298 350
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
299 /// <summary> 373 /// <summary>
300 /// Store the asset for the given item. 374 /// Store the asset for the given item when it has been uploaded.
301 /// </summary> 375 /// </summary>
302 /// <param name="item"></param> 376 /// <param name="item"></param>
303 private void StoreAssetForItemUpdate(InventoryItemBase item) 377 private void CompleteItemUpdate(InventoryItemBase item)
304 { 378 {
305// m_log.DebugFormat( 379// m_log.DebugFormat(
306// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier item update for {1} for {2}", 380// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier item update for {1} for {2}",
307// m_asset.FullID, item.Name, ourClient.Name); 381// m_asset.FullID, item.Name, ourClient.Name);
308 382
309 m_Scene.AssetService.Store(m_asset); 383 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);
310 } 401 }
311 402
312 private void DoCreateItem(uint callbackID) 403 private void CompleteCreateItem(uint callbackID)
313 { 404 {
314 ValidateAssets(); 405 ValidateAssets();
315 m_Scene.AssetService.Store(m_asset); 406 m_Scene.AssetService.Store(m_asset);
@@ -339,6 +430,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
339 ourClient.SendInventoryItemCreateUpdate(item, callbackID); 430 ourClient.SendInventoryItemCreateUpdate(item, callbackID);
340 else 431 else
341 ourClient.SendAlertMessage("Unable to create inventory item"); 432 ourClient.SendAlertMessage("Unable to create inventory item");
433
434 m_transactions.RemoveXferUploader(m_transactionID);
342 } 435 }
343 436
344 private void ValidateAssets() 437 private void ValidateAssets()
@@ -416,7 +509,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
416 /// <returns>null if the asset has not finished uploading</returns> 509 /// <returns>null if the asset has not finished uploading</returns>
417 public AssetBase GetAssetData() 510 public AssetBase GetAssetData()
418 { 511 {
419 if (m_finished) 512 if (m_uploadState == UploadState.Complete)
420 { 513 {
421 ValidateAssets(); 514 ValidateAssets();
422 return m_asset; 515 return m_asset;
@@ -469,4 +562,3 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
469 } 562 }
470 } 563 }
471} 564}
472
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
index 7d7176f..d1a563c 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 Flotsam.RegionModules.AssetCache 55namespace OpenSim.Region.CoreModules.Asset
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,8 +107,6 @@ namespace Flotsam.RegionModules.AssetCache
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
112 public FlotsamAssetCache() 110 public FlotsamAssetCache()
113 { 111 {
114 m_InvalidChars.AddRange(Path.GetInvalidPathChars()); 112 m_InvalidChars.AddRange(Path.GetInvalidPathChars());
@@ -170,8 +168,6 @@ namespace Flotsam.RegionModules.AssetCache
170 m_CacheDirectoryTierLen = assetConfig.GetInt("CacheDirectoryTierLength", m_CacheDirectoryTierLen); 168 m_CacheDirectoryTierLen = assetConfig.GetInt("CacheDirectoryTierLength", m_CacheDirectoryTierLen);
171 169
172 m_CacheWarnAt = assetConfig.GetInt("CacheWarnAt", m_CacheWarnAt); 170 m_CacheWarnAt = assetConfig.GetInt("CacheWarnAt", m_CacheWarnAt);
173
174 m_DeepScanBeforePurge = assetConfig.GetBoolean("DeepScanBeforePurge", m_DeepScanBeforePurge);
175 } 171 }
176 172
177 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory {0}", m_CacheDirectory); 173 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory {0}", m_CacheDirectory);
@@ -519,13 +515,10 @@ namespace Flotsam.RegionModules.AssetCache
519 // Purge all files last accessed prior to this point 515 // Purge all files last accessed prior to this point
520 DateTime purgeLine = DateTime.Now - m_FileExpiration; 516 DateTime purgeLine = DateTime.Now - m_FileExpiration;
521 517
522 // An optional deep scan at this point will ensure assets present in scenes, 518 // An asset cache may contain local non-temporary assets that are not in the asset service. Therefore,
523 // or referenced by objects in the scene, but not recently accessed 519 // before cleaning up expired files we must scan the objects in the scene to make sure that we retain
524 // are not purged. 520 // such local assets if they have not been recently accessed.
525 if (m_DeepScanBeforePurge) 521 TouchAllSceneAssets(false);
526 {
527 CacheScenes();
528 }
529 522
530 foreach (string dir in Directory.GetDirectories(m_CacheDirectory)) 523 foreach (string dir in Directory.GetDirectories(m_CacheDirectory))
531 { 524 {
@@ -718,11 +711,14 @@ namespace Flotsam.RegionModules.AssetCache
718 711
719 /// <summary> 712 /// <summary>
720 /// Iterates through all Scenes, doing a deep scan through assets 713 /// Iterates through all Scenes, doing a deep scan through assets
721 /// to cache all assets present in the scene or referenced by assets 714 /// to update the access time of all assets present in the scene or referenced by assets
722 /// in the scene 715 /// in the scene.
723 /// </summary> 716 /// </summary>
724 /// <returns></returns> 717 /// <param name="storeUncached">
725 private int CacheScenes() 718 /// If true, then assets scanned which are not found in cache are added to the cache.
719 /// </param>
720 /// <returns>Number of distinct asset references found in the scene.</returns>
721 private int TouchAllSceneAssets(bool storeUncached)
726 { 722 {
727 UuidGatherer gatherer = new UuidGatherer(m_AssetService); 723 UuidGatherer gatherer = new UuidGatherer(m_AssetService);
728 724
@@ -745,7 +741,7 @@ namespace Flotsam.RegionModules.AssetCache
745 { 741 {
746 File.SetLastAccessTime(filename, DateTime.Now); 742 File.SetLastAccessTime(filename, DateTime.Now);
747 } 743 }
748 else 744 else if (storeUncached)
749 { 745 {
750 m_AssetService.Get(assetID.ToString()); 746 m_AssetService.Get(assetID.ToString());
751 } 747 }
@@ -873,13 +869,14 @@ namespace Flotsam.RegionModules.AssetCache
873 869
874 break; 870 break;
875 871
876
877 case "assets": 872 case "assets":
878 m_log.Info("[FLOTSAM ASSET CACHE]: Caching all assets, in all scenes."); 873 m_log.Info("[FLOTSAM ASSET CACHE]: Ensuring assets are cached for all scenes.");
879 874
880 Util.FireAndForget(delegate { 875 Util.FireAndForget(delegate {
881 int assetsCached = CacheScenes(); 876 int assetReferenceTotal = TouchAllSceneAssets(true);
882 m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Completed Scene Caching, {0} assets found.", assetsCached); 877 m_log.InfoFormat(
878 "[FLOTSAM ASSET CACHE]: Completed check with {0} assets.",
879 assetReferenceTotal);
883 }); 880 });
884 881
885 break; 882 break;
diff --git a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
index c91b25f..1c2bfd0 100644
--- a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
+++ b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
@@ -35,7 +35,6 @@ using Nini.Config;
35using NUnit.Framework; 35using NUnit.Framework;
36using OpenMetaverse; 36using OpenMetaverse;
37using OpenMetaverse.Assets; 37using OpenMetaverse.Assets;
38using Flotsam.RegionModules.AssetCache;
39using OpenSim.Framework; 38using OpenSim.Framework;
40using OpenSim.Region.Framework.Scenes; 39using OpenSim.Region.Framework.Scenes;
41using OpenSim.Region.Framework.Scenes.Serialization; 40using OpenSim.Region.Framework.Scenes.Serialization;
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index 951afd7..acd156e 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -286,6 +286,20 @@ 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 {
289 lock (sp.AttachmentsSyncLock) 303 lock (sp.AttachmentsSyncLock)
290 { 304 {
291// m_log.DebugFormat( 305// m_log.DebugFormat(
@@ -461,6 +475,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
461 475
462 public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId) 476 public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId)
463 { 477 {
478 DetachSingleAttachmentToGround(sp, soLocalId, sp.AbsolutePosition, Quaternion.Identity);
479 }
480
481 public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId, Vector3 absolutePos, Quaternion absoluteRot)
482 {
464 if (!Enabled) 483 if (!Enabled)
465 return; 484 return;
466 485
@@ -502,7 +521,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
502 so.FromItemID = UUID.Zero; 521 so.FromItemID = UUID.Zero;
503 522
504 SceneObjectPart rootPart = so.RootPart; 523 SceneObjectPart rootPart = so.RootPart;
505 so.AbsolutePosition = sp.AbsolutePosition; 524 so.AbsolutePosition = absolutePos;
525 if (absoluteRot != Quaternion.Identity)
526 {
527 so.UpdateGroupRotationR(absoluteRot);
528 }
506 so.AttachedAvatar = UUID.Zero; 529 so.AttachedAvatar = UUID.Zero;
507 rootPart.SetParentLocalId(0); 530 rootPart.SetParentLocalId(0);
508 so.ClearPartAttachmentData(); 531 so.ClearPartAttachmentData();
@@ -616,9 +639,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
616 639
617 if (grp.HasGroupChanged) 640 if (grp.HasGroupChanged)
618 { 641 {
619// m_log.DebugFormat( 642 m_log.DebugFormat(
620// "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}", 643 "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}",
621// grp.UUID, grp.AttachmentPoint); 644 grp.UUID, grp.AttachmentPoint);
622 645
623 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp, scriptedState); 646 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp, scriptedState);
624 647
@@ -862,7 +885,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
862 // This will throw if the attachment fails 885 // This will throw if the attachment fails
863 try 886 try
864 { 887 {
865 AttachObject(sp, objatt, attachmentPt, false, false, false); 888 AttachObjectInternal(sp, objatt, attachmentPt, false, false, false);
866 } 889 }
867 catch (Exception e) 890 catch (Exception e)
868 { 891 {
@@ -933,6 +956,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
933 956
934 InventoryItemBase item = new InventoryItemBase(itemID, sp.UUID); 957 InventoryItemBase item = new InventoryItemBase(itemID, sp.UUID);
935 item = m_scene.InventoryService.GetItem(item); 958 item = m_scene.InventoryService.GetItem(item);
959 if (item == null)
960 return;
961
936 bool changed = sp.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID); 962 bool changed = sp.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID);
937 if (changed && m_scene.AvatarFactory != null) 963 if (changed && m_scene.AvatarFactory != null)
938 { 964 {
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
index d9a619d..4e9d3f9 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
@@ -62,7 +62,10 @@ 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;
66 69
67 [TestFixtureSetUp] 70 [TestFixtureSetUp]
68 public void FixtureInit() 71 public void FixtureInit()
@@ -83,7 +86,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
83 { 86 {
84// Console.WriteLine("Got chat [{0}]", oscm.Message); 87// Console.WriteLine("Got chat [{0}]", oscm.Message);
85 88
86 m_osChatMessageReceived = oscm; 89// m_osChatMessageReceived = oscm;
87 m_chatEvent.Set(); 90 m_chatEvent.Set();
88 } 91 }
89 92
@@ -99,6 +102,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
99 "attachments-test-scene", TestHelpers.ParseTail(999), 1000, 1000, config); 102 "attachments-test-scene", TestHelpers.ParseTail(999), 1000, 1000, config);
100 SceneHelpers.SetupSceneModules(scene, config, modules.ToArray()); 103 SceneHelpers.SetupSceneModules(scene, config, modules.ToArray());
101 104
105 scene.EventManager.OnAttach += (localID, itemID, avatarID) => m_numberOfAttachEventsFired++;
106
102 return scene; 107 return scene;
103 } 108 }
104 109
@@ -181,6 +186,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
181 TestHelpers.InMethod(); 186 TestHelpers.InMethod();
182// TestHelpers.EnableLogging(); 187// TestHelpers.EnableLogging();
183 188
189 m_numberOfAttachEventsFired = 0;
190
184 Scene scene = CreateTestScene(); 191 Scene scene = CreateTestScene();
185 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); 192 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
186 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1); 193 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1);
@@ -189,6 +196,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
189 196
190 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID); 197 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID);
191 198
199 m_numberOfAttachEventsFired = 0;
192 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false, false); 200 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false, false);
193 201
194 // Check status on scene presence 202 // Check status on scene presence
@@ -216,7 +224,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
216 224
217 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 225 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
218 226
219// TestHelpers.DisableLogging(); 227 // Check events
228 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1));
220 } 229 }
221 230
222 /// <summary> 231 /// <summary>
@@ -228,6 +237,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
228 TestHelpers.InMethod(); 237 TestHelpers.InMethod();
229// TestHelpers.EnableLogging(); 238// TestHelpers.EnableLogging();
230 239
240 m_numberOfAttachEventsFired = 0;
241
231 Scene scene = CreateTestScene(); 242 Scene scene = CreateTestScene();
232 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); 243 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
233 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1); 244 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1);
@@ -247,6 +258,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
247 258
248 Assert.That(sp.HasAttachments(), Is.False); 259 Assert.That(sp.HasAttachments(), Is.False);
249 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 260 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
261
262 // Check events
263 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0));
250 } 264 }
251 265
252 [Test] 266 [Test]
@@ -261,6 +275,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
261 275
262 InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20); 276 InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20);
263 277
278 m_numberOfAttachEventsFired = 0;
264 scene.AttachmentsModule.RezSingleAttachmentFromInventory( 279 scene.AttachmentsModule.RezSingleAttachmentFromInventory(
265 sp, attItem.ID, (uint)AttachmentPoint.Chest); 280 sp, attItem.ID, (uint)AttachmentPoint.Chest);
266 281
@@ -280,6 +295,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
280 Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); 295 Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
281 296
282 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 297 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
298
299 // Check events
300 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1));
283 } 301 }
284 302
285 /// <summary> 303 /// <summary>
@@ -338,6 +356,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
338 ISceneEntity so 356 ISceneEntity so
339 = scene.AttachmentsModule.RezSingleAttachmentFromInventory( 357 = scene.AttachmentsModule.RezSingleAttachmentFromInventory(
340 sp, attItem.ID, (uint)AttachmentPoint.Chest); 358 sp, attItem.ID, (uint)AttachmentPoint.Chest);
359
360 m_numberOfAttachEventsFired = 0;
341 scene.AttachmentsModule.DetachSingleAttachmentToGround(sp, so.LocalId); 361 scene.AttachmentsModule.DetachSingleAttachmentToGround(sp, so.LocalId);
342 362
343 // Check scene presence status 363 // Check scene presence status
@@ -353,6 +373,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
353 373
354 // Check object in scene 374 // Check object in scene
355 Assert.That(scene.GetSceneObjectGroup("att"), Is.Not.Null); 375 Assert.That(scene.GetSceneObjectGroup("att"), Is.Not.Null);
376
377 // Check events
378 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1));
356 } 379 }
357 380
358 [Test] 381 [Test]
@@ -369,6 +392,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
369 SceneObjectGroup so 392 SceneObjectGroup so
370 = (SceneObjectGroup)scene.AttachmentsModule.RezSingleAttachmentFromInventory( 393 = (SceneObjectGroup)scene.AttachmentsModule.RezSingleAttachmentFromInventory(
371 sp, attItem.ID, (uint)AttachmentPoint.Chest); 394 sp, attItem.ID, (uint)AttachmentPoint.Chest);
395
396 m_numberOfAttachEventsFired = 0;
372 scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, so); 397 scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, so);
373 398
374 // Check status on scene presence 399 // Check status on scene presence
@@ -380,6 +405,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
380 Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo(0)); 405 Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo(0));
381 406
382 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(0)); 407 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(0));
408
409 // Check events
410 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1));
383 } 411 }
384 412
385 /// <summary> 413 /// <summary>
@@ -461,10 +489,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
461 489
462 SceneObjectGroup rezzedAtt = presence.GetAttachments()[0]; 490 SceneObjectGroup rezzedAtt = presence.GetAttachments()[0];
463 491
464 scene.IncomingCloseAgent(presence.UUID); 492 m_numberOfAttachEventsFired = 0;
493 scene.IncomingCloseAgent(presence.UUID, false);
465 494
466 // Check that we can't retrieve this attachment from the scene. 495 // Check that we can't retrieve this attachment from the scene.
467 Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null); 496 Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null);
497
498 // Check events
499 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0));
468 } 500 }
469 501
470 [Test] 502 [Test]
@@ -480,6 +512,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
480 AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID); 512 AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID);
481 acd.Appearance = new AvatarAppearance(); 513 acd.Appearance = new AvatarAppearance();
482 acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID); 514 acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID);
515
516 m_numberOfAttachEventsFired = 0;
483 ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd); 517 ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd);
484 518
485 Assert.That(presence.HasAttachments(), Is.True); 519 Assert.That(presence.HasAttachments(), Is.True);
@@ -502,6 +536,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
502 Assert.That(presence.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); 536 Assert.That(presence.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest));
503 537
504 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 538 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));
505 } 542 }
506 543
507 [Test] 544 [Test]
@@ -522,10 +559,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
522 559
523 Vector3 newPosition = new Vector3(1, 2, 4); 560 Vector3 newPosition = new Vector3(1, 2, 4);
524 561
562 m_numberOfAttachEventsFired = 0;
525 scene.SceneGraph.UpdatePrimGroupPosition(attSo.LocalId, newPosition, sp.ControllingClient); 563 scene.SceneGraph.UpdatePrimGroupPosition(attSo.LocalId, newPosition, sp.ControllingClient);
526 564
527 Assert.That(attSo.AbsolutePosition, Is.EqualTo(sp.AbsolutePosition)); 565 Assert.That(attSo.AbsolutePosition, Is.EqualTo(sp.AbsolutePosition));
528 Assert.That(attSo.RootPart.AttachedPos, Is.EqualTo(newPosition)); 566 Assert.That(attSo.RootPart.AttachedPos, Is.EqualTo(newPosition));
567
568 // Check events
569 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0));
529 } 570 }
530 571
531 [Test] 572 [Test]
@@ -574,6 +615,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
574 Vector3 teleportPosition = new Vector3(10, 11, 12); 615 Vector3 teleportPosition = new Vector3(10, 11, 12);
575 Vector3 teleportLookAt = new Vector3(20, 21, 22); 616 Vector3 teleportLookAt = new Vector3(20, 21, 22);
576 617
618 m_numberOfAttachEventsFired = 0;
577 sceneA.RequestTeleportLocation( 619 sceneA.RequestTeleportLocation(
578 beforeTeleportSp.ControllingClient, 620 beforeTeleportSp.ControllingClient,
579 sceneB.RegionInfo.RegionHandle, 621 sceneB.RegionInfo.RegionHandle,
@@ -616,29 +658,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
616 Assert.That(actualSceneAAttachments.Count, Is.EqualTo(0)); 658 Assert.That(actualSceneAAttachments.Count, Is.EqualTo(0));
617 659
618 Assert.That(sceneA.GetSceneObjectGroups().Count, Is.EqualTo(0)); 660 Assert.That(sceneA.GetSceneObjectGroups().Count, Is.EqualTo(0));
619 }
620 661
621 // I'm commenting this test because scene setup NEEDS InventoryService to 662 // Check events
622 // be non-null 663 Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0));
623 //[Test] 664 }
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// }
643 } 665 }
644} 666}
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index 4cb4370..e3bf997 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -533,6 +533,7 @@ 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
536 InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID); 537 InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID);
537 baseItem = invService.GetItem(baseItem); 538 baseItem = invService.GetItem(baseItem);
538 539
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
index dbbb0ae..4407e40 100644
--- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
@@ -197,6 +197,7 @@ 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;
200 string message = c.Message; 201 string message = c.Message;
201 IScene scene = c.Scene; 202 IScene scene = c.Scene;
202 UUID destination = c.Destination; 203 UUID destination = c.Destination;
@@ -224,11 +225,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
224 fromNamePrefix = m_adminPrefix; 225 fromNamePrefix = m_adminPrefix;
225 } 226 }
226 destination = UUID.Zero; // Avatars cant "SayTo" 227 destination = UUID.Zero; // Avatars cant "SayTo"
228 ownerID = c.Sender.AgentId;
229
227 break; 230 break;
228 231
229 case ChatSourceType.Object: 232 case ChatSourceType.Object:
230 fromID = c.SenderUUID; 233 fromID = c.SenderUUID;
231 234
235 if (c.SenderObject != null && c.SenderObject is SceneObjectPart)
236 ownerID = ((SceneObjectPart)c.SenderObject).OwnerID;
237
232 break; 238 break;
233 } 239 }
234 240
@@ -262,8 +268,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
262 // objects on a parcel with access restrictions 268 // objects on a parcel with access restrictions
263 if (c.Sender == null || Presencecheck.IsEitherBannedOrRestricted(c.Sender.AgentId) != true) 269 if (c.Sender == null || Presencecheck.IsEitherBannedOrRestricted(c.Sender.AgentId) != true)
264 { 270 {
265 if (TrySendChatMessage(presence, fromPos, regionPos, fromID, fromNamePrefix + fromName, c.Type, message, sourceType)) 271 if (destination != UUID.Zero)
266 receiverIDs.Add(presence.UUID); 272 {
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 }
267 } 281 }
268 } 282 }
269 } 283 }
@@ -324,7 +338,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
324 (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId)) 338 (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId))
325 return; 339 return;
326 340
327 client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, 341 client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, fromID,
328 (byte)sourceType, (byte)ChatAudibleLevel.Fully); 342 (byte)sourceType, (byte)ChatAudibleLevel.Fully);
329 receiverIDs.Add(client.AgentId); 343 receiverIDs.Add(client.AgentId);
330 } 344 }
@@ -341,15 +355,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
341 /// <param name="fromPos"></param> 355 /// <param name="fromPos"></param>
342 /// <param name="regionPos">/param> 356 /// <param name="regionPos">/param>
343 /// <param name="fromAgentID"></param> 357 /// <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>
344 /// <param name="fromName"></param> 362 /// <param name="fromName"></param>
345 /// <param name="type"></param> 363 /// <param name="type"></param>
346 /// <param name="message"></param> 364 /// <param name="message"></param>
347 /// <param name="src"></param> 365 /// <param name="src"></param>
348 /// <returns>true if the message was sent to the receiver, false if it was not sent due to failing a 366 /// <returns>true if the message was sent to the receiver, false if it was not sent due to failing a
349 /// precondition</returns> 367 /// precondition</returns>
350 protected virtual bool TrySendChatMessage(ScenePresence presence, Vector3 fromPos, Vector3 regionPos, 368 protected virtual bool TrySendChatMessage(
351 UUID fromAgentID, string fromName, ChatTypeEnum type, 369 ScenePresence presence, Vector3 fromPos, Vector3 regionPos,
352 string message, ChatSourceType src) 370 UUID fromAgentID, UUID ownerID, string fromName, ChatTypeEnum type,
371 string message, ChatSourceType src, bool ignoreDistance)
353 { 372 {
354 // don't send chat to child agents 373 // don't send chat to child agents
355 if (presence.IsChildAgent) return false; 374 if (presence.IsChildAgent) return false;
@@ -369,8 +388,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
369 } 388 }
370 389
371 // TODO: should change so the message is sent through the avatar rather than direct to the ClientView 390 // TODO: should change so the message is sent through the avatar rather than direct to the ClientView
372 presence.ControllingClient.SendChatMessage(message, (byte) type, fromPos, fromName, 391 presence.ControllingClient.SendChatMessage(
373 fromAgentID, (byte)src, (byte)ChatAudibleLevel.Fully); 392 message, (byte) type, fromPos, fromName,
393 fromAgentID, ownerID, (byte)src, (byte)ChatAudibleLevel.Fully);
374 394
375 return true; 395 return true;
376 } 396 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs
index d942e87..5ec0ea9 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]), 144 transactionID, false, new Vector3(), new byte[0], true),
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 24ec435..f1903c3 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs
@@ -28,6 +28,7 @@
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Linq;
31using System.Reflection; 32using System.Reflection;
32using System.Threading; 33using System.Threading;
33using log4net; 34using log4net;
@@ -482,9 +483,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
482 Util.FireAndForget( 483 Util.FireAndForget(
483 delegate 484 delegate
484 { 485 {
485 m_log.DebugFormat( 486// m_log.DebugFormat(
486 "[FRIENDS MODULE]: Notifying {0} friends of {1} of online status {2}", 487// "[FRIENDS MODULE]: Notifying {0} friends of {1} of online status {2}",
487 friendList.Count, agentID, online); 488// friendList.Count, agentID, online);
488 489
489 // Notify about this user status 490 // Notify about this user status
490 StatusNotify(friendList, agentID, online); 491 StatusNotify(friendList, agentID, online);
@@ -495,42 +496,36 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
495 496
496 protected virtual void StatusNotify(List<FriendInfo> friendList, UUID userID, bool online) 497 protected virtual void StatusNotify(List<FriendInfo> friendList, UUID userID, bool online)
497 { 498 {
498 foreach (FriendInfo friend in friendList) 499 List<string> friendStringIds = friendList.ConvertAll<string>(friend => friend.Friend);
500 List<string> remoteFriendStringIds = new List<string>();
501 foreach (string friendStringId in friendStringIds)
499 { 502 {
500 UUID friendID; 503 UUID friendUuid;
501 if (UUID.TryParse(friend.Friend, out friendID)) 504 if (UUID.TryParse(friendStringId, out friendUuid))
502 { 505 {
503 // Try local 506 if (LocalStatusNotification(userID, friendUuid, online))
504 if (LocalStatusNotification(userID, friendID, online))
505 continue; 507 continue;
506 508
507 // The friend is not here [as root]. Let's forward. 509 remoteFriendStringIds.Add(friendStringId);
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.
530 } 510 }
531 else 511 else
532 { 512 {
533 m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friend.Friend); 513 m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friendStringId);
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);
534 } 529 }
535 } 530 }
536 } 531 }
diff --git a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
index 716cc69..82816d9 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}), 209 new Vector3(), new byte[] {(byte)kickflags}, true),
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 6587ead..d0e88f6 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} with asset {2}", 169 "[INVENTORY ARCHIVER]: Saving item {0} {1} (asset UUID {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,11 +337,14 @@ 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 new AssetsRequest( 340 AssetsRequest ar
341 new AssetsArchiver(m_archiveWriter), 341 = new AssetsRequest(
342 m_assetUuids, m_scene.AssetService, 342 new AssetsArchiver(m_archiveWriter),
343 m_scene.UserAccountService, m_scene.RegionInfo.ScopeID, 343 m_assetUuids, m_scene.AssetService,
344 options, ReceivedAllAssets).Execute(); 344 m_scene.UserAccountService, m_scene.RegionInfo.ScopeID,
345 options, ReceivedAllAssets);
346
347 Util.FireAndForget(o => ar.Execute());
345 } 348 }
346 else 349 else
347 { 350 {
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
index 7d1fe68..765b960 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs
@@ -35,6 +35,7 @@ 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;
38using OpenSim.Region.Framework.Interfaces; 39using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
40using OpenSim.Services.Interfaces; 41using OpenSim.Services.Interfaces;
@@ -209,6 +210,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
209 Guid id, string firstName, string lastName, string invPath, string pass, string savePath, 210 Guid id, string firstName, string lastName, string invPath, string pass, string savePath,
210 Dictionary<string, object> options) 211 Dictionary<string, object> options)
211 { 212 {
213// if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, savePath))
214// return false;
215
212 if (m_scenes.Count > 0) 216 if (m_scenes.Count > 0)
213 { 217 {
214 UserAccount userInfo = GetUserInfo(firstName, lastName, pass); 218 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 1056865..00727a4 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs
@@ -82,7 +82,25 @@ 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
86 [SetUp] 104 [SetUp]
87 public override void SetUp() 105 public override void SetUp()
88 { 106 {
@@ -90,12 +108,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
90 m_iarStream = new MemoryStream(m_iarStreamBytes); 108 m_iarStream = new MemoryStream(m_iarStreamBytes);
91 } 109 }
92 110
93 [TestFixtureSetUp]
94 public void FixtureSetup()
95 {
96 ConstructDefaultIarBytesForTestLoad();
97 }
98
99 protected void ConstructDefaultIarBytesForTestLoad() 111 protected void ConstructDefaultIarBytesForTestLoad()
100 { 112 {
101// log4net.Config.XmlConfigurator.Configure(); 113// 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 b112b6d..06f6e49 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// log4net.Config.XmlConfigurator.Configure(); 72// TestHelpers.EnableLogging();
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// log4net.Config.XmlConfigurator.Configure(); 361// TestHelpers.EnableLogging();
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 c14cb17..ecaab44 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 : IInventoryTransferModule, ISharedRegionModule 41 public class InventoryTransferModule : 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,6 +313,11 @@ 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.
316 else if (im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted) 321 else if (im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted)
317 { 322 {
318 UUID destinationFolderID = UUID.Zero; 323 UUID destinationFolderID = UUID.Zero;
@@ -324,6 +329,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
324 329
325 if (destinationFolderID != UUID.Zero) 330 if (destinationFolderID != UUID.Zero)
326 { 331 {
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
327 IInventoryService invService = scene.InventoryService; 342 IInventoryService invService = scene.InventoryService;
328 343
329 UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip 344 UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip
@@ -331,9 +346,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
331 InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId); 346 InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId);
332 item = invService.GetItem(item); 347 item = invService.GetItem(item);
333 InventoryFolderBase folder = null; 348 InventoryFolderBase folder = null;
349 UUID? previousParentFolderID = null;
334 350
335 if (item != null) // It's an item 351 if (item != null) // It's an item
336 { 352 {
353 previousParentFolderID = item.Folder;
337 item.Folder = destinationFolderID; 354 item.Folder = destinationFolderID;
338 355
339 invService.DeleteItems(item.Owner, new List<UUID>() { item.ID }); 356 invService.DeleteItems(item.Owner, new List<UUID>() { item.ID });
@@ -346,10 +363,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
346 363
347 if (folder != null) // It's a folder 364 if (folder != null) // It's a folder
348 { 365 {
366 previousParentFolderID = folder.ParentID;
349 folder.ParentID = destinationFolderID; 367 folder.ParentID = destinationFolderID;
350 invService.MoveFolder(folder); 368 invService.MoveFolder(folder);
351 } 369 }
352 } 370 }
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 }
353 } 382 }
354 } 383 }
355 else if ( 384 else if (
@@ -370,9 +399,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
370 InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId); 399 InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId);
371 item = invService.GetItem(item); 400 item = invService.GetItem(item);
372 InventoryFolderBase folder = null; 401 InventoryFolderBase folder = null;
402 UUID? previousParentFolderID = null;
373 403
374 if (item != null && trashFolder != null) 404 if (item != null && trashFolder != null)
375 { 405 {
406 previousParentFolderID = item.Folder;
376 item.Folder = trashFolder.ID; 407 item.Folder = trashFolder.ID;
377 408
378 // Diva comment: can't we just update this item??? 409 // Diva comment: can't we just update this item???
@@ -388,6 +419,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
388 419
389 if (folder != null & trashFolder != null) 420 if (folder != null & trashFolder != null)
390 { 421 {
422 previousParentFolderID = folder.ParentID;
391 folder.ParentID = trashFolder.ID; 423 folder.ParentID = trashFolder.ID;
392 invService.MoveFolder(folder); 424 invService.MoveFolder(folder);
393 client.SendBulkUpdateInventory(folder); 425 client.SendBulkUpdateInventory(folder);
@@ -408,6 +440,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
408 client.SendAgentAlertMessage("Unable to delete "+ 440 client.SendAgentAlertMessage("Unable to delete "+
409 "received inventory" + reason, false); 441 "received inventory" + reason, false);
410 } 442 }
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 }
411 453
412 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID)); 454 ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID));
413 455
@@ -423,69 +465,69 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
423 } 465 }
424 } 466 }
425 467
426 public bool NeedSceneCacheClear(UUID agentID, Scene scene) 468// public bool NeedSceneCacheClear(UUID agentID, Scene scene)
427 { 469// {
428 if (!m_AgentRegions.ContainsKey(agentID)) 470// if (!m_AgentRegions.ContainsKey(agentID))
429 { 471// {
430 // Since we can get here two ways, we need to scan 472// // Since we can get here two ways, we need to scan
431 // the scenes here. This is somewhat more expensive 473// // the scenes here. This is somewhat more expensive
432 // but helps avoid a nasty bug 474// // but helps avoid a nasty bug
433 // 475// //
434 476//
435 foreach (Scene s in m_Scenelist) 477// foreach (Scene s in m_Scenelist)
436 { 478// {
437 ScenePresence presence; 479// ScenePresence presence;
438 480//
439 if (s.TryGetScenePresence(agentID, out presence)) 481// if (s.TryGetScenePresence(agentID, out presence))
440 { 482// {
441 // If the agent is in this scene, then we 483// // If the agent is in this scene, then we
442 // are being called twice in a single 484// // are being called twice in a single
443 // teleport. This is wasteful of cycles 485// // teleport. This is wasteful of cycles
444 // but harmless due to this 2nd level check 486// // but harmless due to this 2nd level check
445 // 487// //
446 // If the agent is found in another scene 488// // If the agent is found in another scene
447 // then the list wasn't current 489// // then the list wasn't current
448 // 490// //
449 // If the agent is totally unknown, then what 491// // If the agent is totally unknown, then what
450 // are we even doing here?? 492// // are we even doing here??
451 // 493// //
452 if (s == scene) 494// if (s == scene)
453 { 495// {
454 //m_log.Debug("[INVTRANSFERMOD]: s == scene. Returning true in " + scene.RegionInfo.RegionName); 496// //m_log.Debug("[INVTRANSFERMOD]: s == scene. Returning true in " + scene.RegionInfo.RegionName);
455 return true; 497// return true;
456 } 498// }
457 else 499// else
458 { 500// {
459 //m_log.Debug("[INVTRANSFERMOD]: s != scene. Returning false in " + scene.RegionInfo.RegionName); 501// //m_log.Debug("[INVTRANSFERMOD]: s != scene. Returning false in " + scene.RegionInfo.RegionName);
460 return false; 502// return false;
461 } 503// }
462 } 504// }
463 } 505// }
464 //m_log.Debug("[INVTRANSFERMOD]: agent not in scene. Returning true in " + scene.RegionInfo.RegionName); 506// //m_log.Debug("[INVTRANSFERMOD]: agent not in scene. Returning true in " + scene.RegionInfo.RegionName);
465 return true; 507// return true;
466 } 508// }
467 509//
468 // The agent is left in current Scene, so we must be 510// // The agent is left in current Scene, so we must be
469 // going to another instance 511// // going to another instance
470 // 512// //
471 if (m_AgentRegions[agentID] == scene) 513// if (m_AgentRegions[agentID] == scene)
472 { 514// {
473 //m_log.Debug("[INVTRANSFERMOD]: m_AgentRegions[agentID] == scene. Returning true in " + scene.RegionInfo.RegionName); 515// //m_log.Debug("[INVTRANSFERMOD]: m_AgentRegions[agentID] == scene. Returning true in " + scene.RegionInfo.RegionName);
474 m_AgentRegions.Remove(agentID); 516// m_AgentRegions.Remove(agentID);
475 return true; 517// return true;
476 } 518// }
477 519//
478 // Another region has claimed the agent 520// // Another region has claimed the agent
479 // 521// //
480 //m_log.Debug("[INVTRANSFERMOD]: last resort. Returning false in " + scene.RegionInfo.RegionName); 522// //m_log.Debug("[INVTRANSFERMOD]: last resort. Returning false in " + scene.RegionInfo.RegionName);
481 return false; 523// return false;
482 } 524// }
483 525//
484 public void ClientLoggedOut(UUID agentID, Scene scene) 526// public void ClientLoggedOut(UUID agentID, Scene scene)
485 { 527// {
486 if (m_AgentRegions.ContainsKey(agentID)) 528// if (m_AgentRegions.ContainsKey(agentID))
487 m_AgentRegions.Remove(agentID); 529// m_AgentRegions.Remove(agentID);
488 } 530// }
489 531
490 /// <summary> 532 /// <summary>
491 /// 533 ///
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs
index 92cf9d1..9c369f6 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]); 189 new Byte[0], true);
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 a889984..1949459 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]); 176 new Byte[0], true);
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]); 184 new Byte[0], true);
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 880b2cc..31e6ce9 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -327,6 +327,14 @@ 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
330 // 338 //
331 // This is it 339 // This is it
332 // 340 //
@@ -358,6 +366,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
358 } 366 }
359 } 367 }
360 368
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
361 /// <summary> 376 /// <summary>
362 /// Determines whether this instance is within the max transfer distance. 377 /// Determines whether this instance is within the max transfer distance.
363 /// </summary> 378 /// </summary>
@@ -473,10 +488,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
473 // both regions 488 // both regions
474 if (sp.ParentID != (uint)0) 489 if (sp.ParentID != (uint)0)
475 sp.StandUp(); 490 sp.StandUp();
476
477 else if (sp.Flying) 491 else if (sp.Flying)
478 teleportFlags |= (uint)TeleportFlags.IsFlying; 492 teleportFlags |= (uint)TeleportFlags.IsFlying;
479 493
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).
480 sp.ControllingClient.SendTeleportStart(teleportFlags); 496 sp.ControllingClient.SendTeleportStart(teleportFlags);
481 497
482 // the avatar.Close below will clear the child region list. We need this below for (possibly) 498 // the avatar.Close below will clear the child region list. We need this below for (possibly)
@@ -552,8 +568,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
552 // So let's wait 568 // So let's wait
553 Thread.Sleep(200); 569 Thread.Sleep(200);
554 570
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.
555 m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath); 575 m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath);
556
557 } 576 }
558 else 577 else
559 { 578 {
@@ -574,7 +593,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
574 593
575 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent..."); 594 //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent...");
576 595
577 if (!UpdateAgent(reg, finalDestination, agent)) 596 if (!UpdateAgent(reg, finalDestination, agent, sp))
578 { 597 {
579 // Region doesn't take it 598 // Region doesn't take it
580 m_log.WarnFormat( 599 m_log.WarnFormat(
@@ -650,7 +669,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
650 // an agent cannot teleport back to this region if it has teleported away. 669 // an agent cannot teleport back to this region if it has teleported away.
651 Thread.Sleep(3000); 670 Thread.Sleep(3000);
652 671
653 sp.Scene.IncomingCloseAgent(sp.UUID); 672 sp.Scene.IncomingCloseAgent(sp.UUID, false);
654 } 673 }
655 else 674 else
656 { 675 {
@@ -658,13 +677,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
658 sp.Reset(); 677 sp.Reset();
659 } 678 }
660 679
661 // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! 680 // Commented pending deletion since this method no longer appears to do anything at all
662 if (sp.Scene.NeedSceneCacheClear(sp.UUID)) 681// // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE!
663 { 682// if (sp.Scene.NeedSceneCacheClear(sp.UUID))
664 m_log.DebugFormat( 683// {
665 "[ENTITY TRANSFER MODULE]: User {0} is going to another region, profile cache removed", 684// m_log.DebugFormat(
666 sp.UUID); 685// "[ENTITY TRANSFER MODULE]: User {0} is going to another region, profile cache removed",
667 } 686// sp.UUID);
687// }
668 688
669 m_entityTransferStateMachine.ResetFromTransit(sp.UUID); 689 m_entityTransferStateMachine.ResetFromTransit(sp.UUID);
670 } 690 }
@@ -701,7 +721,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
701 return success; 721 return success;
702 } 722 }
703 723
704 protected virtual bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agent) 724 protected virtual bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agent, ScenePresence sp)
705 { 725 {
706 return Scene.SimulationService.UpdateAgent(finalDestination, agent); 726 return Scene.SimulationService.UpdateAgent(finalDestination, agent);
707 } 727 }
@@ -1013,6 +1033,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1013 Scene initiatingScene) 1033 Scene initiatingScene)
1014 { 1034 {
1015 Thread.Sleep(10000); 1035 Thread.Sleep(10000);
1036
1016 IMessageTransferModule im = initiatingScene.RequestModuleInterface<IMessageTransferModule>(); 1037 IMessageTransferModule im = initiatingScene.RequestModuleInterface<IMessageTransferModule>();
1017 if (im != null) 1038 if (im != null)
1018 { 1039 {
@@ -1025,11 +1046,22 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1025 (uint)(int)position.X, 1046 (uint)(int)position.X,
1026 (uint)(int)position.Y, 1047 (uint)(int)position.Y,
1027 (uint)(int)position.Z); 1048 (uint)(int)position.Z);
1028 GridInstantMessage m = new GridInstantMessage(initiatingScene, UUID.Zero, 1049
1029 "Region", agent.UUID, 1050 GridInstantMessage m
1030 (byte)InstantMessageDialog.GodLikeRequestTeleport, false, 1051 = new GridInstantMessage(
1031 "", gotoLocation, false, new Vector3(127, 0, 0), 1052 initiatingScene,
1032 new Byte[0]); 1053 UUID.Zero,
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
1033 im.SendInstantMessage(m, delegate(bool success) 1065 im.SendInstantMessage(m, delegate(bool success)
1034 { 1066 {
1035 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Client Initiating Teleport sending IM success = {0}", success); 1067 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Client Initiating Teleport sending IM success = {0}", success);
@@ -1191,11 +1223,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1191 // the user may change their profile information in other region, 1223 // the user may change their profile information in other region,
1192 // so the userinfo in UserProfileCache is not reliable any more, delete it 1224 // so the userinfo in UserProfileCache is not reliable any more, delete it
1193 // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! 1225 // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE!
1194 if (agent.Scene.NeedSceneCacheClear(agent.UUID)) 1226// if (agent.Scene.NeedSceneCacheClear(agent.UUID))
1195 { 1227// {
1196 m_log.DebugFormat( 1228// m_log.DebugFormat(
1197 "[ENTITY TRANSFER MODULE]: User {0} is going to another region", agent.UUID); 1229// "[ENTITY TRANSFER MODULE]: User {0} is going to another region", agent.UUID);
1198 } 1230// }
1199 1231
1200 //m_log.Debug("AFTER CROSS"); 1232 //m_log.Debug("AFTER CROSS");
1201 //Scene.DumpChildrenSeeds(UUID); 1233 //Scene.DumpChildrenSeeds(UUID);
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
index 3010b59..b16c37a 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
@@ -54,6 +54,59 @@ 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
57 #region ISharedRegionModule 110 #region ISharedRegionModule
58 111
59 public override string Name 112 public override string Name
@@ -72,8 +125,18 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
72 { 125 {
73 IConfig transferConfig = source.Configs["EntityTransfer"]; 126 IConfig transferConfig = source.Configs["EntityTransfer"];
74 if (transferConfig != null) 127 if (transferConfig != null)
128 {
75 m_levelHGTeleport = transferConfig.GetInt("LevelHGTeleport", 0); 129 m_levelHGTeleport = transferConfig.GetInt("LevelHGTeleport", 0);
76 130
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
77 InitialiseCommon(source); 140 InitialiseCommon(source);
78 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: {0} enabled.", Name); 141 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: {0} enabled.", Name);
79 } 142 }
@@ -85,7 +148,36 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
85 base.AddRegion(scene); 148 base.AddRegion(scene);
86 149
87 if (m_Enabled) 150 if (m_Enabled)
151 {
88 scene.RegisterModuleInterface<IUserAgentVerificationModule>(this); 152 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 }
89 } 181 }
90 182
91 protected override void OnNewClient(IClientAPI client) 183 protected override void OnNewClient(IClientAPI client)
@@ -120,7 +212,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
120 int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, region.RegionID); 212 int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, region.RegionID);
121 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: region {0} flags: {1}", region.RegionID, flags); 213 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: region {0} flags: {1}", region.RegionID, flags);
122 214
123 if ((flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0) 215 if ((flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0)
124 { 216 {
125 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Destination region {0} is hyperlink", region.RegionID); 217 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Destination region {0} is hyperlink", region.RegionID);
126 GridRegion real_destination = m_GatekeeperConnector.GetHyperlinkRegion(region, region.RegionID); 218 GridRegion real_destination = m_GatekeeperConnector.GetHyperlinkRegion(region, region.RegionID);
@@ -140,7 +232,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
140 return true; 232 return true;
141 233
142 int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID); 234 int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID);
143 if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0) 235 if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0)
144 return true; 236 return true;
145 237
146 return false; 238 return false;
@@ -153,6 +245,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
153 { 245 {
154 // Log them out of this grid 246 // Log them out of this grid
155 Scene.PresenceService.LogoutAgent(sp.ControllingClient.SessionId); 247 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);
156 } 250 }
157 } 251 }
158 252
@@ -162,11 +256,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
162 reason = string.Empty; 256 reason = string.Empty;
163 logout = false; 257 logout = false;
164 int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID); 258 int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID);
165 if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0) 259 if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0)
166 { 260 {
167 // this user is going to another grid 261 // this user is going to another grid
168 // check if HyperGrid teleport is allowed, based on user level 262 // for local users, check if HyperGrid teleport is allowed, based on user level
169 if (sp.UserLevel < m_levelHGTeleport) 263 if (Scene.UserManagementModule.IsLocalGridUser(sp.UUID) && sp.UserLevel < m_levelHGTeleport)
170 { 264 {
171 m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unable to HG teleport agent due to insufficient UserLevel."); 265 m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unable to HG teleport agent due to insufficient UserLevel.");
172 reason = "Hypergrid teleport not allowed"; 266 reason = "Hypergrid teleport not allowed";
@@ -200,6 +294,124 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
200 TeleportHome(id, client); 294 TeleportHome(id, client);
201 } 295 }
202 296
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
203 public override bool TeleportHome(UUID id, IClientAPI client) 415 public override bool TeleportHome(UUID id, IClientAPI client)
204 { 416 {
205 m_log.DebugFormat( 417 m_log.DebugFormat(
@@ -375,4 +587,4 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
375 return region; 587 return region;
376 } 588 }
377 } 589 }
378} \ No newline at end of file 590}
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs
index eaadc1b..f8ec6de 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 AssetBase FetchAsset(string url, UUID assetID) 74 public AssetMetadata FetchMetadata(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 AssetBase asset = m_scene.AssetService.Get(url + assetID.ToString()); 79 AssetMetadata meta = m_scene.AssetService.GetMetadata(url + assetID.ToString());
80 80
81 if (asset != null) 81 if (meta != null)
82 { 82 m_log.DebugFormat("[HG ASSET MAPPER]: Fetched metadata for asset {0} of type {1} from {2} ", assetID, meta.Type, url);
83 m_log.DebugFormat("[HG ASSET MAPPER]: Copied asset {0} from {1} to local asset server. ", asset.ID, url); 83 else
84 return asset; 84 m_log.DebugFormat("[HG ASSET MAPPER]: Unable to fetched metadata for asset {0} from {1} ", assetID, url);
85 } 85
86 return null; 86 return meta;
87 } 87 }
88 88
89 public bool PostAsset(string url, AssetBase asset) 89 public bool PostAsset(string url, AssetBase asset)
@@ -93,6 +93,7 @@ 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;
96 // See long comment in AssetCache.AddAsset 97 // See long comment in AssetCache.AddAsset
97 if (!asset.Temporary || asset.Local) 98 if (!asset.Temporary || asset.Local)
98 { 99 {
@@ -103,14 +104,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
103 // not having a global naming infrastructure 104 // not having a global naming infrastructure
104 AssetBase asset1 = new AssetBase(asset.FullID, asset.Name, asset.Type, asset.Metadata.CreatorID); 105 AssetBase asset1 = new AssetBase(asset.FullID, asset.Name, asset.Type, asset.Metadata.CreatorID);
105 Copy(asset, asset1); 106 Copy(asset, asset1);
106 try 107 asset1.ID = url + asset.ID;
107 {
108 asset1.ID = url + asset.ID;
109 }
110 catch
111 {
112 m_log.Warn("[HG ASSET MAPPER]: Oops.");
113 }
114 108
115 AdjustIdentifiers(asset1.Metadata); 109 AdjustIdentifiers(asset1.Metadata);
116 if (asset1.Metadata.Type == (sbyte)AssetType.Object) 110 if (asset1.Metadata.Type == (sbyte)AssetType.Object)
@@ -118,11 +112,17 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
118 else 112 else
119 asset1.Data = asset.Data; 113 asset1.Data = asset.Data;
120 114
121 m_scene.AssetService.Store(asset1); 115 string id = m_scene.AssetService.Store(asset1);
122 m_log.DebugFormat("[HG ASSET MAPPER]: Posted copy of asset {0} from local asset server to {1}", asset1.ID, url); 116 if (id == string.Empty)
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 true; 124 return success;
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,28 +222,17 @@ 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 AssetCache 225 // Get the item from the remote asset server onto the local AssetService
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);
230 226
231 if (asset != null) 227 AssetMetadata meta = FetchMetadata(userAssetURL, assetID);
232 { 228 if (meta == null)
233 // OK, now fetch the inside. 229 return;
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);
241 230
242 m_log.DebugFormat("[HG ASSET MAPPER]: Successfully fetched asset {0} from asset server {1}", asset.ID, userAssetURL); 231 // The act of gathering UUIDs downloads the assets from the remote server
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);
243 235
244 }
245 else
246 m_log.Warn("[HG ASSET MAPPER]: Could not fetch asset from remote asset server " + userAssetURL);
247 } 236 }
248 237
249 238
@@ -257,19 +246,23 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
257 if (asset != null) 246 if (asset != null)
258 { 247 {
259 Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>(); 248 Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>();
260 HGUuidGatherer uuidGatherer = new HGUuidGatherer(this, m_scene.AssetService, string.Empty); 249 HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, string.Empty);
261 uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids); 250 uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids);
251 bool success = false;
262 foreach (UUID uuid in ids.Keys) 252 foreach (UUID uuid in ids.Keys)
263 { 253 {
264 asset = m_scene.AssetService.Get(uuid.ToString()); 254 asset = m_scene.AssetService.Get(uuid.ToString());
265 if (asset == null) 255 if (asset == null)
266 m_log.DebugFormat("[HG ASSET MAPPER]: Could not find asset {0}", uuid); 256 m_log.DebugFormat("[HG ASSET MAPPER]: Could not find asset {0}", uuid);
267 else 257 else
268 PostAsset(userAssetURL, asset); 258 success = PostAsset(userAssetURL, asset);
269 } 259 }
270 260
271 // maybe all pieces got there... 261 // maybe all pieces got there...
272 m_log.DebugFormat("[HG ASSET MAPPER]: Successfully posted item {0} to asset server {1}", assetID, userAssetURL); 262 if (!success)
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);
273 266
274 } 267 }
275 else 268 else
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs
index cf72b58..6bb758e 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", false); 95 m_RestrictInventoryAccessAbroad = thisModuleConfig.GetBoolean("RestrictInventoryAccessAbroad", true);
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,8 +263,13 @@ 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 return base.RezObject(remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection, 266 SceneObjectGroup sog = 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;
268 273
269 } 274 }
270 275
@@ -308,6 +313,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
308 protected override InventoryItemBase GetItem(UUID agentID, UUID itemID) 313 protected override InventoryItemBase GetItem(UUID agentID, UUID itemID)
309 { 314 {
310 InventoryItemBase item = base.GetItem(agentID, itemID); 315 InventoryItemBase item = base.GetItem(agentID, itemID);
316 if (item == null)
317 return null;
311 318
312 string userAssetServer = string.Empty; 319 string userAssetServer = string.Empty;
313 if (IsForeignUser(agentID, out userAssetServer)) 320 if (IsForeignUser(agentID, out userAssetServer))
@@ -344,6 +351,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
344 351
345 private void ProcessInventoryForArriving(IClientAPI client) 352 private void ProcessInventoryForArriving(IClientAPI client)
346 { 353 {
354 // No-op for now, but we may need to do something for freign users inventory
347 } 355 }
348 356
349 // 357 //
@@ -390,6 +398,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
390 398
391 private void ProcessInventoryForLeaving(IClientAPI client) 399 private void ProcessInventoryForLeaving(IClientAPI client)
392 { 400 {
401 // No-op for now
393 } 402 }
394 403
395 #endregion 404 #endregion
diff --git a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs
index e135c21..e411585 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 m_log.InfoFormat( 98 MainConsole.Instance.OutputFormat(
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 m_log.InfoFormat( 105 MainConsole.Instance.OutputFormat(
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 65e4c90..fd8d5e3 100755
--- a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs
+++ b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs
@@ -1,161 +1,170 @@
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 Write(string line) 114 public void Flush()
115 { 115 {
116 if (!Enabled) return; 116 if (!Enabled) return;
117 try 117 if (m_logFile != null)
118 { 118 {
119 lock (m_logFileWriteLock) 119 m_logFile.Flush();
120 { 120 }
121 DateTime now = DateTime.Now; 121 }
122 if (m_logFile == null || now > m_logFileEndTime) 122
123 { 123 public void Write(string line)
124 if (m_logFile != null) 124 {
125 { 125 if (!Enabled) return;
126 m_logFile.Close(); 126 try
127 m_logFile.Dispose(); 127 {
128 m_logFile = null; 128 lock (m_logFileWriteLock)
129 } 129 {
130 130 DateTime now = DateTime.Now;
131 // First log file or time has expired, start writing to a new log file 131 if (m_logFile == null || now > m_logFileEndTime)
132 m_logFileEndTime = now + m_logFileLife; 132 {
133 string path = (m_logDirectory.Length > 0 ? m_logDirectory 133 if (m_logFile != null)
134 + System.IO.Path.DirectorySeparatorChar.ToString() : "") 134 {
135 + String.Format("{0}{1}.log", LogFileHeader, now.ToString("yyyyMMddHHmmss")); 135 m_logFile.Close();
136 m_logFile = new StreamWriter(File.Open(path, FileMode.Append, FileAccess.Write)); 136 m_logFile.Dispose();
137 } 137 m_logFile = null;
138 if (m_logFile != null) 138 }
139 { 139
140 StringBuilder buff = new StringBuilder(line.Length + 25); 140 // First log file or time has expired, start writing to a new log file
141 buff.Append(now.ToString("yyyyMMddHHmmssfff")); 141 m_logFileEndTime = now + m_logFileLife;
142 // buff.Append(now.ToString("yyyyMMddHHmmss")); 142 string path = (m_logDirectory.Length > 0 ? m_logDirectory
143 buff.Append(","); 143 + System.IO.Path.DirectorySeparatorChar.ToString() : "")
144 buff.Append(line); 144 + String.Format("{0}{1}.log", LogFileHeader, now.ToString("yyyyMMddHHmmss"));
145 buff.Append("\r\n"); 145 m_logFile = new StreamWriter(File.Open(path, FileMode.Append, FileAccess.Write));
146 m_logFile.Write(buff.ToString()); 146 }
147 } 147 if (m_logFile != null)
148 } 148 {
149 } 149 StringBuilder buff = new StringBuilder(line.Length + 25);
150 catch (Exception e) 150 buff.Append(now.ToString("yyyyMMddHHmmssfff"));
151 { 151 // buff.Append(now.ToString("yyyyMMddHHmmss"));
152 if (ErrorLogger != null) 152 buff.Append(",");
153 { 153 buff.Append(line);
154 ErrorLogger.ErrorFormat("{0}: FAILURE WRITING TO LOGFILE: {1}", LogHeader, e); 154 buff.Append("\r\n");
155 } 155 m_logFile.Write(buff.ToString());
156 Enabled = false; 156 }
157 } 157 }
158 return; 158 }
159 } 159 catch (Exception e)
160 } 160 {
161} \ No newline at end of file 161 if (ErrorLogger != null)
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 4eecaa2..acefc97 100644
--- a/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs
@@ -137,6 +137,9 @@ 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.
140 AddUser(userID, names[0], names[1], uriStr); 143 AddUser(userID, names[0], names[1], uriStr);
141 m_log.DebugFormat("[USER MANAGEMENT MODULE]: User {0}@{1} found", words[0], words[1]); 144 m_log.DebugFormat("[USER MANAGEMENT MODULE]: User {0}@{1} found", words[0], words[1]);
142 } 145 }
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
index f4ed67b..b4811da 100644
--- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
@@ -31,6 +31,7 @@ using System.Reflection;
31 31
32using OpenSim.Framework; 32using OpenSim.Framework;
33using OpenSim.Framework.Console; 33using OpenSim.Framework.Console;
34using OpenSim.Region.ClientStack.LindenUDP;
34using OpenSim.Region.Framework; 35using OpenSim.Region.Framework;
35using OpenSim.Region.Framework.Interfaces; 36using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes; 37using OpenSim.Region.Framework.Scenes;
@@ -429,8 +430,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
429 430
430 public void AddUser(UUID uuid, string first, string last, string homeURL) 431 public void AddUser(UUID uuid, string first, string last, string homeURL)
431 { 432 {
432 // m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, first {1}, last {2}, url {3}", uuid, first, last, homeURL); 433 //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}", 556 MainConsole.Instance.Output(String.Format("{0} {1} {2} ({3})",
557 kvp.Key, kvp.Value.FirstName, kvp.Value.LastName)); 557 kvp.Key, kvp.Value.FirstName, kvp.Value.LastName, kvp.Value.HomeURL));
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 424e0ab..6c73d91 100644
--- a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml
+++ b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml
@@ -15,6 +15,7 @@
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" />
18 <RegionModule id="PrimCountModule" type="OpenSim.Region.CoreModules.World.Land.PrimCountModule" /> 19 <RegionModule id="PrimCountModule" type="OpenSim.Region.CoreModules.World.Land.PrimCountModule" />
19 <RegionModule id="ExportSerialisationModule" type="OpenSim.Region.CoreModules.World.Serialiser.SerialiserModule" /> 20 <RegionModule id="ExportSerialisationModule" type="OpenSim.Region.CoreModules.World.Serialiser.SerialiserModule" />
20 <RegionModule id="ArchiverModule" type="OpenSim.Region.CoreModules.World.Archiver.ArchiverModule" /> 21 <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
new file mode 100644
index 0000000..fce9490
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs
@@ -0,0 +1,61 @@
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 18bd018..93a045e 100644
--- a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs
@@ -42,13 +42,29 @@ 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
52 private Dictionary<UUID, Scene> RegisteredScenes = new Dictionary<UUID, Scene>(); 68 private Dictionary<UUID, Scene> RegisteredScenes = new Dictionary<UUID, Scene>();
53 69
54 private Dictionary<string, IDynamicTextureRender> RenderPlugins = 70 private Dictionary<string, IDynamicTextureRender> RenderPlugins =
@@ -56,6 +72,15 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
56 72
57 private Dictionary<UUID, DynamicTextureUpdater> Updaters = new Dictionary<UUID, DynamicTextureUpdater>(); 73 private Dictionary<UUID, DynamicTextureUpdater> Updaters = new Dictionary<UUID, DynamicTextureUpdater>();
58 74
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
59 #region IDynamicTextureManager Members 84 #region IDynamicTextureManager Members
60 85
61 public void RegisterRender(string handleType, IDynamicTextureRender render) 86 public void RegisterRender(string handleType, IDynamicTextureRender render)
@@ -69,17 +94,17 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
69 /// <summary> 94 /// <summary>
70 /// Called by code which actually renders the dynamic texture to supply texture data. 95 /// Called by code which actually renders the dynamic texture to supply texture data.
71 /// </summary> 96 /// </summary>
72 /// <param name="id"></param> 97 /// <param name="updaterId"></param>
73 /// <param name="data"></param> 98 /// <param name="texture"></param>
74 public void ReturnData(UUID id, byte[] data) 99 public void ReturnData(UUID updaterId, IDynamicTexture texture)
75 { 100 {
76 DynamicTextureUpdater updater = null; 101 DynamicTextureUpdater updater = null;
77 102
78 lock (Updaters) 103 lock (Updaters)
79 { 104 {
80 if (Updaters.ContainsKey(id)) 105 if (Updaters.ContainsKey(updaterId))
81 { 106 {
82 updater = Updaters[id]; 107 updater = Updaters[updaterId];
83 } 108 }
84 } 109 }
85 110
@@ -88,7 +113,16 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
88 if (RegisteredScenes.ContainsKey(updater.SimUUID)) 113 if (RegisteredScenes.ContainsKey(updater.SimUUID))
89 { 114 {
90 Scene scene = RegisteredScenes[updater.SimUUID]; 115 Scene scene = RegisteredScenes[updater.SimUUID];
91 updater.DataReceived(data, scene); 116 UUID newTextureID = updater.DataReceived(texture.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 }
92 } 126 }
93 } 127 }
94 128
@@ -104,6 +138,27 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
104 } 138 }
105 } 139 }
106 140
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
107 public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, 162 public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url,
108 string extraParams, int updateTimer) 163 string extraParams, int updateTimer)
109 { 164 {
@@ -167,22 +222,61 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
167 public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, 222 public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data,
168 string extraParams, int updateTimer, bool SetBlending, int disp, byte AlphaValue, int face) 223 string extraParams, int updateTimer, bool SetBlending, int disp, byte AlphaValue, int face)
169 { 224 {
170 if (RenderPlugins.ContainsKey(contentType)) 225 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)
171 { 261 {
172 DynamicTextureUpdater updater = new DynamicTextureUpdater(); 262 string reuseableTextureKey = GenerateReusableTextureKey(data, extraParams);
173 updater.SimUUID = simID; 263 objReusableTextureUUID = m_reuseableDynamicTextures.Get(reuseableTextureKey);
174 updater.PrimID = primID; 264
175 updater.ContentType = contentType; 265 if (objReusableTextureUUID != null)
176 updater.BodyData = data; 266 {
177 updater.UpdateTimer = updateTimer; 267 // If something else has removed this temporary asset from the cache, detect and invalidate
178 updater.UpdaterID = UUID.Random(); 268 // our cached uuid.
179 updater.Params = extraParams; 269 if (scene.AssetService.GetMetadata(objReusableTextureUUID.ToString()) == null)
180 updater.BlendWithOldTexture = SetBlending; 270 {
181 updater.FrontAlpha = AlphaValue; 271 m_reuseableDynamicTextures.Invalidate(reuseableTextureKey);
182 updater.Face = face; 272 objReusableTextureUUID = null;
183 updater.Url = "Local image"; 273 }
184 updater.Disp = disp; 274 }
275 }
185 276
277 // We cannot reuse a dynamic texture if the data is going to be blended with something already there.
278 if (objReusableTextureUUID == null)
279 {
186 lock (Updaters) 280 lock (Updaters)
187 { 281 {
188 if (!Updaters.ContainsKey(updater.UpdaterID)) 282 if (!Updaters.ContainsKey(updater.UpdaterID))
@@ -191,11 +285,29 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
191 } 285 }
192 } 286 }
193 287
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
194 RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams); 292 RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams);
195 return updater.UpdaterID;
196 } 293 }
197 294 else
198 return UUID.Zero; 295 {
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);
199 } 311 }
200 312
201 public void GetDrawStringSize(string contentType, string text, string fontName, int fontSize, 313 public void GetDrawStringSize(string contentType, string text, string fontName, int fontSize,
@@ -215,6 +327,13 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
215 327
216 public void Initialise(Scene scene, IConfigSource config) 328 public void Initialise(Scene scene, IConfigSource config)
217 { 329 {
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
218 if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID)) 337 if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID))
219 { 338 {
220 RegisteredScenes.Add(scene.RegionInfo.RegionID, scene); 339 RegisteredScenes.Add(scene.RegionInfo.RegionID, scene);
@@ -224,6 +343,11 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
224 343
225 public void PostInitialise() 344 public void PostInitialise()
226 { 345 {
346 if (ReuseTextures)
347 {
348 m_reuseableDynamicTextures = new Cache(CacheMedium.Memory, CacheStrategy.Conservative);
349 m_reuseableDynamicTextures.DefaultTTL = new TimeSpan(24, 0, 0);
350 }
227 } 351 }
228 352
229 public void Close() 353 public void Close()
@@ -269,9 +393,60 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
269 } 393 }
270 394
271 /// <summary> 395 /// <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>
272 /// Called once new texture data has been received for this updater. 443 /// Called once new texture data has been received for this updater.
273 /// </summary> 444 /// </summary>
274 public void DataReceived(byte[] data, Scene scene) 445 /// <param name="data"></param>
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)
275 { 450 {
276 SceneObjectPart part = scene.GetSceneObjectPart(PrimID); 451 SceneObjectPart part = scene.GetSceneObjectPart(PrimID);
277 452
@@ -281,7 +456,8 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
281 String.Format("DynamicTextureModule: Error preparing image using URL {0}", Url); 456 String.Format("DynamicTextureModule: Error preparing image using URL {0}", Url);
282 scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Say, 457 scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Say,
283 0, part.ParentGroup.RootPart.AbsolutePosition, part.Name, part.UUID, false); 458 0, part.ParentGroup.RootPart.AbsolutePosition, part.Name, part.UUID, false);
284 return; 459
460 return UUID.Zero;
285 } 461 }
286 462
287 byte[] assetData = null; 463 byte[] assetData = null;
@@ -319,56 +495,29 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
319 IJ2KDecoder cacheLayerDecode = scene.RequestModuleInterface<IJ2KDecoder>(); 495 IJ2KDecoder cacheLayerDecode = scene.RequestModuleInterface<IJ2KDecoder>();
320 if (cacheLayerDecode != null) 496 if (cacheLayerDecode != null)
321 { 497 {
322 cacheLayerDecode.Decode(asset.FullID, asset.Data); 498 if (!cacheLayerDecode.Decode(asset.FullID, asset.Data))
323 cacheLayerDecode = null; 499 m_log.WarnFormat(
500 "[DYNAMIC TEXTURE MODULE]: Decoding of dynamically generated asset {0} for {1} in {2} failed",
501 asset.ID, part.Name, part.ParentGroup.Scene.Name);
324 } 502 }
325 503
326 UUID oldID = UUID.Zero; 504 UUID oldID = UpdatePart(part, asset.FullID);
327
328 lock (part)
329 {
330 // mostly keep the values from before
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 }
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 505
361 if (oldID != UUID.Zero && ((Disp & DISP_EXPIRE) != 0)) 506 if (oldID != UUID.Zero && ((Disp & DISP_EXPIRE) != 0))
362 { 507 {
363 if (oldAsset == null) oldAsset = scene.AssetService.Get(oldID.ToString()); 508 if (oldAsset == null)
509 oldAsset = scene.AssetService.Get(oldID.ToString());
510
364 if (oldAsset != null) 511 if (oldAsset != null)
365 { 512 {
366 if (oldAsset.Temporary == true) 513 if (oldAsset.Temporary)
367 { 514 {
368 scene.AssetService.Delete(oldID.ToString()); 515 scene.AssetService.Delete(oldID.ToString());
369 } 516 }
370 } 517 }
371 } 518 }
519
520 return asset.FullID;
372 } 521 }
373 522
374 private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha) 523 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 56221aa..0b9174f 100644
--- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
@@ -58,6 +58,7 @@ 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";
61 //public ManualResetEvent ev; 62 //public ManualResetEvent ev;
62 public bool requestDone; 63 public bool requestDone;
63 public int startTime; 64 public int startTime;
@@ -270,6 +271,22 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
270 } 271 }
271 } 272 }
272 273
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
273 public void HttpResponse(UUID request, int status, string body) 290 public void HttpResponse(UUID request, int status, string body)
274 { 291 {
275 lock (m_RequestMap) 292 lock (m_RequestMap)
diff --git a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
index 6f83948..45e6527 100644
--- a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs
@@ -32,6 +32,7 @@ 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;
35using OpenSim.Region.Framework.Interfaces; 36using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes; 37using OpenSim.Region.Framework.Scenes;
37using log4net; 38using log4net;
@@ -67,12 +68,18 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
67 return true; 68 return true;
68 } 69 }
69 70
70 public byte[] ConvertUrl(string url, string extraParams) 71// public bool AlwaysIdenticalConversion(string bodyData, 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)
71 { 78 {
72 return null; 79 return null;
73 } 80 }
74 81
75 public byte[] ConvertStream(Stream data, string extraParams) 82 public IDynamicTexture ConvertData(string bodyData, string extraParams)
76 { 83 {
77 return null; 84 return null;
78 } 85 }
@@ -165,11 +172,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
165 172
166 private void HttpRequestReturn(IAsyncResult result) 173 private void HttpRequestReturn(IAsyncResult result)
167 { 174 {
168
169 RequestState state = (RequestState) result.AsyncState; 175 RequestState state = (RequestState) result.AsyncState;
170 WebRequest request = (WebRequest) state.Request; 176 WebRequest request = (WebRequest) state.Request;
171 Stream stream = null; 177 Stream stream = null;
172 byte[] imageJ2000 = new byte[0]; 178 byte[] imageJ2000 = new byte[0];
179 Size newSize = new Size(0, 0);
173 180
174 try 181 try
175 { 182 {
@@ -182,37 +189,43 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
182 try 189 try
183 { 190 {
184 Bitmap image = new Bitmap(stream); 191 Bitmap image = new Bitmap(stream);
185 Size newsize;
186 192
187 // TODO: make this a bit less hard coded 193 // TODO: make this a bit less hard coded
188 if ((image.Height < 64) && (image.Width < 64)) 194 if ((image.Height < 64) && (image.Width < 64))
189 { 195 {
190 newsize = new Size(32, 32); 196 newSize.Width = 32;
197 newSize.Height = 32;
191 } 198 }
192 else if ((image.Height < 128) && (image.Width < 128)) 199 else if ((image.Height < 128) && (image.Width < 128))
193 { 200 {
194 newsize = new Size(64, 64); 201 newSize.Width = 64;
202 newSize.Height = 64;
195 } 203 }
196 else if ((image.Height < 256) && (image.Width < 256)) 204 else if ((image.Height < 256) && (image.Width < 256))
197 { 205 {
198 newsize = new Size(128, 128); 206 newSize.Width = 128;
207 newSize.Height = 128;
199 } 208 }
200 else if ((image.Height < 512 && image.Width < 512)) 209 else if ((image.Height < 512 && image.Width < 512))
201 { 210 {
202 newsize = new Size(256, 256); 211 newSize.Width = 256;
212 newSize.Height = 256;
203 } 213 }
204 else if ((image.Height < 1024 && image.Width < 1024)) 214 else if ((image.Height < 1024 && image.Width < 1024))
205 { 215 {
206 newsize = new Size(512, 512); 216 newSize.Width = 512;
217 newSize.Height = 512;
207 } 218 }
208 else 219 else
209 { 220 {
210 newsize = new Size(1024, 1024); 221 newSize.Width = 1024;
222 newSize.Height = 1024;
211 } 223 }
212 224
213 Bitmap resize = new Bitmap(image, newsize); 225 using (Bitmap resize = new Bitmap(image, newSize))
214 226 {
215 imageJ2000 = OpenJPEG.EncodeFromImage(resize, true); 227 imageJ2000 = OpenJPEG.EncodeFromImage(resize, true);
228 }
216 } 229 }
217 catch (Exception) 230 catch (Exception)
218 { 231 {
@@ -227,7 +240,6 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
227 } 240 }
228 catch (WebException) 241 catch (WebException)
229 { 242 {
230
231 } 243 }
232 finally 244 finally
233 { 245 {
@@ -236,9 +248,14 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
236 stream.Close(); 248 stream.Close();
237 } 249 }
238 } 250 }
239 m_log.DebugFormat("[LOADIMAGEURLMODULE] Returning {0} bytes of image data for request {1}", 251
252 m_log.DebugFormat("[LOADIMAGEURLMODULE]: Returning {0} bytes of image data for request {1}",
240 imageJ2000.Length, state.RequestID); 253 imageJ2000.Length, state.RequestID);
241 m_textureManager.ReturnData(state.RequestID, imageJ2000); 254
255 m_textureManager.ReturnData(
256 state.RequestID,
257 new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture(
258 request.RequestUri, null, imageJ2000, newSize, false));
242 } 259 }
243 260
244 #region Nested type: RequestState 261 #region Nested type: RequestState
diff --git a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
index c5c96a9..dc54c3f 100644
--- a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
@@ -130,13 +130,25 @@ 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
133 public void RegisterScriptInvocation(object target, string meth) 146 public void RegisterScriptInvocation(object target, string meth)
134 { 147 {
135 MethodInfo mi = target.GetType().GetMethod(meth, 148 MethodInfo mi = GetMethodInfoFromType(target.GetType(), meth, true);
136 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
137 if (mi == null) 149 if (mi == null)
138 { 150 {
139 m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}",meth); 151 m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}", meth);
140 return; 152 return;
141 } 153 }
142 154
@@ -151,38 +163,71 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms
151 163
152 public void RegisterScriptInvocation(object target, MethodInfo mi) 164 public void RegisterScriptInvocation(object target, MethodInfo mi)
153 { 165 {
154 m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, target.GetType().Name); 166 m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, (target is Type) ? ((Type)target).Name : target.GetType().Name);
155 167
156 Type delegateType; 168 Type delegateType;
157 var typeArgs = mi.GetParameters() 169 List<Type> typeArgs = mi.GetParameters()
158 .Select(p => p.ParameterType) 170 .Select(p => p.ParameterType)
159 .ToList(); 171 .ToList();
160 172
161 if (mi.ReturnType == typeof(void)) 173 if (mi.ReturnType == typeof(void))
162 { 174 {
163 delegateType = Expression.GetActionType(typeArgs.ToArray()); 175 delegateType = Expression.GetActionType(typeArgs.ToArray());
164 } 176 }
165 else 177 else
166 { 178 {
167 typeArgs.Add(mi.ReturnType); 179 typeArgs.Add(mi.ReturnType);
168 delegateType = Expression.GetFuncType(typeArgs.ToArray()); 180 delegateType = Expression.GetFuncType(typeArgs.ToArray());
169 } 181 }
170 182
171 Delegate fcall = Delegate.CreateDelegate(delegateType, target, mi); 183 Delegate fcall;
184 if (!(target is Type))
185 fcall = Delegate.CreateDelegate(delegateType, target, mi);
186 else
187 fcall = Delegate.CreateDelegate(delegateType, (Type)target, mi.Name);
172 188
173 lock (m_scriptInvocation) 189 lock (m_scriptInvocation)
174 { 190 {
175 ParameterInfo[] parameters = fcall.Method.GetParameters (); 191 ParameterInfo[] parameters = fcall.Method.GetParameters();
176 if (parameters.Length < 2) // Must have two UUID params 192 if (parameters.Length < 2) // Must have two UUID params
177 return; 193 return;
178 194
179 // Hide the first two parameters 195 // Hide the first two parameters
180 Type[] parmTypes = new Type[parameters.Length - 2]; 196 Type[] parmTypes = new Type[parameters.Length - 2];
181 for (int i = 2 ; i < parameters.Length ; i++) 197 for (int i = 2; i < parameters.Length; i++)
182 parmTypes[i - 2] = parameters[i].ParameterType; 198 parmTypes[i - 2] = parameters[i].ParameterType;
183 m_scriptInvocation[fcall.Method.Name] = new ScriptInvocationData(fcall.Method.Name, fcall, parmTypes, fcall.Method.ReturnType); 199 m_scriptInvocation[fcall.Method.Name] = new ScriptInvocationData(fcall.Method.Name, fcall, parmTypes, fcall.Method.ReturnType);
184 } 200 }
185 } 201 }
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 }
186 231
187 public Delegate[] GetScriptInvocationList() 232 public Delegate[] GetScriptInvocationList()
188 { 233 {
@@ -285,6 +330,20 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms
285 } 330 }
286 } 331 }
287 332
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
288 /// <summary> 347 /// <summary>
289 /// Operation to check for a registered constant 348 /// Operation to check for a registered constant
290 /// </summary> 349 /// </summary>
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
index 9787c8c..41baccc 100644
--- a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs
@@ -45,31 +45,292 @@ 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 48 public class VectorRenderModuleTests : OpenSimTestCase
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
50 [Test] 67 [Test]
51 public void TestDraw() 68 public void TestDraw()
52 { 69 {
53 TestHelpers.InMethod(); 70 TestHelpers.InMethod();
54 71
55 Scene scene = new SceneHelpers().SetupScene(); 72 SetupScene(false);
56 DynamicTextureModule dtm = new DynamicTextureModule(); 73 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
57 VectorRenderModule vrm = new VectorRenderModule();
58 SceneHelpers.SetupSceneModules(scene, dtm, vrm);
59
60 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene);
61 UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; 74 UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
62 75
63 dtm.AddDynamicTextureData( 76 m_dtm.AddDynamicTextureData(
64 scene.RegionInfo.RegionID, 77 m_scene.RegionInfo.RegionID,
65 so.UUID, 78 so.UUID,
66 vrm.GetContentType(), 79 m_vrm.GetContentType(),
67 "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;", 80 "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;",
68 "", 81 "",
69 0); 82 0);
70 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
186 SetupScene(true);
187 SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
188 UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
189
190 m_dtm.AddDynamicTextureData(
191 m_scene.RegionInfo.RegionID,
192 so.UUID,
193 m_vrm.GetContentType(),
194 "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;",
195 "",
196 0);
71 197
72 Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); 198 Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
73 } 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
333 Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
334 }
74 } 335 }
75} \ No newline at end of file 336} \ 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 8b2f2f8..673c2d1 100644
--- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
@@ -30,10 +30,12 @@ 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;
33using System.Net; 34using System.Net;
34using Nini.Config; 35using Nini.Config;
35using OpenMetaverse; 36using OpenMetaverse;
36using OpenMetaverse.Imaging; 37using OpenMetaverse.Imaging;
38using OpenSim.Region.CoreModules.Scripting.DynamicTexture;
37using OpenSim.Region.Framework.Interfaces; 39using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
39using log4net; 41using log4net;
@@ -45,9 +47,13 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
45{ 47{
46 public class VectorRenderModule : IRegionModule, IDynamicTextureRender 48 public class VectorRenderModule : IRegionModule, IDynamicTextureRender
47 { 49 {
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
48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 55 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49 56
50 private string m_name = "VectorRenderModule";
51 private Scene m_scene; 57 private Scene m_scene;
52 private IDynamicTextureManager m_textureManager; 58 private IDynamicTextureManager m_textureManager;
53 private Graphics m_graph; 59 private Graphics m_graph;
@@ -61,12 +67,12 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
61 67
62 public string GetContentType() 68 public string GetContentType()
63 { 69 {
64 return ("vector"); 70 return "vector";
65 } 71 }
66 72
67 public string GetName() 73 public string GetName()
68 { 74 {
69 return m_name; 75 return Name;
70 } 76 }
71 77
72 public bool SupportsAsynchronous() 78 public bool SupportsAsynchronous()
@@ -74,14 +80,20 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
74 return true; 80 return true;
75 } 81 }
76 82
77 public byte[] ConvertUrl(string url, string extraParams) 83// public bool AlwaysIdenticalConversion(string bodyData, 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)
78 { 90 {
79 return null; 91 return null;
80 } 92 }
81 93
82 public byte[] ConvertStream(Stream data, string extraParams) 94 public IDynamicTexture ConvertData(string bodyData, string extraParams)
83 { 95 {
84 return null; 96 return Draw(bodyData, extraParams);
85 } 97 }
86 98
87 public bool AsyncConvertUrl(UUID id, string url, string extraParams) 99 public bool AsyncConvertUrl(UUID id, string url, string extraParams)
@@ -91,21 +103,28 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
91 103
92 public bool AsyncConvertData(UUID id, string bodyData, string extraParams) 104 public bool AsyncConvertData(UUID id, string bodyData, string extraParams)
93 { 105 {
94 Draw(bodyData, id, extraParams); 106 // XXX: This isn't actually being done asynchronously!
107 m_textureManager.ReturnData(id, ConvertData(bodyData, extraParams));
108
95 return true; 109 return true;
96 } 110 }
97 111
98 public void GetDrawStringSize(string text, string fontName, int fontSize, 112 public void GetDrawStringSize(string text, string fontName, int fontSize,
99 out double xSize, out double ySize) 113 out double xSize, out double ySize)
100 { 114 {
101 using (Font myFont = new Font(fontName, fontSize)) 115 lock (this)
102 { 116 {
103 SizeF stringSize = new SizeF(); 117 using (Font myFont = new Font(fontName, fontSize))
104 lock (m_graph)
105 { 118 {
106 stringSize = m_graph.MeasureString(text, myFont); 119 SizeF stringSize = new SizeF();
107 xSize = stringSize.Width; 120
108 ySize = stringSize.Height; 121 // XXX: This lock may be unnecessary.
122 lock (m_graph)
123 {
124 stringSize = m_graph.MeasureString(text, myFont);
125 xSize = stringSize.Width;
126 ySize = stringSize.Height;
127 }
109 } 128 }
110 } 129 }
111 } 130 }
@@ -144,6 +163,13 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
144 { 163 {
145 m_textureManager.RegisterRender(GetContentType(), this); 164 m_textureManager.RegisterRender(GetContentType(), this);
146 } 165 }
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;
147 } 173 }
148 174
149 public void Close() 175 public void Close()
@@ -152,7 +178,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
152 178
153 public string Name 179 public string Name
154 { 180 {
155 get { return m_name; } 181 get { return "VectorRenderModule"; }
156 } 182 }
157 183
158 public bool IsSharedModule 184 public bool IsSharedModule
@@ -162,7 +188,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
162 188
163 #endregion 189 #endregion
164 190
165 private void Draw(string data, UUID id, string extraParams) 191 private IDynamicTexture Draw(string data, string extraParams)
166 { 192 {
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 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
168 // we will now support multiple comma seperated params in the form width:256,height:512,alpha:255 194 // we will now support multiple comma seperated params in the form width:256,height:512,alpha:255
@@ -305,40 +331,57 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
305 331
306 Bitmap bitmap = null; 332 Bitmap bitmap = null;
307 Graphics graph = null; 333 Graphics graph = null;
334 bool reuseable = false;
308 335
309 try 336 try
310 { 337 {
311 if (alpha == 256) 338 // XXX: In testing, it appears that if multiple threads dispose of separate GDI+ objects simultaneously,
312 bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb); 339 // the native malloc heap can become corrupted, possibly due to a double free(). This may be due to
313 else 340 // bugs in the underlying libcairo used by mono's libgdiplus.dll on Linux/OSX. These problems were
314 bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); 341 // seen with both libcario 1.10.2-6.1ubuntu3 and 1.8.10-2ubuntu1. They go away if disposal is perfomed
315 342 // under lock.
316 graph = Graphics.FromImage(bitmap); 343 lock (this)
317
318 // this is really just to save people filling the
319 // background color in their scripts, only do when fully opaque
320 if (alpha >= 255)
321 { 344 {
322 using (SolidBrush bgFillBrush = new SolidBrush(bgColor)) 345 if (alpha == 256)
346 bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb);
347 else
348 bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);
349
350 graph = Graphics.FromImage(bitmap);
351
352 // this is really just to save people filling the
353 // background color in their scripts, only do when fully opaque
354 if (alpha >= 255)
323 { 355 {
324 graph.FillRectangle(bgFillBrush, 0, 0, width, height); 356 using (SolidBrush bgFillBrush = new SolidBrush(bgColor))
357 {
358 graph.FillRectangle(bgFillBrush, 0, 0, width, height);
359 }
325 } 360 }
326 } 361
327 362 for (int w = 0; w < bitmap.Width; w++)
328 for (int w = 0; w < bitmap.Width; w++)
329 {
330 if (alpha <= 255)
331 { 363 {
332 for (int h = 0; h < bitmap.Height; h++) 364 if (alpha <= 255)
333 { 365 {
334 bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h))); 366 for (int h = 0; h < bitmap.Height; h++)
367 {
368 bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h)));
369 }
335 } 370 }
336 } 371 }
372
373 GDIDraw(data, graph, altDataDelim, out reuseable);
337 } 374 }
338 375
339 GDIDraw(data, graph, altDataDelim);
340
341 byte[] imageJ2000 = new byte[0]; 376 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;
342 385
343 try 386 try
344 { 387 {
@@ -351,15 +394,24 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
351 e.Message, e.StackTrace); 394 e.Message, e.StackTrace);
352 } 395 }
353 396
354 m_textureManager.ReturnData(id, imageJ2000); 397 return new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture(
398 data, extraParams, imageJ2000, new Size(width, height), reuseable);
355 } 399 }
356 finally 400 finally
357 { 401 {
358 if (graph != null) 402 // XXX: In testing, it appears that if multiple threads dispose of separate GDI+ objects simultaneously,
359 graph.Dispose(); 403 // the native malloc heap can become corrupted, possibly due to a double free(). This may be due to
360 404 // bugs in the underlying libcairo used by mono's libgdiplus.dll on Linux/OSX. These problems were
361 if (bitmap != null) 405 // seen with both libcario 1.10.2-6.1ubuntu3 and 1.8.10-2ubuntu1. They go away if disposal is perfomed
362 bitmap.Dispose(); 406 // under lock.
407 lock (this)
408 {
409 if (graph != null)
410 graph.Dispose();
411
412 if (bitmap != null)
413 bitmap.Dispose();
414 }
363 } 415 }
364 } 416 }
365 417
@@ -418,8 +470,21 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
418 } 470 }
419*/ 471*/
420 472
421 private void GDIDraw(string data, Graphics graph, char dataDelim) 473 /// <summary>
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)
422 { 486 {
487 reuseable = true;
423 Point startPoint = new Point(0, 0); 488 Point startPoint = new Point(0, 0);
424 Point endPoint = new Point(0, 0); 489 Point endPoint = new Point(0, 0);
425 Pen drawPen = null; 490 Pen drawPen = null;
@@ -434,11 +499,9 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
434 myFont = new Font(fontName, fontSize); 499 myFont = new Font(fontName, fontSize);
435 myBrush = new SolidBrush(Color.Black); 500 myBrush = new SolidBrush(Color.Black);
436 501
437 char[] lineDelimiter = {dataDelim};
438 char[] partsDelimiter = {','}; 502 char[] partsDelimiter = {','};
439 string[] lines = data.Split(lineDelimiter);
440 503
441 foreach (string line in lines) 504 foreach (string line in GetLines(data, dataDelim))
442 { 505 {
443 string nextLine = line.Trim(); 506 string nextLine = line.Trim();
444 //replace with switch, or even better, do some proper parsing 507 //replace with switch, or even better, do some proper parsing
@@ -469,6 +532,10 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
469 } 532 }
470 else if (nextLine.StartsWith("Image")) 533 else if (nextLine.StartsWith("Image"))
471 { 534 {
535 // We cannot reuse any generated texture involving fetching an image via HTTP since that image
536 // can change.
537 reuseable = false;
538
472 float x = 0; 539 float x = 0;
473 float y = 0; 540 float y = 0;
474 GetParams(partsDelimiter, ref nextLine, 5, ref x, ref y); 541 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 07bb291..e167e31 100644
--- a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs
@@ -28,6 +28,7 @@
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Text.RegularExpressions;
31using Nini.Config; 32using Nini.Config;
32using OpenMetaverse; 33using OpenMetaverse;
33using OpenSim.Framework; 34using OpenSim.Framework;
@@ -172,12 +173,42 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
172 /// <param name="hostID">UUID of the SceneObjectPart</param> 173 /// <param name="hostID">UUID of the SceneObjectPart</param>
173 /// <param name="channel">channel to listen on</param> 174 /// <param name="channel">channel to listen on</param>
174 /// <param name="name">name to filter on</param> 175 /// <param name="name">name to filter on</param>
175 /// <param name="id">key to filter on (user given, could be totally faked)</param> 176 /// <param name="id">
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>
176 /// <param name="msg">msg to filter on</param> 202 /// <param name="msg">msg to filter on</param>
203 /// <param name="regexBitfield">
204 /// Bitfield indicating which strings should be processed as regex.
205 /// </param>
177 /// <returns>number of the scripts handle</returns> 206 /// <returns>number of the scripts handle</returns>
178 public int Listen(uint localID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg) 207 public int Listen(uint localID, UUID itemID, UUID hostID, int channel,
208 string name, UUID id, string msg, int regexBitfield)
179 { 209 {
180 return m_listenerManager.AddListener(localID, itemID, hostID, channel, name, id, msg); 210 return m_listenerManager.AddListener(localID, itemID, hostID,
211 channel, name, id, msg, regexBitfield);
181 } 212 }
182 213
183 /// <summary> 214 /// <summary>
@@ -326,7 +357,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
326 if (channel == 0) 357 if (channel == 0)
327 { 358 {
328 // Channel 0 goes to viewer ONLY 359 // Channel 0 goes to viewer ONLY
329 m_scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Broadcast, 0, pos, name, id, false, false, target); 360 m_scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Broadcast, 0, pos, name, id, target, false, false);
330 return true; 361 return true;
331 } 362 }
332 363
@@ -470,15 +501,25 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
470 m_curlisteners = 0; 501 m_curlisteners = 0;
471 } 502 }
472 503
473 public int AddListener(uint localID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg) 504 public int AddListener(uint localID, UUID itemID, UUID hostID,
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)
474 { 514 {
475 // do we already have a match on this particular filter event? 515 // do we already have a match on this particular filter event?
476 List<ListenerInfo> coll = GetListeners(itemID, channel, name, id, msg); 516 List<ListenerInfo> coll = GetListeners(itemID, channel, name, id,
517 msg);
477 518
478 if (coll.Count > 0) 519 if (coll.Count > 0)
479 { 520 {
480 // special case, called with same filter settings, return same handle 521 // special case, called with same filter settings, return same
481 // (2008-05-02, tested on 1.21.1 server, still holds) 522 // handle (2008-05-02, tested on 1.21.1 server, still holds)
482 return coll[0].GetHandle(); 523 return coll[0].GetHandle();
483 } 524 }
484 525
@@ -490,7 +531,9 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
490 531
491 if (newHandle > 0) 532 if (newHandle > 0)
492 { 533 {
493 ListenerInfo li = new ListenerInfo(newHandle, localID, itemID, hostID, channel, name, id, msg); 534 ListenerInfo li = new ListenerInfo(newHandle, localID,
535 itemID, hostID, channel, name, id, msg,
536 regexBitfield);
494 537
495 List<ListenerInfo> listeners; 538 List<ListenerInfo> listeners;
496 if (!m_listeners.TryGetValue(channel,out listeners)) 539 if (!m_listeners.TryGetValue(channel,out listeners))
@@ -631,6 +674,22 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
631 return -1; 674 return -1;
632 } 675 }
633 676
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
634 // Theres probably a more clever and efficient way to 693 // Theres probably a more clever and efficient way to
635 // do this, maybe with regex. 694 // do this, maybe with regex.
636 // PM2008: Ha, one could even be smart and define a specialized Enumerator. 695 // PM2008: Ha, one could even be smart and define a specialized Enumerator.
@@ -656,7 +715,10 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
656 { 715 {
657 continue; 716 continue;
658 } 717 }
659 if (li.GetName().Length > 0 && !li.GetName().Equals(name)) 718 if (li.GetName().Length > 0 && (
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 ))
660 { 722 {
661 continue; 723 continue;
662 } 724 }
@@ -664,7 +726,10 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
664 { 726 {
665 continue; 727 continue;
666 } 728 }
667 if (li.GetMessage().Length > 0 && !li.GetMessage().Equals(msg)) 729 if (li.GetMessage().Length > 0 && (
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 ))
668 { 733 {
669 continue; 734 continue;
670 } 735 }
@@ -697,10 +762,13 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
697 { 762 {
698 int idx = 0; 763 int idx = 0;
699 Object[] item = new Object[6]; 764 Object[] item = new Object[6];
765 int dataItemLength = 6;
700 766
701 while (idx < data.Length) 767 while (idx < data.Length)
702 { 768 {
703 Array.Copy(data, idx, item, 0, 6); 769 dataItemLength = (idx + 7 == data.Length || (idx + 7 < data.Length && data[idx + 7] is bool)) ? 7 : 6;
770 item = new Object[dataItemLength];
771 Array.Copy(data, idx, item, 0, dataItemLength);
704 772
705 ListenerInfo info = 773 ListenerInfo info =
706 ListenerInfo.FromData(localID, itemID, hostID, item); 774 ListenerInfo.FromData(localID, itemID, hostID, item);
@@ -712,12 +780,12 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
712 m_listeners[(int)item[2]].Add(info); 780 m_listeners[(int)item[2]].Add(info);
713 } 781 }
714 782
715 idx+=6; 783 idx+=dataItemLength;
716 } 784 }
717 } 785 }
718 } 786 }
719 787
720 public class ListenerInfo: IWorldCommListenerInfo 788 public class ListenerInfo : IWorldCommListenerInfo
721 { 789 {
722 private bool m_active; // Listener is active or not 790 private bool m_active; // Listener is active or not
723 private int m_handle; // Assigned handle of this listener 791 private int m_handle; // Assigned handle of this listener
@@ -731,16 +799,29 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
731 799
732 public ListenerInfo(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, UUID id, string message) 800 public ListenerInfo(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, UUID id, string message)
733 { 801 {
734 Initialise(handle, localID, ItemID, hostID, channel, name, id, message); 802 Initialise(handle, localID, ItemID, hostID, channel, name, id,
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);
735 } 812 }
736 813
737 public ListenerInfo(ListenerInfo li, string name, UUID id, string message) 814 public ListenerInfo(ListenerInfo li, string name, UUID id, string message)
738 { 815 {
739 Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID, li.m_channel, name, id, message); 816 Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID, li.m_channel, name, id, message, 0);
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);
740 } 822 }
741 823
742 private void Initialise(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, 824 private void Initialise(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, UUID id, string message, int regexBitfield)
743 UUID id, string message)
744 { 825 {
745 m_active = true; 826 m_active = true;
746 m_handle = handle; 827 m_handle = handle;
@@ -751,11 +832,12 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
751 m_name = name; 832 m_name = name;
752 m_id = id; 833 m_id = id;
753 m_message = message; 834 m_message = message;
835 RegexBitfield = regexBitfield;
754 } 836 }
755 837
756 public Object[] GetSerializationData() 838 public Object[] GetSerializationData()
757 { 839 {
758 Object[] data = new Object[6]; 840 Object[] data = new Object[7];
759 841
760 data[0] = m_active; 842 data[0] = m_active;
761 data[1] = m_handle; 843 data[1] = m_handle;
@@ -763,16 +845,19 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
763 data[3] = m_name; 845 data[3] = m_name;
764 data[4] = m_id; 846 data[4] = m_id;
765 data[5] = m_message; 847 data[5] = m_message;
848 data[6] = RegexBitfield;
766 849
767 return data; 850 return data;
768 } 851 }
769 852
770 public static ListenerInfo FromData(uint localID, UUID ItemID, UUID hostID, Object[] data) 853 public static ListenerInfo FromData(uint localID, UUID ItemID, UUID hostID, Object[] data)
771 { 854 {
772 ListenerInfo linfo = new ListenerInfo((int)data[1], localID, 855 ListenerInfo linfo = new ListenerInfo((int)data[1], localID, ItemID, hostID, (int)data[2], (string)data[3], (UUID)data[4], (string)data[5]);
773 ItemID, hostID, (int)data[2], (string)data[3], 856 linfo.m_active = (bool)data[0];
774 (UUID)data[4], (string)data[5]); 857 if (data.Length >= 7)
775 linfo.m_active=(bool)data[0]; 858 {
859 linfo.RegexBitfield = (int)data[6];
860 }
776 861
777 return linfo; 862 return linfo;
778 } 863 }
@@ -831,5 +916,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
831 { 916 {
832 return m_id; 917 return m_id;
833 } 918 }
919
920 public int RegexBitfield { get; private set; }
834 } 921 }
835} 922}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs
index 008465f..1e1c7d0 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs
@@ -56,6 +56,8 @@ 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
59 public Type ReplaceableInterface 61 public Type ReplaceableInterface
60 { 62 {
61 get { return null; } 63 get { return null; }
@@ -128,6 +130,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
128 if (m_LocalAssetServiceURI != string.Empty) 130 if (m_LocalAssetServiceURI != string.Empty)
129 m_LocalAssetServiceURI = m_LocalAssetServiceURI.Trim('/'); 131 m_LocalAssetServiceURI = m_LocalAssetServiceURI.Trim('/');
130 132
133 IConfig hgConfig = source.Configs["HGAssetService"];
134 m_AssetPerms = new AssetPermissions(hgConfig); // it's ok if arg is null
135
131 m_Enabled = true; 136 m_Enabled = true;
132 m_log.Info("[HG ASSET CONNECTOR]: HG asset broker enabled"); 137 m_log.Info("[HG ASSET CONNECTOR]: HG asset broker enabled");
133 } 138 }
@@ -206,14 +211,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
206 asset = m_HGService.Get(id); 211 asset = m_HGService.Get(id);
207 if (asset != null) 212 if (asset != null)
208 { 213 {
209 // Now store it locally 214 // Now store it locally, if allowed
210 // For now, let me just do it for textures and scripts 215 if (m_AssetPerms.AllowedImport(asset.Type))
211 if (((AssetType)asset.Type == AssetType.Texture) ||
212 ((AssetType)asset.Type == AssetType.LSLBytecode) ||
213 ((AssetType)asset.Type == AssetType.LSLText))
214 {
215 m_GridService.Store(asset); 216 m_GridService.Store(asset);
216 } 217 else
218 return null;
217 } 219 }
218 } 220 }
219 else 221 else
@@ -328,7 +330,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
328 330
329 string id = string.Empty; 331 string id = string.Empty;
330 if (IsHG(asset.ID)) 332 if (IsHG(asset.ID))
331 id = m_HGService.Store(asset); 333 {
334 if (m_AssetPerms.AllowedExport(asset.Type))
335 id = m_HGService.Store(asset);
336 else
337 return String.Empty;
338 }
332 else 339 else
333 id = m_GridService.Store(asset); 340 id = m_GridService.Store(asset);
334 341
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs
index c78915f..449c1f1 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs
@@ -204,8 +204,11 @@ 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 = m_Cache.Get(id); 208 AssetBase asset = null;
209
210 if (m_Cache != null)
211 asset = m_Cache.Get(id);
209 212
210 if (asset != null) 213 if (asset != null)
211 return asset.Data; 214 return asset.Data;
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs
new file mode 100644
index 0000000..1982473
--- /dev/null
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs
@@ -0,0 +1,136 @@
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 b286d17..4338133 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs
@@ -43,11 +43,15 @@ 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 46 public class GridConnectorsTests : OpenSimTestCase
47 { 47 {
48 LocalGridServicesConnector m_LocalConnector; 48 LocalGridServicesConnector m_LocalConnector;
49 private void SetUp() 49
50 [SetUp]
51 public override void SetUp()
50 { 52 {
53 base.SetUp();
54
51 IConfigSource config = new IniConfigSource(); 55 IConfigSource config = new IniConfigSource();
52 config.AddConfig("Modules"); 56 config.AddConfig("Modules");
53 config.AddConfig("GridService"); 57 config.AddConfig("GridService");
@@ -71,8 +75,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests
71 TestHelpers.InMethod(); 75 TestHelpers.InMethod();
72// log4net.Config.XmlConfigurator.Configure(); 76// log4net.Config.XmlConfigurator.Configure();
73 77
74 SetUp();
75
76 // Create 4 regions 78 // Create 4 regions
77 GridRegion r1 = new GridRegion(); 79 GridRegion r1 = new GridRegion();
78 r1.RegionName = "Test Region 1"; 80 r1.RegionName = "Test Region 1";
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs
index b0edce7..221f815 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs
@@ -65,11 +65,13 @@ 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
70 if (sp.PresenceType != PresenceType.Npc) 68 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);
71 m_GridUserService.SetLastPosition( 72 m_GridUserService.SetLastPosition(
72 sp.UUID.ToString(), UUID.Zero, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat); 73 userid, UUID.Zero, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat);
74 }
73 } 75 }
74 76
75 public void OnNewClient(IClientAPI client) 77 public void OnNewClient(IClientAPI client)
@@ -82,9 +84,16 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser
82 if (client.SceneAgent.IsChildAgent) 84 if (client.SceneAgent.IsChildAgent)
83 return; 85 return;
84 86
85// m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected client logout {0} in {1}", client.AgentId, client.Scene.RegionInfo.RegionName); 87 string userId = client.AgentId.ToString();
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
86 m_GridUserService.LoggedOut( 95 m_GridUserService.LoggedOut(
87 client.AgentId.ToString(), client.SessionId, client.Scene.RegionInfo.RegionID, 96 userId, client.SessionId, client.Scene.RegionInfo.RegionID,
88 client.SceneAgent.AbsolutePosition, client.SceneAgent.Lookat); 97 client.SceneAgent.AbsolutePosition, client.SceneAgent.Lookat);
89 } 98 }
90 } 99 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs
index badb552..04acf67 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs
@@ -44,6 +44,9 @@ 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
47 #region ISharedRegionModule 50 #region ISharedRegionModule
48 51
49 private bool m_Enabled = false; 52 private bool m_Enabled = false;
@@ -128,23 +131,60 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser
128 131
129 public bool LoggedOut(string userID, UUID sessionID, UUID region, Vector3 position, Vector3 lookat) 132 public bool LoggedOut(string userID, UUID sessionID, UUID region, Vector3 position, Vector3 lookat)
130 { 133 {
134 if (m_Infos.Contains(userID))
135 m_Infos.Remove(userID);
136
131 return m_RemoteConnector.LoggedOut(userID, sessionID, region, position, lookat); 137 return m_RemoteConnector.LoggedOut(userID, sessionID, region, position, lookat);
132 } 138 }
133 139
134 140
135 public bool SetHome(string userID, UUID regionID, Vector3 position, Vector3 lookAt) 141 public bool SetHome(string userID, UUID regionID, Vector3 position, Vector3 lookAt)
136 { 142 {
137 return m_RemoteConnector.SetHome(userID, regionID, position, lookAt); 143 if (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;
138 } 157 }
139 158
140 public bool SetLastPosition(string userID, UUID sessionID, UUID regionID, Vector3 position, Vector3 lookAt) 159 public bool SetLastPosition(string userID, UUID sessionID, UUID regionID, Vector3 position, Vector3 lookAt)
141 { 160 {
142 return m_RemoteConnector.SetLastPosition(userID, sessionID, regionID, position, lookAt); 161 if (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;
143 } 175 }
144 176
145 public GridUserInfo GetGridUserInfo(string userID) 177 public GridUserInfo GetGridUserInfo(string userID)
146 { 178 {
147 return m_RemoteConnector.GetGridUserInfo(userID); 179 GridUserInfo info = null;
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;
148 } 188 }
149 189
150 public GridUserInfo[] GetGridUserInfo(string[] userID) 190 public GridUserInfo[] GetGridUserInfo(string[] userID)
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
index 6eb99ea..8ed1833 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
@@ -313,7 +313,11 @@ 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 Util.FireAndForget(delegate { m_scenes[destination.RegionID].IncomingCloseAgent(id); }); 316// m_log.DebugFormat(
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); });
317 return true; 321 return true;
318 } 322 }
319 //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent"); 323 //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 619550c..ade5e76 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
@@ -43,6 +43,7 @@ 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;
46 47
47namespace OpenSim.Region.CoreModules.World.Archiver 48namespace OpenSim.Region.CoreModules.World.Archiver
48{ 49{
@@ -52,7 +53,30 @@ namespace OpenSim.Region.CoreModules.World.Archiver
52 public class ArchiveReadRequest 53 public class ArchiveReadRequest
53 { 54 {
54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 55 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 }
55 78
79
56 /// <summary> 80 /// <summary>
57 /// The maximum major version of OAR that we can read. Minor versions shouldn't need a max number since version 81 /// The maximum major version of OAR that we can read. Minor versions shouldn't need a max number since version
58 /// bumps here should be compatible. 82 /// bumps here should be compatible.
@@ -62,9 +86,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver
62 /// <summary> 86 /// <summary>
63 /// Has the control file been loaded for this archive? 87 /// Has the control file been loaded for this archive?
64 /// </summary> 88 /// </summary>
65 public bool ControlFileLoaded { get; private set; } 89 public bool ControlFileLoaded { get; private set; }
66 90
67 protected Scene m_scene; 91 protected string m_loadPath;
92 protected Scene m_rootScene;
68 protected Stream m_loadStream; 93 protected Stream m_loadStream;
69 protected Guid m_requestId; 94 protected Guid m_requestId;
70 protected string m_errorMessage; 95 protected string m_errorMessage;
@@ -91,16 +116,27 @@ namespace OpenSim.Region.CoreModules.World.Archiver
91 { 116 {
92 if (m_UserMan == null) 117 if (m_UserMan == null)
93 { 118 {
94 m_UserMan = m_scene.RequestModuleInterface<IUserManagement>(); 119 m_UserMan = m_rootScene.RequestModuleInterface<IUserManagement>();
95 } 120 }
96 return m_UserMan; 121 return m_UserMan;
97 } 122 }
98 } 123 }
99 124
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
100 public ArchiveReadRequest(Scene scene, string loadPath, bool merge, bool skipAssets, Guid requestId) 135 public ArchiveReadRequest(Scene scene, string loadPath, bool merge, bool skipAssets, Guid requestId)
101 { 136 {
102 m_scene = scene; 137 m_rootScene = scene;
103 138
139 m_loadPath = loadPath;
104 try 140 try
105 { 141 {
106 m_loadStream = new GZipStream(ArchiveHelpers.GetStream(loadPath), CompressionMode.Decompress); 142 m_loadStream = new GZipStream(ArchiveHelpers.GetStream(loadPath), CompressionMode.Decompress);
@@ -120,11 +156,15 @@ namespace OpenSim.Region.CoreModules.World.Archiver
120 156
121 // Zero can never be a valid user id 157 // Zero can never be a valid user id
122 m_validUserUuids[UUID.Zero] = false; 158 m_validUserUuids[UUID.Zero] = false;
159
160 m_groupsModule = m_rootScene.RequestModuleInterface<IGroupsModule>();
161 m_assetService = m_rootScene.AssetService;
123 } 162 }
124 163
125 public ArchiveReadRequest(Scene scene, Stream loadStream, bool merge, bool skipAssets, Guid requestId) 164 public ArchiveReadRequest(Scene scene, Stream loadStream, bool merge, bool skipAssets, Guid requestId)
126 { 165 {
127 m_scene = scene; 166 m_rootScene = scene;
167 m_loadPath = null;
128 m_loadStream = loadStream; 168 m_loadStream = loadStream;
129 m_merge = merge; 169 m_merge = merge;
130 m_skipAssets = skipAssets; 170 m_skipAssets = skipAssets;
@@ -132,6 +172,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
132 172
133 // Zero can never be a valid user id 173 // Zero can never be a valid user id
134 m_validUserUuids[UUID.Zero] = false; 174 m_validUserUuids[UUID.Zero] = false;
175
176 m_groupsModule = m_rootScene.RequestModuleInterface<IGroupsModule>();
177 m_assetService = m_rootScene.AssetService;
135 } 178 }
136 179
137 /// <summary> 180 /// <summary>
@@ -139,25 +182,25 @@ namespace OpenSim.Region.CoreModules.World.Archiver
139 /// </summary> 182 /// </summary>
140 public void DearchiveRegion() 183 public void DearchiveRegion()
141 { 184 {
142 // The same code can handle dearchiving 0.1 and 0.2 OpenSim Archive versions
143 DearchiveRegion0DotStar();
144 }
145
146 private void DearchiveRegion0DotStar()
147 {
148 int successfulAssetRestores = 0; 185 int successfulAssetRestores = 0;
149 int failedAssetRestores = 0; 186 int failedAssetRestores = 0;
150 List<string> serialisedSceneObjects = new List<string>();
151 List<string> serialisedParcels = new List<string>();
152 string filePath = "NONE";
153 187
154 TarArchiveReader archive = new TarArchiveReader(m_loadStream); 188 DearchiveScenesInfo dearchivedScenes;
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;
155 byte[] data; 196 byte[] data;
156 TarArchiveReader.TarEntryType entryType; 197 TarArchiveReader.TarEntryType entryType;
157 198
158 try 199 try
159 { 200 {
160 while ((data = archive.ReadEntry(out filePath, out entryType)) != null) 201 FindAndLoadControlFile(out archive, out dearchivedScenes);
202
203 while ((data = archive.ReadEntry(out fullPath, out entryType)) != null)
161 { 204 {
162 //m_log.DebugFormat( 205 //m_log.DebugFormat(
163 // "[ARCHIVER]: Successfully read {0} ({1} bytes)", filePath, data.Length); 206 // "[ARCHIVER]: Successfully read {0} ({1} bytes)", filePath, data.Length);
@@ -165,9 +208,30 @@ namespace OpenSim.Region.CoreModules.World.Archiver
165 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType) 208 if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType)
166 continue; 209 continue;
167 210
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
168 if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH)) 232 if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH))
169 { 233 {
170 serialisedSceneObjects.Add(Encoding.UTF8.GetString(data)); 234 sceneContext.SerialisedSceneObjects.Add(Encoding.UTF8.GetString(data));
171 } 235 }
172 else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH) && !m_skipAssets) 236 else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH) && !m_skipAssets)
173 { 237 {
@@ -181,19 +245,19 @@ namespace OpenSim.Region.CoreModules.World.Archiver
181 } 245 }
182 else if (!m_merge && filePath.StartsWith(ArchiveConstants.TERRAINS_PATH)) 246 else if (!m_merge && filePath.StartsWith(ArchiveConstants.TERRAINS_PATH))
183 { 247 {
184 LoadTerrain(filePath, data); 248 LoadTerrain(scene, filePath, data);
185 } 249 }
186 else if (!m_merge && filePath.StartsWith(ArchiveConstants.SETTINGS_PATH)) 250 else if (!m_merge && filePath.StartsWith(ArchiveConstants.SETTINGS_PATH))
187 { 251 {
188 LoadRegionSettings(filePath, data); 252 LoadRegionSettings(scene, filePath, data, dearchivedScenes);
189 } 253 }
190 else if (!m_merge && filePath.StartsWith(ArchiveConstants.LANDDATA_PATH)) 254 else if (!m_merge && filePath.StartsWith(ArchiveConstants.LANDDATA_PATH))
191 { 255 {
192 serialisedParcels.Add(Encoding.UTF8.GetString(data)); 256 sceneContext.SerialisedParcels.Add(Encoding.UTF8.GetString(data));
193 } 257 }
194 else if (filePath == ArchiveConstants.CONTROL_FILE_PATH) 258 else if (filePath == ArchiveConstants.CONTROL_FILE_PATH)
195 { 259 {
196 LoadControlFile(filePath, data); 260 // Ignore, because we already read the control file
197 } 261 }
198 } 262 }
199 263
@@ -201,15 +265,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver
201 } 265 }
202 catch (Exception e) 266 catch (Exception e)
203 { 267 {
204 m_log.ErrorFormat( 268 m_log.Error(
205 "[ARCHIVER]: Aborting load with error in archive file {0}. {1}", filePath, e); 269 String.Format("[ARCHIVER]: Aborting load with error in archive file {0} ", fullPath), e);
206 m_errorMessage += e.ToString(); 270 m_errorMessage += e.ToString();
207 m_scene.EventManager.TriggerOarFileLoaded(m_requestId, m_errorMessage); 271 m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, new List<UUID>(), m_errorMessage);
208 return; 272 return;
209 } 273 }
210 finally 274 finally
211 { 275 {
212 archive.Close(); 276 if (archive != null)
277 archive.Close();
213 } 278 }
214 279
215 if (!m_skipAssets) 280 if (!m_skipAssets)
@@ -223,32 +288,143 @@ namespace OpenSim.Region.CoreModules.World.Archiver
223 } 288 }
224 } 289 }
225 290
226 if (!m_merge) 291 foreach (DearchiveContext sceneContext in sceneContexts.Values)
227 { 292 {
228 m_log.Info("[ARCHIVER]: Clearing all existing scene objects"); 293 m_log.InfoFormat("[ARCHIVER]: Loading region {0}", sceneContext.Scene.RegionInfo.RegionName);
229 m_scene.DeleteAllSceneObjects(); 294
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 }
230 } 319 }
231 320
232 LoadParcels(serialisedParcels); 321 // Start the scripts. We delayed this because we want the OAR to finish loading ASAP, so
233 LoadObjects(serialisedSceneObjects); 322 // that users can enter the scene. If we allow the scripts to start in the loop above
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 });
234 340
235 m_log.InfoFormat("[ARCHIVER]: Successfully loaded archive"); 341 m_log.InfoFormat("[ARCHIVER]: Successfully loaded archive");
236 342
237 m_scene.EventManager.TriggerOarFileLoaded(m_requestId, m_errorMessage); 343 m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, dearchivedScenes.GetLoadedScenes(), 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");
238 } 415 }
239 416
240 /// <summary> 417 /// <summary>
241 /// Load serialized scene objects. 418 /// Load serialized scene objects.
242 /// </summary> 419 /// </summary>
243 /// <param name="serialisedSceneObjects"></param> 420 protected void LoadObjects(Scene scene, List<string> serialisedSceneObjects, List<SceneObjectGroup> sceneObjects)
244 protected void LoadObjects(List<string> serialisedSceneObjects)
245 { 421 {
246 // Reload serialized prims 422 // Reload serialized prims
247 m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count); 423 m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count);
248 424
249 UUID oldTelehubUUID = m_scene.RegionInfo.RegionSettings.TelehubObject; 425 UUID oldTelehubUUID = scene.RegionInfo.RegionSettings.TelehubObject;
250 426
251 IRegionSerialiserModule serialiser = m_scene.RequestModuleInterface<IRegionSerialiserModule>(); 427 IRegionSerialiserModule serialiser = scene.RequestModuleInterface<IRegionSerialiserModule>();
252 int sceneObjectsLoadedCount = 0; 428 int sceneObjectsLoadedCount = 0;
253 429
254 foreach (string serialisedSceneObject in serialisedSceneObjects) 430 foreach (string serialisedSceneObject in serialisedSceneObjects)
@@ -269,7 +445,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
269 445
270 SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject); 446 SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject);
271 447
272 bool isTelehub = (sceneObject.UUID == oldTelehubUUID); 448 bool isTelehub = (sceneObject.UUID == oldTelehubUUID) && (oldTelehubUUID != UUID.Zero);
273 449
274 // For now, give all incoming scene objects new uuids. This will allow scenes to be cloned 450 // For now, give all incoming scene objects new uuids. This will allow scenes to be cloned
275 // on the same region server and multiple examples a single object archive to be imported 451 // on the same region server and multiple examples a single object archive to be imported
@@ -279,8 +455,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
279 if (isTelehub) 455 if (isTelehub)
280 { 456 {
281 // Change the Telehub Object to the new UUID 457 // Change the Telehub Object to the new UUID
282 m_scene.RegionInfo.RegionSettings.TelehubObject = sceneObject.UUID; 458 scene.RegionInfo.RegionSettings.TelehubObject = sceneObject.UUID;
283 m_scene.RegionInfo.RegionSettings.Save(); 459 scene.RegionInfo.RegionSettings.Save();
284 oldTelehubUUID = UUID.Zero; 460 oldTelehubUUID = UUID.Zero;
285 } 461 }
286 462
@@ -290,17 +466,20 @@ namespace OpenSim.Region.CoreModules.World.Archiver
290 { 466 {
291 if (part.CreatorData == null || part.CreatorData == string.Empty) 467 if (part.CreatorData == null || part.CreatorData == string.Empty)
292 { 468 {
293 if (!ResolveUserUuid(part.CreatorID)) 469 if (!ResolveUserUuid(scene, part.CreatorID))
294 part.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner; 470 part.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner;
295 } 471 }
296 if (UserManager != null) 472 if (UserManager != null)
297 UserManager.AddUser(part.CreatorID, part.CreatorData); 473 UserManager.AddUser(part.CreatorID, part.CreatorData);
298 474
299 if (!ResolveUserUuid(part.OwnerID)) 475 if (!ResolveUserUuid(scene, part.OwnerID))
300 part.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; 476 part.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner;
477
478 if (!ResolveUserUuid(scene, part.LastOwnerID))
479 part.LastOwnerID = scene.RegionInfo.EstateSettings.EstateOwner;
301 480
302 if (!ResolveUserUuid(part.LastOwnerID)) 481 if (!ResolveGroupUuid(part.GroupID))
303 part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; 482 part.GroupID = UUID.Zero;
304 483
305 // And zap any troublesome sit target information 484 // And zap any troublesome sit target information
306// part.SitTargetOrientation = new Quaternion(0, 0, 0, 1); 485// part.SitTargetOrientation = new Quaternion(0, 0, 0, 1);
@@ -311,14 +490,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver
311 // being no copy/no mod for everyone 490 // being no copy/no mod for everyone
312 lock (part.TaskInventory) 491 lock (part.TaskInventory)
313 { 492 {
314 if (!ResolveUserUuid(part.CreatorID)) 493 if (!ResolveUserUuid(scene, part.CreatorID))
315 part.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner; 494 part.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner;
316 495
317 if (!ResolveUserUuid(part.OwnerID)) 496 if (!ResolveUserUuid(scene, part.OwnerID))
318 part.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; 497 part.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner;
319 498
320 if (!ResolveUserUuid(part.LastOwnerID)) 499 if (!ResolveUserUuid(scene, part.LastOwnerID))
321 part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; 500 part.LastOwnerID = scene.RegionInfo.EstateSettings.EstateOwner;
322 501
323 // And zap any troublesome sit target information 502 // And zap any troublesome sit target information
324 part.SitTargetOrientation = new Quaternion(0, 0, 0, 1); 503 part.SitTargetOrientation = new Quaternion(0, 0, 0, 1);
@@ -331,26 +510,31 @@ namespace OpenSim.Region.CoreModules.World.Archiver
331 TaskInventoryDictionary inv = part.TaskInventory; 510 TaskInventoryDictionary inv = part.TaskInventory;
332 foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv) 511 foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv)
333 { 512 {
334 if (!ResolveUserUuid(kvp.Value.OwnerID)) 513 if (!ResolveUserUuid(scene, kvp.Value.OwnerID))
335 { 514 {
336 kvp.Value.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; 515 kvp.Value.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner;
337 } 516 }
517
338 if (kvp.Value.CreatorData == null || kvp.Value.CreatorData == string.Empty) 518 if (kvp.Value.CreatorData == null || kvp.Value.CreatorData == string.Empty)
339 { 519 {
340 if (!ResolveUserUuid(kvp.Value.CreatorID)) 520 if (!ResolveUserUuid(scene, kvp.Value.CreatorID))
341 kvp.Value.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner; 521 kvp.Value.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner;
342 } 522 }
523
343 if (UserManager != null) 524 if (UserManager != null)
344 UserManager.AddUser(kvp.Value.CreatorID, kvp.Value.CreatorData); 525 UserManager.AddUser(kvp.Value.CreatorID, kvp.Value.CreatorData);
526
527 if (!ResolveGroupUuid(kvp.Value.GroupID))
528 kvp.Value.GroupID = UUID.Zero;
345 } 529 }
346 part.TaskInventory.LockItemsForRead(false); 530 part.TaskInventory.LockItemsForRead(false);
347 } 531 }
348 } 532 }
349 533
350 if (m_scene.AddRestoredSceneObject(sceneObject, true, false)) 534 if (scene.AddRestoredSceneObject(sceneObject, true, false))
351 { 535 {
352 sceneObjectsLoadedCount++; 536 sceneObjectsLoadedCount++;
353 sceneObject.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, 0); 537 sceneObject.CreateScriptInstances(0, false, scene.DefaultScriptEngine, 0);
354 sceneObject.ResumeScripts(); 538 sceneObject.ResumeScripts();
355 } 539 }
356 } 540 }
@@ -365,16 +549,17 @@ namespace OpenSim.Region.CoreModules.World.Archiver
365 if (oldTelehubUUID != UUID.Zero) 549 if (oldTelehubUUID != UUID.Zero)
366 { 550 {
367 m_log.WarnFormat("Telehub object not found: {0}", oldTelehubUUID); 551 m_log.WarnFormat("Telehub object not found: {0}", oldTelehubUUID);
368 m_scene.RegionInfo.RegionSettings.TelehubObject = UUID.Zero; 552 scene.RegionInfo.RegionSettings.TelehubObject = UUID.Zero;
369 m_scene.RegionInfo.RegionSettings.ClearSpawnPoints(); 553 scene.RegionInfo.RegionSettings.ClearSpawnPoints();
370 } 554 }
371 } 555 }
372 556
373 /// <summary> 557 /// <summary>
374 /// Load serialized parcels. 558 /// Load serialized parcels.
375 /// </summary> 559 /// </summary>
560 /// <param name="scene"></param>
376 /// <param name="serialisedParcels"></param> 561 /// <param name="serialisedParcels"></param>
377 protected void LoadParcels(List<string> serialisedParcels) 562 protected void LoadParcels(Scene scene, List<string> serialisedParcels)
378 { 563 {
379 // Reload serialized parcels 564 // Reload serialized parcels
380 m_log.InfoFormat("[ARCHIVER]: Loading {0} parcels. Please wait.", serialisedParcels.Count); 565 m_log.InfoFormat("[ARCHIVER]: Loading {0} parcels. Please wait.", serialisedParcels.Count);
@@ -382,9 +567,27 @@ namespace OpenSim.Region.CoreModules.World.Archiver
382 foreach (string serialisedParcel in serialisedParcels) 567 foreach (string serialisedParcel in serialisedParcels)
383 { 568 {
384 LandData parcel = LandDataSerializer.Deserialize(serialisedParcel); 569 LandData parcel = LandDataSerializer.Deserialize(serialisedParcel);
385 if (!ResolveUserUuid(parcel.OwnerID))
386 parcel.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
387 570
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
388// m_log.DebugFormat( 591// m_log.DebugFormat(
389// "[ARCHIVER]: Adding parcel {0}, local id {1}, area {2}", 592// "[ARCHIVER]: Adding parcel {0}, local id {1}, area {2}",
390// parcel.Name, parcel.LocalID, parcel.Area); 593// parcel.Name, parcel.LocalID, parcel.Area);
@@ -395,23 +598,24 @@ namespace OpenSim.Region.CoreModules.World.Archiver
395 if (!m_merge) 598 if (!m_merge)
396 { 599 {
397 bool setupDefaultParcel = (landData.Count == 0); 600 bool setupDefaultParcel = (landData.Count == 0);
398 m_scene.LandChannel.Clear(setupDefaultParcel); 601 scene.LandChannel.Clear(setupDefaultParcel);
399 } 602 }
400 603
401 m_scene.EventManager.TriggerIncomingLandDataFromStorage(landData); 604 scene.EventManager.TriggerIncomingLandDataFromStorage(landData);
402 m_log.InfoFormat("[ARCHIVER]: Restored {0} parcels.", landData.Count); 605 m_log.InfoFormat("[ARCHIVER]: Restored {0} parcels.", landData.Count);
403 } 606 }
404 607
405 /// <summary> 608 /// <summary>
406 /// Look up the given user id to check whether it's one that is valid for this grid. 609 /// Look up the given user id to check whether it's one that is valid for this grid.
407 /// </summary> 610 /// </summary>
611 /// <param name="scene"></param>
408 /// <param name="uuid"></param> 612 /// <param name="uuid"></param>
409 /// <returns></returns> 613 /// <returns></returns>
410 private bool ResolveUserUuid(UUID uuid) 614 private bool ResolveUserUuid(Scene scene, UUID uuid)
411 { 615 {
412 if (!m_validUserUuids.ContainsKey(uuid)) 616 if (!m_validUserUuids.ContainsKey(uuid))
413 { 617 {
414 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, uuid); 618 UserAccount account = scene.UserAccountService.GetUserAccount(scene.RegionInfo.ScopeID, uuid);
415 m_validUserUuids.Add(uuid, account != null); 619 m_validUserUuids.Add(uuid, account != null);
416 } 620 }
417 621
@@ -419,6 +623,30 @@ namespace OpenSim.Region.CoreModules.World.Archiver
419 } 623 }
420 624
421 /// <summary> 625 /// <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
422 /// Load an asset 650 /// Load an asset
423 /// </summary> 651 /// </summary>
424 /// <param name="assetFilename"></param> 652 /// <param name="assetFilename"></param>
@@ -442,7 +670,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
442 string extension = filename.Substring(i); 670 string extension = filename.Substring(i);
443 string uuid = filename.Remove(filename.Length - extension.Length); 671 string uuid = filename.Remove(filename.Length - extension.Length);
444 672
445 if (m_scene.AssetService.GetMetadata(uuid) != null) 673 if (m_assetService.GetMetadata(uuid) != null)
446 { 674 {
447 // m_log.DebugFormat("[ARCHIVER]: found existing asset {0}",uuid); 675 // m_log.DebugFormat("[ARCHIVER]: found existing asset {0}",uuid);
448 return true; 676 return true;
@@ -462,7 +690,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
462 690
463 // We're relying on the asset service to do the sensible thing and not store the asset if it already 691 // We're relying on the asset service to do the sensible thing and not store the asset if it already
464 // exists. 692 // exists.
465 m_scene.AssetService.Store(asset); 693 m_assetService.Store(asset);
466 694
467 /** 695 /**
468 * Create layers on decode for image assets. This is likely to significantly increase the time to load archives so 696 * Create layers on decode for image assets. This is likely to significantly increase the time to load archives so
@@ -490,12 +718,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver
490 /// <summary> 718 /// <summary>
491 /// Load region settings data 719 /// Load region settings data
492 /// </summary> 720 /// </summary>
721 /// <param name="scene"></param>
493 /// <param name="settingsPath"></param> 722 /// <param name="settingsPath"></param>
494 /// <param name="data"></param> 723 /// <param name="data"></param>
724 /// <param name="dearchivedScenes"></param>
495 /// <returns> 725 /// <returns>
496 /// true if settings were loaded successfully, false otherwise 726 /// true if settings were loaded successfully, false otherwise
497 /// </returns> 727 /// </returns>
498 private bool LoadRegionSettings(string settingsPath, byte[] data) 728 private bool LoadRegionSettings(Scene scene, string settingsPath, byte[] data, DearchiveScenesInfo dearchivedScenes)
499 { 729 {
500 RegionSettings loadedRegionSettings; 730 RegionSettings loadedRegionSettings;
501 731
@@ -511,7 +741,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
511 return false; 741 return false;
512 } 742 }
513 743
514 RegionSettings currentRegionSettings = m_scene.RegionInfo.RegionSettings; 744 RegionSettings currentRegionSettings = scene.RegionInfo.RegionSettings;
515 745
516 currentRegionSettings.AgentLimit = loadedRegionSettings.AgentLimit; 746 currentRegionSettings.AgentLimit = loadedRegionSettings.AgentLimit;
517 currentRegionSettings.AllowDamage = loadedRegionSettings.AllowDamage; 747 currentRegionSettings.AllowDamage = loadedRegionSettings.AllowDamage;
@@ -548,12 +778,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver
548 foreach (SpawnPoint sp in loadedRegionSettings.SpawnPoints()) 778 foreach (SpawnPoint sp in loadedRegionSettings.SpawnPoints())
549 currentRegionSettings.AddSpawnPoint(sp); 779 currentRegionSettings.AddSpawnPoint(sp);
550 780
781 currentRegionSettings.LoadedCreationDateTime = dearchivedScenes.LoadedCreationDateTime;
782 currentRegionSettings.LoadedCreationID = dearchivedScenes.GetOriginalRegionID(scene.RegionInfo.RegionID).ToString();
783
551 currentRegionSettings.Save(); 784 currentRegionSettings.Save();
552 785
553 m_scene.TriggerEstateSunUpdate(); 786 scene.TriggerEstateSunUpdate();
554 787
555 IEstateModule estateModule = m_scene.RequestModuleInterface<IEstateModule>(); 788 IEstateModule estateModule = scene.RequestModuleInterface<IEstateModule>();
556
557 if (estateModule != null) 789 if (estateModule != null)
558 estateModule.sendRegionHandshakeToAll(); 790 estateModule.sendRegionHandshakeToAll();
559 791
@@ -563,14 +795,15 @@ namespace OpenSim.Region.CoreModules.World.Archiver
563 /// <summary> 795 /// <summary>
564 /// Load terrain data 796 /// Load terrain data
565 /// </summary> 797 /// </summary>
798 /// <param name="scene"></param>
566 /// <param name="terrainPath"></param> 799 /// <param name="terrainPath"></param>
567 /// <param name="data"></param> 800 /// <param name="data"></param>
568 /// <returns> 801 /// <returns>
569 /// true if terrain was resolved successfully, false otherwise. 802 /// true if terrain was resolved successfully, false otherwise.
570 /// </returns> 803 /// </returns>
571 private bool LoadTerrain(string terrainPath, byte[] data) 804 private bool LoadTerrain(Scene scene, string terrainPath, byte[] data)
572 { 805 {
573 ITerrainModule terrainModule = m_scene.RequestModuleInterface<ITerrainModule>(); 806 ITerrainModule terrainModule = scene.RequestModuleInterface<ITerrainModule>();
574 807
575 MemoryStream ms = new MemoryStream(data); 808 MemoryStream ms = new MemoryStream(data);
576 terrainModule.LoadFromStream(terrainPath, ms); 809 terrainModule.LoadFromStream(terrainPath, ms);
@@ -586,17 +819,18 @@ namespace OpenSim.Region.CoreModules.World.Archiver
586 /// </summary> 819 /// </summary>
587 /// <param name="path"></param> 820 /// <param name="path"></param>
588 /// <param name="data"></param> 821 /// <param name="data"></param>
589 public void LoadControlFile(string path, byte[] data) 822 /// <param name="dearchivedScenes"></param>
823 public DearchiveScenesInfo LoadControlFile(string path, byte[] data, DearchiveScenesInfo dearchivedScenes)
590 { 824 {
591 XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable()); 825 XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable());
592 XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None); 826 XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None);
593 XmlTextReader xtr = new XmlTextReader(Encoding.ASCII.GetString(data), XmlNodeType.Document, context); 827 XmlTextReader xtr = new XmlTextReader(Encoding.ASCII.GetString(data), XmlNodeType.Document, context);
594 828
595 RegionSettings currentRegionSettings = m_scene.RegionInfo.RegionSettings; 829 // Loaded metadata will be empty if no information exists in the archive
830 dearchivedScenes.LoadedCreationDateTime = 0;
831 dearchivedScenes.DefaultOriginalID = "";
596 832
597 // Loaded metadata will empty if no information exists in the archive 833 bool multiRegion = false;
598 currentRegionSettings.LoadedCreationDateTime = 0;
599 currentRegionSettings.LoadedCreationID = "";
600 834
601 while (xtr.Read()) 835 while (xtr.Read())
602 { 836 {
@@ -622,18 +856,44 @@ namespace OpenSim.Region.CoreModules.World.Archiver
622 { 856 {
623 int value; 857 int value;
624 if (Int32.TryParse(xtr.ReadElementContentAsString(), out value)) 858 if (Int32.TryParse(xtr.ReadElementContentAsString(), out value))
625 currentRegionSettings.LoadedCreationDateTime = value; 859 dearchivedScenes.LoadedCreationDateTime = value;
626 } 860 }
627 else if (xtr.Name.ToString() == "id") 861 else if (xtr.Name.ToString() == "row")
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")
628 { 878 {
629 currentRegionSettings.LoadedCreationID = xtr.ReadElementContentAsString(); 879 dearchivedScenes.SetRegionDirectory(xtr.ReadElementContentAsString());
630 } 880 }
631 } 881 }
632 } 882 }
633 883
634 currentRegionSettings.Save(); 884 dearchivedScenes.MultiRegionFormat = multiRegion;
635 885 if (!multiRegion)
886 {
887 // Add the single scene
888 dearchivedScenes.StartRow();
889 dearchivedScenes.StartRegion();
890 dearchivedScenes.SetRegionOriginalID(dearchivedScenes.DefaultOriginalID);
891 dearchivedScenes.SetRegionDirectory("");
892 }
893
636 ControlFileLoaded = true; 894 ControlFileLoaded = true;
895
896 return dearchivedScenes;
637 } 897 }
638 } 898 }
639} \ No newline at end of file 899}
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs
new file mode 100644
index 0000000..d8dace2
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs
@@ -0,0 +1,176 @@
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
new file mode 100644
index 0000000..d751b1c
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
@@ -0,0 +1,634 @@
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
deleted file mode 100644
index 0780d86..0000000
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs
+++ /dev/null
@@ -1,153 +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.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
deleted file mode 100644
index 4edaaca..0000000
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs
+++ /dev/null
@@ -1,438 +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;
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 bf3b124..abf3713 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs
@@ -32,6 +32,8 @@ 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;
35using OpenSim.Region.Framework.Interfaces; 37using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes; 38using OpenSim.Region.Framework.Scenes;
37 39
@@ -117,7 +119,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
117// 119//
118// foreach (string param in mainParams) 120// foreach (string param in mainParams)
119// m_log.DebugFormat("GOT PARAM [{0}]", param); 121// m_log.DebugFormat("GOT PARAM [{0}]", param);
120 122
121 if (mainParams.Count > 2) 123 if (mainParams.Count > 2)
122 { 124 {
123 DearchiveRegion(mainParams[2], mergeOar, skipAssets, Guid.Empty); 125 DearchiveRegion(mainParams[2], mergeOar, skipAssets, Guid.Empty);
@@ -146,17 +148,22 @@ namespace OpenSim.Region.CoreModules.World.Archiver
146 ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; }); 148 ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; });
147 ops.Add("publish", v => options["wipe-owners"] = v != null); 149 ops.Add("publish", v => options["wipe-owners"] = v != null);
148 ops.Add("perm=", delegate(string v) { options["checkPermissions"] = v; }); 150 ops.Add("perm=", delegate(string v) { options["checkPermissions"] = v; });
151 ops.Add("all", delegate(string v) { options["all"] = v != null; });
149 152
150 List<string> mainParams = ops.Parse(cmdparams); 153 List<string> mainParams = ops.Parse(cmdparams);
151 154
155 string path;
152 if (mainParams.Count > 2) 156 if (mainParams.Count > 2)
153 { 157 path = mainParams[2];
154 ArchiveRegion(mainParams[2], options);
155 }
156 else 158 else
157 { 159 path = DEFAULT_OAR_BACKUP_FILENAME;
158 ArchiveRegion(DEFAULT_OAR_BACKUP_FILENAME, options); 160
159 } 161 // Not doing this right now as this causes some problems with auto-backup systems. Maybe a force flag is
162 // needed
163// if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, path))
164// return;
165
166 ArchiveRegion(path, options);
160 } 167 }
161 168
162 public void ArchiveRegion(string savePath, Dictionary<string, object> options) 169 public void ArchiveRegion(string savePath, Dictionary<string, object> options)
@@ -169,7 +176,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
169 m_log.InfoFormat( 176 m_log.InfoFormat(
170 "[ARCHIVER]: Writing archive for region {0} to {1}", Scene.RegionInfo.RegionName, savePath); 177 "[ARCHIVER]: Writing archive for region {0} to {1}", Scene.RegionInfo.RegionName, savePath);
171 178
172 new ArchiveWriteRequestPreparation(this, savePath, requestId).ArchiveRegion(options); 179 new ArchiveWriteRequest(Scene, savePath, requestId).ArchiveRegion(options);
173 } 180 }
174 181
175 public void ArchiveRegion(Stream saveStream) 182 public void ArchiveRegion(Stream saveStream)
@@ -184,7 +191,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
184 191
185 public void ArchiveRegion(Stream saveStream, Guid requestId, Dictionary<string, object> options) 192 public void ArchiveRegion(Stream saveStream, Guid requestId, Dictionary<string, object> options)
186 { 193 {
187 new ArchiveWriteRequestPreparation(this, saveStream, requestId).ArchiveRegion(options); 194 new ArchiveWriteRequest(Scene, saveStream, requestId).ArchiveRegion(options);
188 } 195 }
189 196
190 public void DearchiveRegion(string loadPath) 197 public void DearchiveRegion(string loadPath)
diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
index 89e9593..e2f8833 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs
@@ -46,6 +46,12 @@ 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
49 enum RequestState 55 enum RequestState
50 { 56 {
51 Initial, 57 Initial,
@@ -123,6 +129,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver
123 m_options = options; 129 m_options = options;
124 m_repliesRequired = uuids.Count; 130 m_repliesRequired = uuids.Count;
125 131
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
126 m_requestCallbackTimer = new System.Timers.Timer(TIMEOUT); 136 m_requestCallbackTimer = new System.Timers.Timer(TIMEOUT);
127 m_requestCallbackTimer.AutoReset = false; 137 m_requestCallbackTimer.AutoReset = false;
128 m_requestCallbackTimer.Elapsed += new ElapsedEventHandler(OnRequestCallbackTimeout); 138 m_requestCallbackTimer.Elapsed += new ElapsedEventHandler(OnRequestCallbackTimeout);
diff --git a/OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs b/OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs
new file mode 100644
index 0000000..3dcc020
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs
@@ -0,0 +1,232 @@
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 5deaf52..82f49b0 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
@@ -47,32 +47,41 @@ 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;
50 51
51namespace OpenSim.Region.CoreModules.World.Archiver.Tests 52namespace OpenSim.Region.CoreModules.World.Archiver.Tests
52{ 53{
53 [TestFixture] 54 [TestFixture]
54 public class ArchiverTests 55 public class ArchiverTests : OpenSimTestCase
55 { 56 {
56 private Guid m_lastRequestId; 57 private Guid m_lastRequestId;
57 private string m_lastErrorMessage; 58 private string m_lastErrorMessage;
58 59
60 protected SceneHelpers m_sceneHelpers;
59 protected TestScene m_scene; 61 protected TestScene m_scene;
60 protected ArchiverModule m_archiverModule; 62 protected ArchiverModule m_archiverModule;
63 protected SerialiserModule m_serialiserModule;
61 64
62 protected TaskInventoryItem m_soundItem; 65 protected TaskInventoryItem m_soundItem;
63 66
64 [SetUp] 67 [SetUp]
65 public void SetUp() 68 public override void SetUp()
66 { 69 {
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
67 m_archiverModule = new ArchiverModule(); 75 m_archiverModule = new ArchiverModule();
68 SerialiserModule serialiserModule = new SerialiserModule(); 76 m_serialiserModule = new SerialiserModule();
69 TerrainModule terrainModule = new TerrainModule(); 77 TerrainModule terrainModule = new TerrainModule();
70 78
71 m_scene = new SceneHelpers().SetupScene(); 79 m_sceneHelpers = new SceneHelpers();
72 SceneHelpers.SetupSceneModules(m_scene, m_archiverModule, serialiserModule, terrainModule); 80 m_scene = m_sceneHelpers.SetupScene();
81 SceneHelpers.SetupSceneModules(m_scene, m_archiverModule, m_serialiserModule, terrainModule);
73 } 82 }
74 83
75 private void LoadCompleted(Guid requestId, string errorMessage) 84 private void LoadCompleted(Guid requestId, List<UUID> loadedScenes, string errorMessage)
76 { 85 {
77 lock (this) 86 lock (this)
78 { 87 {
@@ -128,26 +137,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
128 TestHelpers.InMethod(); 137 TestHelpers.InMethod();
129// log4net.Config.XmlConfigurator.Configure(); 138// log4net.Config.XmlConfigurator.Configure();
130 139
131 SceneObjectPart part1 = CreateSceneObjectPart1(); 140 SceneObjectGroup sog1;
132 SceneObjectGroup sog1 = new SceneObjectGroup(part1); 141 SceneObjectGroup sog2;
133 m_scene.AddNewSceneObject(sog1, false); 142 UUID ncAssetUuid;
134 143 CreateTestObjects(m_scene, out sog1, out sog2, out ncAssetUuid);
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);
151 144
152 MemoryStream archiveWriteStream = new MemoryStream(); 145 MemoryStream archiveWriteStream = new MemoryStream();
153 m_scene.EventManager.OnOarFileSaved += SaveCompleted; 146 m_scene.EventManager.OnOarFileSaved += SaveCompleted;
@@ -186,7 +179,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
186 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); 179 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
187 180
188 ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty); 181 ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty);
189 arr.LoadControlFile(filePath, data); 182 arr.LoadControlFile(filePath, data, new DearchiveScenesInfo());
190 183
191 Assert.That(arr.ControlFileLoaded, Is.True); 184 Assert.That(arr.ControlFileLoaded, Is.True);
192 185
@@ -211,6 +204,30 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
211 // TODO: Test presence of more files and contents of files. 204 // TODO: Test presence of more files and contents of files.
212 } 205 }
213 206
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
214 /// <summary> 231 /// <summary>
215 /// Test saving an OpenSim Region Archive with the no assets option 232 /// Test saving an OpenSim Region Archive with the no assets option
216 /// </summary> 233 /// </summary>
@@ -270,7 +287,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
270 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); 287 Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH));
271 288
272 ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty); 289 ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty);
273 arr.LoadControlFile(filePath, data); 290 arr.LoadControlFile(filePath, data, new DearchiveScenesInfo());
274 291
275 Assert.That(arr.ControlFileLoaded, Is.True); 292 Assert.That(arr.ControlFileLoaded, Is.True);
276 293
@@ -307,7 +324,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
307 324
308 tar.WriteFile( 325 tar.WriteFile(
309 ArchiveConstants.CONTROL_FILE_PATH, 326 ArchiveConstants.CONTROL_FILE_PATH,
310 new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary<string, Object>())); 327 new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup()));
311 328
312 SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ownerId, "obj1-", 0x11); 329 SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ownerId, "obj1-", 0x11);
313 SceneObjectPart sop2 330 SceneObjectPart sop2
@@ -362,11 +379,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
362 // Also check that direct entries which will also have a file entry containing that directory doesn't 379 // Also check that direct entries which will also have a file entry containing that directory doesn't
363 // upset load 380 // upset load
364 tar.WriteDir(ArchiveConstants.TERRAINS_PATH); 381 tar.WriteDir(ArchiveConstants.TERRAINS_PATH);
365 382
366 tar.WriteFile( 383 tar.WriteFile(
367 ArchiveConstants.CONTROL_FILE_PATH, 384 ArchiveConstants.CONTROL_FILE_PATH,
368 new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary<string, Object>())); 385 new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup()));
369
370 SceneObjectPart part1 = CreateSceneObjectPart1(); 386 SceneObjectPart part1 = CreateSceneObjectPart1();
371 387
372 part1.SitTargetOrientation = new Quaternion(0.2f, 0.3f, 0.4f, 0.5f); 388 part1.SitTargetOrientation = new Quaternion(0.2f, 0.3f, 0.4f, 0.5f);
@@ -389,31 +405,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
389 Assert.That(soundDataResourceName, Is.Not.Null); 405 Assert.That(soundDataResourceName, Is.Not.Null);
390 406
391 byte[] soundData; 407 byte[] soundData;
392 Console.WriteLine("Loading " + soundDataResourceName); 408 UUID soundUuid;
393 using (Stream resource = assembly.GetManifestResourceStream(soundDataResourceName)) 409 CreateSoundAsset(tar, assembly, soundDataResourceName, out soundData, out soundUuid);
394 { 410
395 using (BinaryReader br = new BinaryReader(resource)) 411 TaskInventoryItem item1
396 { 412 = new TaskInventoryItem { AssetID = soundUuid, ItemID = soundItemUuid, Name = soundItemName };
397 // FIXME: Use the inspector instead 413 part1.Inventory.AddInventoryItem(item1, true);
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
417 m_scene.AddNewSceneObject(object1, false); 414 m_scene.AddNewSceneObject(object1, false);
418 415
419 string object1FileName = string.Format( 416 string object1FileName = string.Format(
@@ -435,6 +432,34 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
435 432
436 Assert.That(m_lastErrorMessage, Is.Null); 433 Assert.That(m_lastErrorMessage, Is.Null);
437 434
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 {
438 SceneObjectPart object1PartLoaded = m_scene.GetSceneObjectPart(part1.Name); 463 SceneObjectPart object1PartLoaded = m_scene.GetSceneObjectPart(part1.Name);
439 464
440 Assert.That(object1PartLoaded, Is.Not.Null, "object1 was not loaded"); 465 Assert.That(object1PartLoaded, Is.Not.Null, "object1 was not loaded");
@@ -454,9 +479,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
454 Assert.That(loadedSoundAsset.Data, Is.EqualTo(soundData), "saved and loaded sound data do not match"); 479 Assert.That(loadedSoundAsset.Data, Is.EqualTo(soundData), "saved and loaded sound data do not match");
455 480
456 Assert.Greater(m_scene.LandChannel.AllParcels().Count, 0, "incorrect number of parcels"); 481 Assert.Greater(m_scene.LandChannel.AllParcels().Count, 0, "incorrect number of parcels");
457
458 // Temporary
459 Console.WriteLine("Successfully completed {0}", MethodBase.GetCurrentMethod());
460 } 482 }
461 483
462 /// <summary> 484 /// <summary>
@@ -516,7 +538,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
516 SerialiserModule serialiserModule = new SerialiserModule(); 538 SerialiserModule serialiserModule = new SerialiserModule();
517 TerrainModule terrainModule = new TerrainModule(); 539 TerrainModule terrainModule = new TerrainModule();
518 540
519 TestScene scene2 = new SceneHelpers().SetupScene(); 541 m_sceneHelpers = new SceneHelpers();
542 TestScene scene2 = m_sceneHelpers.SetupScene();
520 SceneHelpers.SetupSceneModules(scene2, archiverModule, serialiserModule, terrainModule); 543 SceneHelpers.SetupSceneModules(scene2, archiverModule, serialiserModule, terrainModule);
521 544
522 // Make sure there's a valid owner for the owner we saved (this should have been wiped if the code is 545 // Make sure there's a valid owner for the owner we saved (this should have been wiped if the code is
@@ -554,7 +577,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
554 tar.WriteDir(ArchiveConstants.TERRAINS_PATH); 577 tar.WriteDir(ArchiveConstants.TERRAINS_PATH);
555 tar.WriteFile( 578 tar.WriteFile(
556 ArchiveConstants.CONTROL_FILE_PATH, 579 ArchiveConstants.CONTROL_FILE_PATH,
557 new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary<string, Object>())); 580 new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup()));
558 581
559 RegionSettings rs = new RegionSettings(); 582 RegionSettings rs = new RegionSettings();
560 rs.AgentLimit = 17; 583 rs.AgentLimit = 17;
@@ -664,7 +687,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
664 SerialiserModule serialiserModule = new SerialiserModule(); 687 SerialiserModule serialiserModule = new SerialiserModule();
665 TerrainModule terrainModule = new TerrainModule(); 688 TerrainModule terrainModule = new TerrainModule();
666 689
667 Scene scene = new SceneHelpers().SetupScene(); 690 Scene scene = m_sceneHelpers.SetupScene();
668 SceneHelpers.SetupSceneModules(scene, archiverModule, serialiserModule, terrainModule); 691 SceneHelpers.SetupSceneModules(scene, archiverModule, serialiserModule, terrainModule);
669 692
670 m_scene.AddNewSceneObject(new SceneObjectGroup(part2), false); 693 m_scene.AddNewSceneObject(new SceneObjectGroup(part2), false);
@@ -700,5 +723,258 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
700 Assert.That(object2PartMerged.GroupPosition, Is.EqualTo(part2.GroupPosition), "object2 group position not equal after merge"); 723 Assert.That(object2PartMerged.GroupPosition, Is.EqualTo(part2.GroupPosition), "object2 group position not equal after merge");
701 } 724 }
702 } 725 }
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
703 } 979 }
704} 980}
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
index fdef9d8..5fd1bce 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
@@ -40,6 +40,7 @@ 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;
43 44
44namespace OpenSim.Region.CoreModules.World.Estate 45namespace OpenSim.Region.CoreModules.World.Estate
45{ 46{
diff --git a/OpenSim/Region/CoreModules/World/Land/DwellModule.cs b/OpenSim/Region/CoreModules/World/Land/DwellModule.cs
new file mode 100644
index 0000000..d1f05a7
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Land/DwellModule.cs
@@ -0,0 +1,110 @@
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 aae6603..b5e2bc3 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
@@ -927,6 +927,7 @@ 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;
930 931
931 newLand.SetLandBitmap(newLand.GetSquareLandBitmap(start_x, start_y, end_x, end_y)); 932 newLand.SetLandBitmap(newLand.GetSquareLandBitmap(start_x, start_y, end_x, end_y));
932 933
diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
index 4f06737..d5b2adb 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
@@ -33,6 +33,7 @@ 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;
36 37
37namespace OpenSim.Region.CoreModules.World.Land 38namespace OpenSim.Region.CoreModules.World.Land
38{ 39{
diff --git a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
index 102b4d7..cbb3abe 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 09f6758..ab8f143 100644
--- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
@@ -27,9 +27,12 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.IO;
31using System.Linq;
30using System.Reflection; 32using System.Reflection;
31using System.Text; 33using System.Text;
32using System.Text.RegularExpressions; 34using System.Text.RegularExpressions;
35using System.Xml;
33using log4net; 36using log4net;
34using Mono.Addins; 37using Mono.Addins;
35using NDesk.Options; 38using NDesk.Options;
@@ -40,6 +43,7 @@ using OpenSim.Framework.Console;
40using OpenSim.Framework.Monitoring; 43using OpenSim.Framework.Monitoring;
41using OpenSim.Region.Framework.Interfaces; 44using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes; 45using OpenSim.Region.Framework.Scenes;
46using OpenSim.Region.Framework.Scenes.Serialization;
43 47
44namespace OpenSim.Region.CoreModules.World.Objects.Commands 48namespace OpenSim.Region.CoreModules.World.Objects.Commands
45{ 49{
@@ -83,52 +87,85 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
83 m_console.Commands.AddCommand( 87 m_console.Commands.AddCommand(
84 "Objects", false, "delete object owner", 88 "Objects", false, "delete object owner",
85 "delete object owner <UUID>", 89 "delete object owner <UUID>",
86 "Delete a scene object by owner", HandleDeleteObject); 90 "Delete scene objects by owner",
91 "Command will ask for confirmation before proceeding.",
92 HandleDeleteObject);
87 93
88 m_console.Commands.AddCommand( 94 m_console.Commands.AddCommand(
89 "Objects", false, "delete object creator", 95 "Objects", false, "delete object creator",
90 "delete object creator <UUID>", 96 "delete object creator <UUID>",
91 "Delete a scene object by creator", HandleDeleteObject); 97 "Delete scene objects by creator",
98 "Command will ask for confirmation before proceeding.",
99 HandleDeleteObject);
92 100
93 m_console.Commands.AddCommand( 101 m_console.Commands.AddCommand(
94 "Objects", false, "delete object uuid", 102 "Objects", false, "delete object id",
95 "delete object uuid <UUID>", 103 "delete object id <UUID-or-localID>",
96 "Delete a scene object by uuid", HandleDeleteObject); 104 "Delete a scene object by uuid or localID",
105 HandleDeleteObject);
97 106
98 m_console.Commands.AddCommand( 107 m_console.Commands.AddCommand(
99 "Objects", false, "delete object name", 108 "Objects", false, "delete object name",
100 "delete object name [--regex] <name>", 109 "delete object name [--regex] <name>",
101 "Delete a scene object by name.", 110 "Delete a scene object by name.",
102 "If --regex is specified then the name is treatead as a regular expression", 111 "Command will ask for confirmation before proceeding.\n"
112 + "If --regex is specified then the name is treatead as a regular expression",
103 HandleDeleteObject); 113 HandleDeleteObject);
104 114
105 m_console.Commands.AddCommand( 115 m_console.Commands.AddCommand(
106 "Objects", false, "delete object outside", 116 "Objects", false, "delete object outside",
107 "delete object outside", 117 "delete object outside",
108 "Delete all scene objects outside region boundaries", HandleDeleteObject); 118 "Delete all scene objects outside region boundaries",
119 "Command will ask for confirmation before proceeding.",
120 HandleDeleteObject);
109 121
110 m_console.Commands.AddCommand( 122 m_console.Commands.AddCommand(
111 "Objects", 123 "Objects",
112 false, 124 false,
113 "show object uuid", 125 "delete object pos",
114 "show object uuid <UUID>", 126 "delete object pos <start-coord> to <end-coord>",
115 "Show details of a scene object with the given UUID", HandleShowObjectByUuid); 127 "Delete scene objects within the given area.",
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);
116 140
117 m_console.Commands.AddCommand( 141 m_console.Commands.AddCommand(
118 "Objects", 142 "Objects",
119 false, 143 false,
120 "show object name", 144 "show object name",
121 "show object name [--regex] <name>", 145 "show object name [--full] [--regex] <name>",
122 "Show details of scene objects with the given name.", 146 "Show details of scene objects with the given name.",
123 "If --regex is specified then the name is treatead as a regular expression", 147 "The --full option will print out information on all the parts of the object.\n"
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.",
124 HandleShowObjectByName); 150 HandleShowObjectByName);
125 151
126 m_console.Commands.AddCommand( 152 m_console.Commands.AddCommand(
127 "Objects", 153 "Objects",
128 false, 154 false,
129 "show part uuid", 155 "show object pos",
130 "show part uuid <UUID>", 156 "show object pos [--full] <start-coord> to <end-coord>",
131 "Show details of a scene object parts with the given UUID", HandleShowPartByUuid); 157 "Show details of scene objects within the given area.",
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);
132 169
133 m_console.Commands.AddCommand( 170 m_console.Commands.AddCommand(
134 "Objects", 171 "Objects",
@@ -136,8 +173,28 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
136 "show part name", 173 "show part name",
137 "show part name [--regex] <name>", 174 "show part name [--regex] <name>",
138 "Show details of scene object parts with the given name.", 175 "Show details of scene object parts with the given name.",
139 "If --regex is specified then the name is treatead as a regular expression", 176 "If --regex is specified then the name is treated as a regular expression",
140 HandleShowPartByName); 177 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);
141 } 198 }
142 199
143 public void RemoveRegion(Scene scene) 200 public void RemoveRegion(Scene scene)
@@ -150,25 +207,75 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
150// m_log.DebugFormat("[OBJECTS COMMANDS MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName); 207// m_log.DebugFormat("[OBJECTS COMMANDS MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName);
151 } 208 }
152 209
153 private void HandleShowObjectByUuid(string module, string[] cmd) 210 /// <summary>
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)
154 { 253 {
155 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) 254 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
156 return; 255 return;
157 256
158 if (cmd.Length < 4) 257 bool showFull = false;
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)
159 { 263 {
160 m_console.OutputFormat("Usage: show object uuid <uuid>"); 264 m_console.OutputFormat("Usage: show object uuid <uuid>");
161 return; 265 return;
162 } 266 }
163 267
164 UUID objectUuid; 268 UUID uuid;
165 if (!UUID.TryParse(cmd[3], out objectUuid)) 269 uint localId;
166 { 270 if (!ConsoleUtil.TryParseConsoleId(m_console, mainParams[3], out uuid, out localId))
167 m_console.OutputFormat("{0} is not a valid uuid", cmd[3]);
168 return; 271 return;
169 }
170 272
171 SceneObjectGroup so = m_scene.GetSceneObjectGroup(objectUuid); 273 SceneObjectGroup so;
274
275 if (localId != ConsoleUtil.LocalIdNotFound)
276 so = m_scene.GetSceneObjectGroup(localId);
277 else
278 so = m_scene.GetSceneObjectGroup(uuid);
172 279
173 if (so == null) 280 if (so == null)
174 { 281 {
@@ -177,7 +284,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
177 } 284 }
178 285
179 StringBuilder sb = new StringBuilder(); 286 StringBuilder sb = new StringBuilder();
180 AddSceneObjectReport(sb, so); 287 AddSceneObjectReport(sb, so, showFull);
181 288
182 m_console.OutputFormat(sb.ToString()); 289 m_console.OutputFormat(sb.ToString());
183 } 290 }
@@ -187,70 +294,91 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
187 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) 294 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
188 return; 295 return;
189 296
297 bool showFull = false;
190 bool useRegex = false; 298 bool useRegex = false;
191 OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null ); 299 OptionSet options = new OptionSet();
300 options.Add("full", v => showFull = v != null );
301 options.Add("regex", v => useRegex = v != null );
192 302
193 List<string> mainParams = options.Parse(cmdparams); 303 List<string> mainParams = options.Parse(cmdparams);
194 304
195 if (mainParams.Count < 4) 305 if (mainParams.Count < 4)
196 { 306 {
197 m_console.OutputFormat("Usage: show object name [--regex] <name>"); 307 m_console.OutputFormat("Usage: show object name [--full] [--regex] <name>");
198 return; 308 return;
199 } 309 }
200 310
201 string name = mainParams[3]; 311 string name = mainParams[3];
202 312
203 List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>(); 313 Predicate<SceneObjectGroup> searchPredicate;
204 Action<SceneObjectGroup> searchAction;
205 314
206 if (useRegex) 315 if (useRegex)
207 { 316 {
208 Regex nameRegex = new Regex(name); 317 Regex nameRegex = new Regex(name);
209 searchAction = so => { if (nameRegex.IsMatch(so.Name)) { sceneObjects.Add(so); }}; 318 searchPredicate = so => nameRegex.IsMatch(so.Name);
210 } 319 }
211 else 320 else
212 { 321 {
213 searchAction = so => { if (so.Name == name) { sceneObjects.Add(so); }}; 322 searchPredicate = so => so.Name == name;
214 } 323 }
215 324
216 m_scene.ForEachSOG(searchAction); 325 OutputSogsToConsole(searchPredicate, showFull);
326 }
217 327
218 if (sceneObjects.Count == 0) 328 private void HandleShowObjectByPos(string module, string[] cmdparams)
219 { 329 {
220 m_console.OutputFormat("No objects with name {0} found in {1}", name, m_scene.RegionInfo.RegionName); 330 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
221 return; 331 return;
222 }
223 332
224 StringBuilder sb = new StringBuilder(); 333 bool showFull = false;
334 OptionSet options = new OptionSet().Add("full", v => showFull = v != null );
225 335
226 foreach (SceneObjectGroup so in sceneObjects) 336 List<string> mainParams = options.Parse(cmdparams);
337
338 if (mainParams.Count < 5)
227 { 339 {
228 AddSceneObjectReport(sb, so); 340 m_console.OutputFormat("Usage: show object pos [--full] <start-coord> to <end-coord>");
229 sb.Append("\n"); 341 return;
230 } 342 }
231 343
232 m_console.OutputFormat(sb.ToString()); 344 Vector3 startVector, endVector;
345
346 if (!TryParseVectorRange(cmdparams.Skip(3).Take(3), out startVector, out endVector))
347 return;
348
349 Predicate<SceneObjectGroup> searchPredicate
350 = so => Util.IsInsideBox(so.AbsolutePosition, startVector, endVector);
351
352 OutputSogsToConsole(searchPredicate, showFull);
233 } 353 }
234 354
235 private void HandleShowPartByUuid(string module, string[] cmd) 355 private void HandleShowPartById(string module, string[] cmdparams)
236 { 356 {
237 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) 357 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
238 return; 358 return;
239 359
240 if (cmd.Length < 4) 360// bool showFull = false;
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)
241 { 367 {
242 m_console.OutputFormat("Usage: show part uuid <uuid>"); 368 m_console.OutputFormat("Usage: show part id [--full] <UUID-or-localID>");
243 return; 369 return;
244 } 370 }
245 371
246 UUID objectUuid; 372 UUID objectUuid;
247 if (!UUID.TryParse(cmd[3], out objectUuid)) 373 uint localId;
248 { 374 if (!ConsoleUtil.TryParseConsoleId(m_console, mainParams[3], out objectUuid, out localId))
249 m_console.OutputFormat("{0} is not a valid uuid", cmd[3]);
250 return; 375 return;
251 }
252 376
253 SceneObjectPart sop = m_scene.GetSceneObjectPart(objectUuid); 377 SceneObjectPart sop;
378 if (localId == ConsoleUtil.LocalIdNotFound)
379 sop = m_scene.GetSceneObjectPart(objectUuid);
380 else
381 sop = m_scene.GetSceneObjectPart(localId);
254 382
255 if (sop == null) 383 if (sop == null)
256 { 384 {
@@ -259,84 +387,239 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
259 } 387 }
260 388
261 StringBuilder sb = new StringBuilder(); 389 StringBuilder sb = new StringBuilder();
262 AddScenePartReport(sb, sop); 390 AddScenePartReport(sb, sop, true);
263 391
264 m_console.OutputFormat(sb.ToString()); 392 m_console.OutputFormat(sb.ToString());
265 } 393 }
266 394
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
267 private void HandleShowPartByName(string module, string[] cmdparams) 433 private void HandleShowPartByName(string module, string[] cmdparams)
268 { 434 {
269 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) 435 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
270 return; 436 return;
271 437
438// bool showFull = false;
272 bool useRegex = false; 439 bool useRegex = false;
273 OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null ); 440 OptionSet options = new OptionSet();
441// options.Add("full", v => showFull = v != null );
442 options.Add("regex", v => useRegex = v != null );
274 443
275 List<string> mainParams = options.Parse(cmdparams); 444 List<string> mainParams = options.Parse(cmdparams);
276 445
277 if (mainParams.Count < 4) 446 if (mainParams.Count < 4)
278 { 447 {
279 m_console.OutputFormat("Usage: show part name [--regex] <name>"); 448 m_console.OutputFormat("Usage: show part name [--full] [--regex] <name>");
280 return; 449 return;
281 } 450 }
282 451
283 string name = mainParams[3]; 452 string name = mainParams[3];
284 453
285 List<SceneObjectPart> parts = new List<SceneObjectPart>(); 454 Predicate<SceneObjectPart> searchPredicate;
286
287 Action<SceneObjectGroup> searchAction;
288 455
289 if (useRegex) 456 if (useRegex)
290 { 457 {
291 Regex nameRegex = new Regex(name); 458 Regex nameRegex = new Regex(name);
292 searchAction = so => so.ForEachPart(sop => { if (nameRegex.IsMatch(sop.Name)) { parts.Add(sop); } }); 459 searchPredicate = sop => nameRegex.IsMatch(sop.Name);
293 } 460 }
294 else 461 else
295 { 462 {
296 searchAction = so => so.ForEachPart(sop => { if (sop.Name == name) { parts.Add(sop); } }); 463 searchPredicate = sop => sop.Name == name;
297 } 464 }
298 465
299 m_scene.ForEachSOG(searchAction); 466 OutputSopsToConsole(searchPredicate, true);
467 }
468
469 private void HandleDumpObjectById(string module, string[] cmdparams)
470 {
471 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
472 return;
300 473
301 if (parts.Count == 0) 474 if (cmdparams.Length < 4)
302 { 475 {
303 m_console.OutputFormat("No parts with name {0} found in {1}", name, m_scene.RegionInfo.RegionName); 476 m_console.OutputFormat("Usage: dump object id <UUID-or-localID>");
304 return; 477 return;
305 } 478 }
306 479
307 StringBuilder sb = new StringBuilder(); 480 UUID objectUuid;
481 uint localId;
482 if (!ConsoleUtil.TryParseConsoleId(m_console, cmdparams[3], out objectUuid, out localId))
483 return;
308 484
309 foreach (SceneObjectPart part in parts) 485 SceneObjectGroup so;
486 if (localId == ConsoleUtil.LocalIdNotFound)
487 so = m_scene.GetSceneObjectGroup(objectUuid);
488 else
489 so = m_scene.GetSceneObjectGroup(localId);
490
491 if (so == null)
310 { 492 {
311 AddScenePartReport(sb, part); 493// m_console.OutputFormat("No part found with uuid {0}", objectUuid);
312 sb.Append("\n"); 494 return;
313 } 495 }
314 496
315 m_console.OutputFormat(sb.ToString()); 497 // In case we found it via local ID.
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);
316 } 512 }
317 513
318 private StringBuilder AddSceneObjectReport(StringBuilder sb, SceneObjectGroup so) 514 /// <summary>
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)
319 { 525 {
320 sb.AppendFormat("Name: {0}\n", so.Name); 526 if (showFull)
321 sb.AppendFormat("Description: {0}\n", so.Description); 527 {
322 sb.AppendFormat("Location: {0} @ {1}\n", so.AbsolutePosition, so.Scene.RegionInfo.RegionName); 528 foreach (SceneObjectPart sop in so.Parts)
323 sb.AppendFormat("Parts: {0}\n", so.PrimCount); 529 {
324 sb.AppendFormat("Flags: {0}\n", so.RootPart.Flags); 530 AddScenePartReport(sb, sop, false);
531 sb.Append("\n");
532 }
533 }
534 else
535 {
536 AddSummarySceneObjectReport(sb, so);
537 }
325 538
326 return sb; 539 return sb;
327 } 540 }
328 541
329 private StringBuilder AddScenePartReport(StringBuilder sb, SceneObjectPart sop) 542 private StringBuilder AddSummarySceneObjectReport(StringBuilder sb, SceneObjectGroup so)
330 { 543 {
331 sb.AppendFormat("Name: {0}\n", sop.Name); 544 ConsoleDisplayList cdl = new ConsoleDisplayList();
332 sb.AppendFormat("Description: {0}\n", sop.Description); 545 cdl.AddRow("Name", so.Name);
333 sb.AppendFormat("Location: {0} @ {1}\n", sop.AbsolutePosition, sop.ParentGroup.Scene.RegionInfo.RegionName); 546 cdl.AddRow("Descrition", so.Description);
334 sb.AppendFormat("Parent: {0}", 547 cdl.AddRow("Local ID", so.LocalId);
335 sop.IsRoot ? "Is Root\n" : string.Format("{0} {1}\n", sop.ParentGroup.Name, sop.ParentGroup.UUID)); 548 cdl.AddRow("UUID", so.UUID);
336 sb.AppendFormat("Link number: {0}\n", sop.LinkNum); 549 cdl.AddRow("Location", string.Format("{0} @ {1}", so.AbsolutePosition, so.Scene.Name));
337 sb.AppendFormat("Flags: {0}\n", sop.Flags); 550 cdl.AddRow("Parts", so.PrimCount);
551 cdl.AddRow("Flags", so.RootPart.Flags);
552
553 return sb.Append(cdl.ToString());
554 }
338 555
339 return sb; 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 {
599 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
600 cdt.Indent = 2;
601
602 cdt.AddColumn("Name", 50);
603 cdt.AddColumn("Type", 12);
604 cdt.AddColumn("Running", 7);
605 cdt.AddColumn("Item UUID", 36);
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
622 return sb.Append(cdt.ToString());
340 } 623 }
341 624
342 private void HandleDeleteObject(string module, string[] cmd) 625 private void HandleDeleteObject(string module, string[] cmd)
@@ -398,19 +681,24 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
398 681
399 break; 682 break;
400 683
401 case "uuid": 684 case "id":
402 if (!UUID.TryParse(o, out match)) 685 UUID uuid;
686 uint localId;
687 if (!ConsoleUtil.TryParseConsoleId(m_console, o, out uuid, out localId))
403 return; 688 return;
404 689
405 requireConfirmation = false; 690 requireConfirmation = false;
406 deletes = new List<SceneObjectGroup>(); 691 deletes = new List<SceneObjectGroup>();
407 692
408 m_scene.ForEachSOG(delegate (SceneObjectGroup g) 693 SceneObjectGroup so;
409 { 694 if (localId == ConsoleUtil.LocalIdNotFound)
410 if (g.UUID == match && !g.IsAttachment) 695 so = m_scene.GetSceneObjectGroup(uuid);
411 deletes.Add(g); 696 else
412 }); 697 so = m_scene.GetSceneObjectGroup(localId);
413 698
699 if (!so.IsAttachment)
700 deletes.Add(so);
701
414 // if (deletes.Count == 0) 702 // if (deletes.Count == 0)
415 // m_console.OutputFormat("No objects were found with uuid {0}", match); 703 // m_console.OutputFormat("No objects were found with uuid {0}", match);
416 704
@@ -450,6 +738,10 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
450 738
451 break; 739 break;
452 740
741 case "pos":
742 deletes = GetDeleteCandidatesByPos(module, cmd);
743 break;
744
453 default: 745 default:
454 m_console.OutputFormat("Unrecognized mode {0}", mode); 746 m_console.OutputFormat("Unrecognized mode {0}", mode);
455 return; 747 return;
@@ -464,7 +756,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
464 string.Format( 756 string.Format(
465 "Are you sure that you want to delete {0} objects from {1}", 757 "Are you sure that you want to delete {0} objects from {1}",
466 deletes.Count, m_scene.RegionInfo.RegionName), 758 deletes.Count, m_scene.RegionInfo.RegionName),
467 "n"); 759 "y/N");
468 760
469 if (response.ToLower() != "y") 761 if (response.ToLower() != "y")
470 { 762 {
@@ -486,9 +778,6 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
486 778
487 private List<SceneObjectGroup> GetDeleteCandidatesByName(string module, string[] cmdparams) 779 private List<SceneObjectGroup> GetDeleteCandidatesByName(string module, string[] cmdparams)
488 { 780 {
489 if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene))
490 return null;
491
492 bool useRegex = false; 781 bool useRegex = false;
493 OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null ); 782 OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null );
494 783
@@ -522,5 +811,52 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands
522 811
523 return sceneObjects; 812 return sceneObjects;
524 } 813 }
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 }
525 } 861 }
526} \ No newline at end of file 862} \ 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 14c1a39..513a8f5 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,56 +24,110 @@
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
28using System; 27using System;
28using System.IO;
29using System.Collections.Generic;
30using System.Reflection;
31
29using Nini.Config; 32using Nini.Config;
30using OpenMetaverse; 33using OpenMetaverse;
34using log4net;
35using Mono.Addins;
36
31using OpenSim.Framework; 37using OpenSim.Framework;
32using OpenSim.Region.Framework.Interfaces; 38using OpenSim.Region.Framework.Interfaces;
33using OpenSim.Region.Framework.Scenes; 39using OpenSim.Region.Framework.Scenes;
34using System.Reflection;
35using log4net;
36 40
37namespace OpenSim.Region.CoreModules.World.Sound 41namespace OpenSim.Region.CoreModules.World.Sound
38{ 42{
39 public class SoundModule : IRegionModule, ISoundModule 43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SoundModule")]
44 public class SoundModule : INonSharedRegionModule, ISoundModule
40 { 45 {
41// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 private static readonly ILog m_log = LogManager.GetLogger(
42 47 MethodBase.GetCurrentMethod().DeclaringType);
43 protected Scene m_scene; 48
44 49 private Scene m_scene;
45 public void Initialise(Scene scene, IConfigSource source) 50
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)
46 { 78 {
79 m_scene.EventManager.OnClientLogin -= OnNewClient;
80 }
81
82 public void RegionLoaded(Scene scene)
83 {
84 if (!Enabled)
85 return;
86
47 m_scene = scene; 87 m_scene = scene;
48 88 m_scene.EventManager.OnClientLogin += OnNewClient;
49 m_scene.EventManager.OnNewClient += OnNewClient; 89
50
51 m_scene.RegisterModuleInterface<ISoundModule>(this); 90 m_scene.RegisterModuleInterface<ISoundModule>(this);
52 } 91 }
53 92
54 public void PostInitialise() {} 93 public void Close() { }
55 public void Close() {} 94
95 public Type ReplaceableInterface
96 {
97 get { return typeof(ISoundModule); }
98 }
99
56 public string Name { get { return "Sound Module"; } } 100 public string Name { get { return "Sound Module"; } }
57 public bool IsSharedModule { get { return false; } } 101
58 102 #endregion
103
104 #region Event Handlers
105
59 private void OnNewClient(IClientAPI client) 106 private void OnNewClient(IClientAPI client)
60 { 107 {
61 client.OnSoundTrigger += TriggerSound; 108 client.OnSoundTrigger += TriggerSound;
62 } 109 }
63 110
111 #endregion
112
113 #region ISoundModule
114
64 public virtual void PlayAttachedSound( 115 public virtual void PlayAttachedSound(
65 UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags, float radius) 116 UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags, float radius)
66 { 117 {
67 SceneObjectPart part = m_scene.GetSceneObjectPart(objectID); 118 SceneObjectPart part;
68 if (part == null) 119 if (!m_scene.TryGetSceneObjectPart(objectID, out part))
69 return; 120 return;
70 121
71 SceneObjectGroup grp = part.ParentGroup; 122 SceneObjectGroup grp = part.ParentGroup;
72 123
124 if (radius == 0)
125 radius = MaxDistance;
126
73 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) 127 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
74 { 128 {
75 double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); 129 double dis = Util.GetDistanceTo(sp.AbsolutePosition, position);
76 if (dis > 100.0) // Max audio distance 130 if (dis > MaxDistance) // Max audio distance
77 return; 131 return;
78 132
79 if (grp.IsAttachment) 133 if (grp.IsAttachment)
@@ -86,23 +140,21 @@ namespace OpenSim.Region.CoreModules.World.Sound
86 } 140 }
87 141
88 // Scale by distance 142 // Scale by distance
89 if (radius == 0) 143 double thisSpGain = gain * ((radius - dis) / radius);
90 gain = (float)((double)gain * ((100.0 - dis) / 100.0));
91 else
92 gain = (float)((double)gain * ((radius - dis) / radius));
93 144
94 sp.ControllingClient.SendPlayAttachedSound(soundID, objectID, ownerID, (float)gain, flags); 145 sp.ControllingClient.SendPlayAttachedSound(soundID, objectID,
146 ownerID, (float)thisSpGain, flags);
95 }); 147 });
96 } 148 }
97 149
98 public virtual void TriggerSound( 150 public virtual void TriggerSound(
99 UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius) 151 UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius)
100 { 152 {
101 SceneObjectPart part = m_scene.GetSceneObjectPart(objectID); 153 SceneObjectPart part;
102 if (part == null) 154 if (!m_scene.TryGetSceneObjectPart(objectID, out part))
103 { 155 {
104 ScenePresence sp; 156 ScenePresence sp;
105 if (!m_scene.TryGetScenePresence(objectID, out sp)) 157 if (!m_scene.TryGetScenePresence(ownerID, out sp))
106 return; 158 return;
107 } 159 }
108 else 160 else
@@ -116,24 +168,207 @@ namespace OpenSim.Region.CoreModules.World.Sound
116 } 168 }
117 } 169 }
118 170
171 if (radius == 0)
172 radius = MaxDistance;
173
119 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) 174 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
120 { 175 {
121 double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); 176 double dis = Util.GetDistanceTo(sp.AbsolutePosition, position);
122 177
123 if (dis > 100.0) // Max audio distance 178 if (dis > MaxDistance) // Max audio distance
124 return; 179 return;
125 180
126 float thisSpGain;
127
128 // Scale by distance 181 // Scale by distance
129 if (radius == 0) 182 double thisSpGain = gain * ((radius - dis) / radius);
130 thisSpGain = (float)((double)gain * ((100.0 - dis) / 100.0)); 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 }
131 else 328 else
132 thisSpGain = (float)((double)gain * ((radius - dis) / radius)); 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 }
133 341
134 sp.ControllingClient.SendTriggeredSound( 342 public void TriggerSoundLimited(UUID objectID, UUID sound,
135 soundId, ownerID, objectID, parentID, handle, position, thisSpGain); 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
362 // Scale by distance
363 double thisSpGain = volume * ((MaxDistance - dis) / MaxDistance);
364
365 sp.ControllingClient.SendTriggeredSound(sound, part.OwnerID,
366 part.UUID, part.ParentGroup.UUID,
367 m_scene.RegionInfo.RegionHandle,
368 part.AbsolutePosition, (float)thisSpGain);
136 }); 369 });
137 } 370 }
371
372 #endregion
138 } 373 }
139} 374}
diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
index 402b9fb..d99567c 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs
@@ -414,6 +414,7 @@ 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());
417 string plugineffectsPath = "Terrain"; 418 string plugineffectsPath = "Terrain";
418 419
419 // Load the files in the Terrain/ dir 420 // Load the files in the Terrain/ dir
@@ -427,34 +428,39 @@ namespace OpenSim.Region.CoreModules.World.Terrain
427 try 428 try
428 { 429 {
429 Assembly library = Assembly.LoadFrom(file); 430 Assembly library = Assembly.LoadFrom(file);
430 foreach (Type pluginType in library.GetTypes()) 431 LoadPlugins(library);
431 { 432 }
432 try 433 catch (BadImageFormatException)
433 { 434 {
434 if (pluginType.IsAbstract || pluginType.IsNotPublic) 435 }
435 continue; 436 }
437 }
436 438
437 string typeName = pluginType.Name; 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;
438 447
439 if (pluginType.GetInterface("ITerrainEffect", false) != null) 448 string typeName = pluginType.Name;
440 {
441 ITerrainEffect terEffect = (ITerrainEffect) Activator.CreateInstance(library.GetType(pluginType.ToString()));
442 449
443 InstallPlugin(typeName, terEffect); 450 if (pluginType.GetInterface("ITerrainEffect", false) != null)
444 } 451 {
445 else if (pluginType.GetInterface("ITerrainLoader", false) != null) 452 ITerrainEffect terEffect = (ITerrainEffect)Activator.CreateInstance(library.GetType(pluginType.ToString()));
446 { 453
447 ITerrainLoader terLoader = (ITerrainLoader) Activator.CreateInstance(library.GetType(pluginType.ToString())); 454 InstallPlugin(typeName, terEffect);
448 m_loaders[terLoader.FileExtension] = terLoader; 455 }
449 m_log.Info("L ... " + typeName); 456 else if (pluginType.GetInterface("ITerrainLoader", false) != null)
450 } 457 {
451 } 458 ITerrainLoader terLoader = (ITerrainLoader)Activator.CreateInstance(library.GetType(pluginType.ToString()));
452 catch (AmbiguousMatchException) 459 m_loaders[terLoader.FileExtension] = terLoader;
453 { 460 m_log.Info("L ... " + typeName);
454 }
455 } 461 }
456 } 462 }
457 catch (BadImageFormatException) 463 catch (AmbiguousMatchException)
458 { 464 {
459 } 465 }
460 } 466 }
@@ -1178,7 +1184,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1178 1184
1179 private void InterfaceRunPluginEffect(Object[] args) 1185 private void InterfaceRunPluginEffect(Object[] args)
1180 { 1186 {
1181 if ((string) args[0] == "list") 1187 string firstArg = (string)args[0];
1188 if (firstArg == "list")
1182 { 1189 {
1183 m_log.Info("List of loaded plugins"); 1190 m_log.Info("List of loaded plugins");
1184 foreach (KeyValuePair<string, ITerrainEffect> kvp in m_plugineffects) 1191 foreach (KeyValuePair<string, ITerrainEffect> kvp in m_plugineffects)
@@ -1187,14 +1194,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain
1187 } 1194 }
1188 return; 1195 return;
1189 } 1196 }
1190 if ((string) args[0] == "reload") 1197 if (firstArg == "reload")
1191 { 1198 {
1192 LoadPlugins(); 1199 LoadPlugins();
1193 return; 1200 return;
1194 } 1201 }
1195 if (m_plugineffects.ContainsKey((string) args[0])) 1202 if (m_plugineffects.ContainsKey(firstArg))
1196 { 1203 {
1197 m_plugineffects[(string) args[0]].RunEffect(m_channel); 1204 m_plugineffects[firstArg].RunEffect(m_channel);
1198 CheckForTerrainUpdates(); 1205 CheckForTerrainUpdates();
1199 } 1206 }
1200 else 1207 else
diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
index 3c48d07..33f6c3f 100644
--- a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
+++ b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs
@@ -222,6 +222,13 @@ 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
225 return bitmap; 232 return bitmap;
226 } 233 }
227 234
diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
index 90a13a7..d781eae 100644
--- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
@@ -114,6 +114,15 @@ 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>
117 /// Detach the given attachment so that it remains in the user's inventory. 126 /// Detach the given attachment so that it remains in the user's inventory.
118 /// </summary> 127 /// </summary>
119 /// <param name="sp">/param> 128 /// <param name="sp">/param>
diff --git a/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs b/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs
index 8954513..6df5cc2 100644
--- a/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs
+++ b/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs
@@ -25,6 +25,8 @@
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;
28using System.IO; 30using System.IO;
29using OpenMetaverse; 31using OpenMetaverse;
30 32
@@ -33,7 +35,14 @@ namespace OpenSim.Region.Framework.Interfaces
33 public interface IDynamicTextureManager 35 public interface IDynamicTextureManager
34 { 36 {
35 void RegisterRender(string handleType, IDynamicTextureRender render); 37 void RegisterRender(string handleType, IDynamicTextureRender render);
36 void ReturnData(UUID id, byte[] data); 38
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);
37 46
38 UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams, 47 UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams,
39 int updateTimer); 48 int updateTimer);
@@ -113,11 +122,65 @@ namespace OpenSim.Region.Framework.Interfaces
113 string GetName(); 122 string GetName();
114 string GetContentType(); 123 string GetContentType();
115 bool SupportsAsynchronous(); 124 bool SupportsAsynchronous();
116 byte[] ConvertUrl(string url, string extraParams); 125
117 byte[] ConvertStream(Stream data, string extraParams); 126// /// <summary>
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
118 bool AsyncConvertUrl(UUID id, string url, string extraParams); 140 bool AsyncConvertUrl(UUID id, string url, string extraParams);
119 bool AsyncConvertData(UUID id, string bodyData, string extraParams); 141 bool AsyncConvertData(UUID id, string bodyData, string extraParams);
142
120 void GetDrawStringSize(string text, string fontName, int fontSize, 143 void GetDrawStringSize(string text, string fontName, int fontSize,
121 out double xSize, out double ySize); 144 out double xSize, out double ySize);
122 } 145 }
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 }
123} 186}
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
index 4274cbe..8028d87 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
@@ -152,6 +152,19 @@ 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>
155 /// Add an item to this entity's inventory. If an item with the same name already exists, then an alternative 168 /// Add an item to this entity's inventory. If an item with the same name already exists, then an alternative
156 /// name is chosen. 169 /// name is chosen.
157 /// </summary> 170 /// </summary>
@@ -270,17 +283,25 @@ namespace OpenSim.Region.Framework.Interfaces
270 void ApplyGodPermissions(uint perms); 283 void ApplyGodPermissions(uint perms);
271 284
272 /// <summary> 285 /// <summary>
286 /// Number of items in this inventory.
287 /// </summary>
288 int Count { get; }
289
290 /// <summary>
273 /// Returns true if this inventory contains any scripts 291 /// Returns true if this inventory contains any scripts
274 /// </summary></returns> 292 /// </summary></returns>
275 bool ContainsScripts(); 293 bool ContainsScripts();
276 294
277 /// <summary> 295 /// <summary>
278 /// Returns the count of scripts contained 296 /// Number of scripts in this inventory.
279 /// </summary></returns> 297 /// </summary>
298 /// <remarks>
299 /// Includes both running and non running scripts.
300 /// </remarks>
280 int ScriptCount(); 301 int ScriptCount();
281 302
282 /// <summary> 303 /// <summary>
283 /// Returns the count of running scripts contained 304 /// Number of running scripts in this inventory.
284 /// </summary></returns> 305 /// </summary></returns>
285 int RunningScriptCount(); 306 int RunningScriptCount();
286 307
diff --git a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
index ca2ad94..292efa4 100644
--- a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
@@ -46,6 +46,10 @@ 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>
49 void TriggerRegionInfoChange(); 53 void TriggerRegionInfoChange();
50 54
51 void setEstateTerrainBaseTexture(int level, UUID texture); 55 void setEstateTerrainBaseTexture(int level, UUID texture);
diff --git a/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs
index baac6e8..da39e95 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, out UUID result); 38 bool CreateStore(string value, ref 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 a76ffde..70ff954 100644
--- a/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs
+++ b/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs
@@ -47,9 +47,46 @@ 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>
50 void RegisterScriptInvocation(object target, string method); 55 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>
51 void RegisterScriptInvocation(object target, MethodInfo method); 62 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>
52 void RegisterScriptInvocation(object target, string[] methods); 69 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>
53 Delegate[] GetScriptInvocationList(); 90 Delegate[] GetScriptInvocationList();
54 91
55 Delegate LookupScriptInvocation(string fname); 92 Delegate LookupScriptInvocation(string fname);
@@ -68,12 +105,44 @@ namespace OpenSim.Region.Framework.Interfaces
68 /// <param name="key"></param> 105 /// <param name="key"></param>
69 void DispatchReply(UUID scriptId, int code, string text, string key); 106 void DispatchReply(UUID scriptId, int code, string text, string key);
70 107
71 /// For constants 108 /// <summary>
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>
72 void RegisterConstant(string cname, object value); 120 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>
73 object LookupModConstant(string cname); 134 object LookupModConstant(string cname);
74 Dictionary<string, object> GetConstants(); 135 Dictionary<string, object> GetConstants();
75 136
76 // For use ONLY by the script API 137 // For use ONLY by the script API
77 void RaiseEvent(UUID script, string id, string module, string command, string key); 138 void RaiseEvent(UUID script, string id, string module, string command, string key);
78 } 139 }
140
141 [AttributeUsage(AttributeTargets.Method)]
142 public class ScriptInvocationAttribute : Attribute
143 { }
144
145 [AttributeUsage(AttributeTargets.Field)]
146 public class ScriptConstantAttribute : Attribute
147 { }
79} 148}
diff --git a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs
index 6117a80..68af492 100644
--- a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs
@@ -32,9 +32,96 @@ namespace OpenSim.Region.Framework.Interfaces
32{ 32{
33 public interface ISoundModule 33 public interface ISoundModule
34 { 34 {
35 void PlayAttachedSound(UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags, float radius); 35 /// <summary>
36 36 /// Maximum distance between a sound source and a recipient.
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>
37 void TriggerSound( 68 void TriggerSound(
38 UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius); 69 UUID soundId, UUID ownerID, UUID objectID, UUID parentID,
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);
39 } 126 }
40} \ No newline at end of file 127} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Interfaces/IUrlModule.cs b/OpenSim/Region/Framework/Interfaces/IUrlModule.cs
index 457444c..79e9f9d 100644
--- a/OpenSim/Region/Framework/Interfaces/IUrlModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IUrlModule.cs
@@ -39,6 +39,8 @@ 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
42 string GetHttpHeader(UUID request, string header); 44 string GetHttpHeader(UUID request, string header);
43 int GetFreeUrls(); 45 int GetFreeUrls();
44 46
diff --git a/OpenSim/Region/Framework/Interfaces/IUserManagement.cs b/OpenSim/Region/Framework/Interfaces/IUserManagement.cs
index 24cd069..f8088c3 100644
--- a/OpenSim/Region/Framework/Interfaces/IUserManagement.cs
+++ b/OpenSim/Region/Framework/Interfaces/IUserManagement.cs
@@ -1,4 +1,31 @@
1using System; 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;
2using System.Collections.Generic; 29using System.Collections.Generic;
3 30
4using OpenMetaverse; 31using OpenMetaverse;
diff --git a/OpenSim/Region/Framework/Interfaces/IWorldComm.cs b/OpenSim/Region/Framework/Interfaces/IWorldComm.cs
index e8e375e..20e0199 100644
--- a/OpenSim/Region/Framework/Interfaces/IWorldComm.cs
+++ b/OpenSim/Region/Framework/Interfaces/IWorldComm.cs
@@ -45,6 +45,13 @@ 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; }
48 } 55 }
49 56
50 public interface IWorldComm 57 public interface IWorldComm
@@ -60,7 +67,7 @@ namespace OpenSim.Region.Framework.Interfaces
60 /// the script during 'peek' time. Parameter hostID is needed to 67 /// the script during 'peek' time. Parameter hostID is needed to
61 /// determine the position of the script. 68 /// determine the position of the script.
62 /// </summary> 69 /// </summary>
63 /// <param name="localID">localID of the script engine</param> 70 /// <param name="LocalID">localID of the script engine</param>
64 /// <param name="itemID">UUID of the script engine</param> 71 /// <param name="itemID">UUID of the script engine</param>
65 /// <param name="hostID">UUID of the SceneObjectPart</param> 72 /// <param name="hostID">UUID of the SceneObjectPart</param>
66 /// <param name="channel">channel to listen on</param> 73 /// <param name="channel">channel to listen on</param>
@@ -70,6 +77,23 @@ namespace OpenSim.Region.Framework.Interfaces
70 /// <returns>number of the scripts handle</returns> 77 /// <returns>number of the scripts handle</returns>
71 int Listen(uint LocalID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg); 78 int Listen(uint LocalID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg);
72 79
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
73 /// <summary> 97 /// <summary>
74 /// This method scans over the objects which registered an interest in listen callbacks. 98 /// This method scans over the objects which registered an interest in listen callbacks.
75 /// For everyone it finds, it checks if it fits the given filter. If it does, then 99 /// 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 ad421ee..65ae445 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs
@@ -41,6 +41,7 @@ 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();
44 private OpenSim.Framework.Animation m_defaultAnimation = new OpenSim.Framework.Animation(); 45 private OpenSim.Framework.Animation m_defaultAnimation = new OpenSim.Framework.Animation();
45 private List<OpenSim.Framework.Animation> m_animations = new List<OpenSim.Framework.Animation>(); 46 private List<OpenSim.Framework.Animation> m_animations = new List<OpenSim.Framework.Animation>();
46 47
@@ -49,6 +50,11 @@ namespace OpenSim.Region.Framework.Scenes.Animation
49 get { return m_defaultAnimation; } 50 get { return m_defaultAnimation; }
50 } 51 }
51 52
53 public OpenSim.Framework.Animation ImplicitDefaultAnimation
54 {
55 get { return m_implicitDefaultAnimation; }
56 }
57
52 public AnimationSet() 58 public AnimationSet()
53 { 59 {
54 ResetDefaultAnimation(); 60 ResetDefaultAnimation();
@@ -119,11 +125,18 @@ namespace OpenSim.Region.Framework.Scenes.Animation
119 if (m_defaultAnimation.AnimID != animID) 125 if (m_defaultAnimation.AnimID != animID)
120 { 126 {
121 m_defaultAnimation = new OpenSim.Framework.Animation(animID, sequenceNum, objectID); 127 m_defaultAnimation = new OpenSim.Framework.Animation(animID, sequenceNum, objectID);
128 m_implicitDefaultAnimation = m_defaultAnimation;
122 return true; 129 return true;
123 } 130 }
124 return false; 131 return false;
125 } 132 }
126 133
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
127 protected bool ResetDefaultAnimation() 140 protected bool ResetDefaultAnimation()
128 { 141 {
129 return TrySetDefaultAnimation("STAND", 1, UUID.Zero); 142 return TrySetDefaultAnimation("STAND", 1, UUID.Zero);
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index 7916c42..8691b91 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -47,30 +47,75 @@ 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>
50 public event OnFrameDelegate OnFrame; 58 public event OnFrameDelegate OnFrame;
51 59
52 public delegate void ClientMovement(ScenePresence client); 60 public delegate void ClientMovement(ScenePresence client);
53 61
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>
54 public event ClientMovement OnClientMovement; 69 public event ClientMovement OnClientMovement;
55 70
56 public delegate void OnTerrainTaintedDelegate(); 71 public delegate void OnTerrainTaintedDelegate();
57 72
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>
58 public event OnTerrainTaintedDelegate OnTerrainTainted; 80 public event OnTerrainTaintedDelegate OnTerrainTainted;
59 81
60 public delegate void OnTerrainTickDelegate(); 82 public delegate void OnTerrainTickDelegate();
61 83
62 public delegate void OnTerrainUpdateDelegate(); 84 /// <summary>
63 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>
64 public event OnTerrainTickDelegate OnTerrainTick; 91 public event OnTerrainTickDelegate OnTerrainTick;
65 92
93 public delegate void OnTerrainUpdateDelegate();
94
66 public event OnTerrainUpdateDelegate OnTerrainUpdate; 95 public event OnTerrainUpdateDelegate OnTerrainUpdate;
67 96
68 public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup); 97 public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup);
69 98
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>
70 public event OnBackupDelegate OnBackup; 106 public event OnBackupDelegate OnBackup;
71 107
72 public delegate void OnClientConnectCoreDelegate(IClientCore client); 108 public delegate void OnClientConnectCoreDelegate(IClientCore client);
73 109
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>
74 public event OnClientConnectCoreDelegate OnClientConnect; 119 public event OnClientConnectCoreDelegate OnClientConnect;
75 120
76 public delegate void OnNewClientDelegate(IClientAPI client); 121 public delegate void OnNewClientDelegate(IClientAPI client);
@@ -80,33 +125,96 @@ namespace OpenSim.Region.Framework.Scenes
80 /// </summary> 125 /// </summary>
81 /// <remarks> 126 /// <remarks>
82 /// This is triggered for both child and root agent client connections. 127 /// This is triggered for both child and root agent client connections.
128 ///
83 /// Triggered before OnClientLogin. 129 /// 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.
84 /// </remarks> 133 /// </remarks>
85 public event OnNewClientDelegate OnNewClient; 134 public event OnNewClientDelegate OnNewClient;
86 135
87 /// <summary> 136 /// <summary>
88 /// Fired if the client entering this sim is doing so as a new login 137 /// Fired if the client entering this sim is doing so as a new login
89 /// </summary> 138 /// </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>
90 public event Action<IClientAPI> OnClientLogin; 143 public event Action<IClientAPI> OnClientLogin;
91 144
92 public delegate void OnNewPresenceDelegate(ScenePresence presence); 145 public delegate void OnNewPresenceDelegate(ScenePresence presence);
93 146
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>
94 public event OnNewPresenceDelegate OnNewPresence; 154 public event OnNewPresenceDelegate OnNewPresence;
95 155
96 public delegate void OnRemovePresenceDelegate(UUID agentId); 156 public delegate void OnRemovePresenceDelegate(UUID agentId);
97 157
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>
98 public event OnRemovePresenceDelegate OnRemovePresence; 168 public event OnRemovePresenceDelegate OnRemovePresence;
99 169
100 public delegate void OnParcelPrimCountUpdateDelegate(); 170 public delegate void OnParcelPrimCountUpdateDelegate();
101 171
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>
102 public event OnParcelPrimCountUpdateDelegate OnParcelPrimCountUpdate; 186 public event OnParcelPrimCountUpdateDelegate OnParcelPrimCountUpdate;
103 187
104 public delegate void OnParcelPrimCountAddDelegate(SceneObjectGroup obj); 188 public delegate void OnParcelPrimCountAddDelegate(SceneObjectGroup obj);
105 189
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>
106 public event OnParcelPrimCountAddDelegate OnParcelPrimCountAdd; 198 public event OnParcelPrimCountAddDelegate OnParcelPrimCountAdd;
107 199
108 public delegate void OnPluginConsoleDelegate(string[] args); 200 public delegate void OnPluginConsoleDelegate(string[] args);
109 201
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>
110 public event OnPluginConsoleDelegate OnPluginConsole; 218 public event OnPluginConsoleDelegate OnPluginConsole;
111 219
112 /// <summary> 220 /// <summary>
@@ -121,8 +229,28 @@ namespace OpenSim.Region.Framework.Scenes
121 229
122 public delegate void OnSetRootAgentSceneDelegate(UUID agentID, Scene scene); 230 public delegate void OnSetRootAgentSceneDelegate(UUID agentID, Scene scene);
123 231
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>
124 public event OnSetRootAgentSceneDelegate OnSetRootAgentScene; 244 public event OnSetRootAgentSceneDelegate OnSetRootAgentScene;
125 245
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>
126 public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest; 254 public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest;
127 255
128 /// <summary> 256 /// <summary>
@@ -137,13 +265,45 @@ namespace OpenSim.Region.Framework.Scenes
137 /// <summary> 265 /// <summary>
138 /// Fired when an object is touched/grabbed. 266 /// Fired when an object is touched/grabbed.
139 /// </summary> 267 /// </summary>
268 /// <remarks>
140 /// The originalID is the local ID of the part that was actually touched. The localID itself is always that of 269 /// The originalID is the local ID of the part that was actually touched. The localID itself is always that of
141 /// the root part. 270 /// 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>
142 public event ObjectGrabDelegate OnObjectGrab; 275 public event ObjectGrabDelegate OnObjectGrab;
143 public delegate void ObjectGrabDelegate(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs); 276 public delegate void ObjectGrabDelegate(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs);
144 277
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>
145 public event ObjectGrabDelegate OnObjectGrabbing; 286 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>
146 public event ObjectDeGrabDelegate OnObjectDeGrab; 296 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>
147 public event ScriptResetDelegate OnScriptReset; 307 public event ScriptResetDelegate OnScriptReset;
148 308
149 public event OnPermissionErrorDelegate OnPermissionError; 309 public event OnPermissionErrorDelegate OnPermissionError;
@@ -153,29 +313,105 @@ namespace OpenSim.Region.Framework.Scenes
153 /// </summary> 313 /// </summary>
154 /// <remarks> 314 /// <remarks>
155 /// Occurs after OnNewScript. 315 /// Occurs after OnNewScript.
316 /// Triggered by <see cref="TriggerRezScript"/>
317 /// in <see cref="SceneObjectPartInventory.CreateScriptInstance"/>
156 /// </remarks> 318 /// </remarks>
157 public event NewRezScript OnRezScript; 319 public event NewRezScript OnRezScript;
158 public delegate void NewRezScript(uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine, int stateSource); 320 public delegate void NewRezScript(uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine, int stateSource);
159 321
160 public delegate void RemoveScript(uint localID, UUID itemID); 322 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>
161 public event RemoveScript OnRemoveScript; 334 public event RemoveScript OnRemoveScript;
162 335
163 public delegate void StartScript(uint localID, UUID itemID); 336 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>
164 public event StartScript OnStartScript; 347 public event StartScript OnStartScript;
165 348
166 public delegate void StopScript(uint localID, UUID itemID); 349 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>
167 public event StopScript OnStopScript; 360 public event StopScript OnStopScript;
168 361
169 public delegate bool SceneGroupMoved(UUID groupID, Vector3 delta); 362 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>
170 public event SceneGroupMoved OnSceneGroupMove; 372 public event SceneGroupMoved OnSceneGroupMove;
171 373
172 public delegate void SceneGroupGrabed(UUID groupID, Vector3 offset, UUID userID); 374 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>
173 public event SceneGroupGrabed OnSceneGroupGrab; 387 public event SceneGroupGrabed OnSceneGroupGrab;
174 388
175 public delegate bool SceneGroupSpinStarted(UUID groupID); 389 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>
176 public event SceneGroupSpinStarted OnSceneGroupSpinStart; 401 public event SceneGroupSpinStarted OnSceneGroupSpinStart;
177 402
178 public delegate bool SceneGroupSpun(UUID groupID, Quaternion rotation); 403 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>
179 public event SceneGroupSpun OnSceneGroupSpin; 415 public event SceneGroupSpun OnSceneGroupSpin;
180 416
181 public delegate void LandObjectAdded(ILandObject newParcel); 417 public delegate void LandObjectAdded(ILandObject newParcel);
@@ -204,6 +440,9 @@ namespace OpenSim.Region.Framework.Scenes
204 /// </summary> 440 /// </summary>
205 /// <remarks> 441 /// <remarks>
206 /// At the point of firing, the scene still contains the client's scene presence. 442 /// 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.
207 /// </remarks> 446 /// </remarks>
208 public event ClientClosed OnClientClosed; 447 public event ClientClosed OnClientClosed;
209 448
@@ -214,6 +453,9 @@ namespace OpenSim.Region.Framework.Scenes
214 /// </summary> 453 /// </summary>
215 /// <remarks> 454 /// <remarks>
216 /// Occurs before OnRezScript 455 /// Occurs before OnRezScript
456 /// Triggered by <see cref="TriggerNewScript"/>
457 /// in <see cref="Scene.RezScriptFromAgentInventory"/>,
458 /// <see cref="Scene.RezNewScript"/>
217 /// </remarks> 459 /// </remarks>
218 public event NewScript OnNewScript; 460 public event NewScript OnNewScript;
219 461
@@ -248,6 +490,12 @@ namespace OpenSim.Region.Framework.Scenes
248 /// </summary> 490 /// </summary>
249 /// <remarks> 491 /// <remarks>
250 /// Triggered after the scene receives a client's upload of an updated script and has stored it in an asset. 492 /// 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"/>
251 /// </remarks> 499 /// </remarks>
252 public event UpdateScript OnUpdateScript; 500 public event UpdateScript OnUpdateScript;
253 501
@@ -273,48 +521,203 @@ namespace OpenSim.Region.Framework.Scenes
273 } 521 }
274 522
275 /// <summary> 523 /// <summary>
524 /// Triggered when some scene object properties change.
525 /// </summary>
526 /// <remarks>
276 /// ScriptChangedEvent is fired when a scene object property that a script might be interested 527 /// ScriptChangedEvent is fired when a scene object property that a script might be interested
277 /// in (such as color, scale or inventory) changes. Only enough information sent is for the LSL changed event. 528 /// in (such as color, scale or inventory) changes. Only enough information sent is for the LSL changed event.
278 /// This is not an indication that the script has changed (see OnUpdateScript for that). 529 /// This is not an indication that the script has changed (see OnUpdateScript for that).
279 /// This event is sent to a script to tell it that some property changed on 530 /// This event is sent to a script to tell it that some property changed on
280 /// the object the script is in. See http://lslwiki.net/lslwiki/wakka.php?wakka=changed . 531 /// the object the script is in. See http://lslwiki.net/lslwiki/wakka.php?wakka=changed .
281 /// </summary> 532 /// Triggered by <see cref="TriggerOnScriptChangedEvent"/>
533 /// in <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.TeleportAgentWithinRegion"/>,
534 /// <see cref="SceneObjectPart.TriggerScriptChangedEvent"/>
535 /// </remarks>
282 public event ScriptChangedEvent OnScriptChangedEvent; 536 public event ScriptChangedEvent OnScriptChangedEvent;
283 public delegate void ScriptChangedEvent(uint localID, uint change); 537 public delegate void ScriptChangedEvent(uint localID, uint change);
284 538
285 public delegate void ScriptControlEvent(UUID item, UUID avatarID, uint held, uint changed); 539 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>
286 public event ScriptControlEvent OnScriptControlEvent; 551 public event ScriptControlEvent OnScriptControlEvent;
287 552
288 public delegate void ScriptAtTargetEvent(uint localID, uint handle, Vector3 targetpos, Vector3 atpos); 553 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>
289 public event ScriptAtTargetEvent OnScriptAtTargetEvent; 565 public event ScriptAtTargetEvent OnScriptAtTargetEvent;
290 566
291 public delegate void ScriptNotAtTargetEvent(uint localID); 567 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>
292 public event ScriptNotAtTargetEvent OnScriptNotAtTargetEvent; 579 public event ScriptNotAtTargetEvent OnScriptNotAtTargetEvent;
293 580
294 public delegate void ScriptAtRotTargetEvent(uint localID, uint handle, Quaternion targetrot, Quaternion atrot); 581 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>
295 public event ScriptAtRotTargetEvent OnScriptAtRotTargetEvent; 593 public event ScriptAtRotTargetEvent OnScriptAtRotTargetEvent;
296 594
297 public delegate void ScriptNotAtRotTargetEvent(uint localID); 595 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>
298 public event ScriptNotAtRotTargetEvent OnScriptNotAtRotTargetEvent; 607 public event ScriptNotAtRotTargetEvent OnScriptNotAtRotTargetEvent;
299 608
300 public delegate void ScriptColliding(uint localID, ColliderArgs colliders); 609 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>
301 public event ScriptColliding OnScriptColliderStart; 622 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>
302 public event ScriptColliding OnScriptColliding; 636 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>
303 public event ScriptColliding OnScriptCollidingEnd; 649 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>
304 public event ScriptColliding OnScriptLandColliderStart; 662 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>
305 public event ScriptColliding OnScriptLandColliding; 675 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>
306 public event ScriptColliding OnScriptLandColliderEnd; 688 public event ScriptColliding OnScriptLandColliderEnd;
307 689
308 public delegate void OnMakeChildAgentDelegate(ScenePresence presence); 690 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>
309 public event OnMakeChildAgentDelegate OnMakeChildAgent; 702 public event OnMakeChildAgentDelegate OnMakeChildAgent;
310 703
311 public delegate void OnSaveNewWindlightProfileDelegate(); 704 public delegate void OnSaveNewWindlightProfileDelegate();
312 public delegate void OnSendNewWindlightProfileTargetedDelegate(RegionLightShareData wl, UUID user); 705 public delegate void OnSendNewWindlightProfileTargetedDelegate(RegionLightShareData wl, UUID user);
313 706
314 /// <summary> 707 /// <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>
315 /// This event is on the critical path for transferring an avatar from one region to another. Try and do 713 /// This event is on the critical path for transferring an avatar from one region to another. Try and do
316 /// as little work on this event as possible, or do work asynchronously. 714 /// as little work on this event as possible, or do work asynchronously.
317 /// </summary> 715 /// Triggered after <see cref="OnSetRootAgentScene"/>
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>
318 public event Action<ScenePresence> OnMakeRootAgent; 721 public event Action<ScenePresence> OnMakeRootAgent;
319 722
320 public event OnSendNewWindlightProfileTargetedDelegate OnSendNewWindlightProfileTargeted; 723 public event OnSendNewWindlightProfileTargetedDelegate OnSendNewWindlightProfileTargeted;
@@ -340,9 +743,17 @@ namespace OpenSim.Region.Framework.Scenes
340 public event AvatarKillData OnAvatarKilled; 743 public event AvatarKillData OnAvatarKilled;
341 public delegate void AvatarKillData(uint KillerLocalID, ScenePresence avatar); 744 public delegate void AvatarKillData(uint KillerLocalID, ScenePresence avatar);
342 745
343// public delegate void ScriptTimerEvent(uint localID, double timerinterval); 746 /*
344 747 public delegate void ScriptTimerEvent(uint localID, double timerinterval);
345// public event ScriptTimerEvent OnScriptTimerEvent; 748 /// <summary>
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 */
346 757
347 public delegate void EstateToolsSunUpdate(ulong regionHandle, bool FixedTime, bool EstateSun, float LindenHour); 758 public delegate void EstateToolsSunUpdate(ulong regionHandle, bool FixedTime, bool EstateSun, float LindenHour);
348 public delegate void GetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID); 759 public delegate void GetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID);
@@ -352,12 +763,27 @@ namespace OpenSim.Region.Framework.Scenes
352 /// <summary> 763 /// <summary>
353 /// Triggered when an object is added to the scene. 764 /// Triggered when an object is added to the scene.
354 /// </summary> 765 /// </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>
355 public event Action<SceneObjectGroup> OnObjectAddedToScene; 772 public event Action<SceneObjectGroup> OnObjectAddedToScene;
356 773
357 /// <summary> 774 /// <summary>
358 /// Triggered when an object is removed from the scene. 775 /// Delegate for <see cref="OnObjectBeingRemovedFromScene"/>
359 /// </summary> 776 /// </summary>
777 /// <param name="obj">The object being removed from the scene</param>
360 public delegate void ObjectBeingRemovedFromScene(SceneObjectGroup obj); 778 public delegate void ObjectBeingRemovedFromScene(SceneObjectGroup obj);
779
780 /// <summary>
781 /// Triggered when an object is removed from the scene.
782 /// </summary>
783 /// <remarks>
784 /// Triggered by <see cref="TriggerObjectBeingRemovedFromScene"/>
785 /// in <see cref="Scene.DeleteSceneObject"/>
786 /// </remarks>
361 public event ObjectBeingRemovedFromScene OnObjectBeingRemovedFromScene; 787 public event ObjectBeingRemovedFromScene OnObjectBeingRemovedFromScene;
362 788
363 public delegate void NoticeNoLandDataFromStorage(); 789 public delegate void NoticeNoLandDataFromStorage();
@@ -373,6 +799,20 @@ namespace OpenSim.Region.Framework.Scenes
373 public event RequestParcelPrimCountUpdate OnRequestParcelPrimCountUpdate; 799 public event RequestParcelPrimCountUpdate OnRequestParcelPrimCountUpdate;
374 800
375 public delegate void ParcelPrimCountTainted(); 801 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>
376 public event ParcelPrimCountTainted OnParcelPrimCountTainted; 816 public event ParcelPrimCountTainted OnParcelPrimCountTainted;
377 public event GetScriptRunning OnGetScriptRunning; 817 public event GetScriptRunning OnGetScriptRunning;
378 818
@@ -432,7 +872,7 @@ namespace OpenSim.Region.Framework.Scenes
432 /// the scripts may not have started yet 872 /// the scripts may not have started yet
433 /// Message is non empty string if there were problems loading the oar file 873 /// Message is non empty string if there were problems loading the oar file
434 /// </summary> 874 /// </summary>
435 public delegate void OarFileLoaded(Guid guid, string message); 875 public delegate void OarFileLoaded(Guid guid, List<UUID> loadedScenes, string message);
436 public event OarFileLoaded OnOarFileLoaded; 876 public event OarFileLoaded OnOarFileLoaded;
437 877
438 /// <summary> 878 /// <summary>
@@ -485,10 +925,13 @@ namespace OpenSim.Region.Framework.Scenes
485 /// <param name="copy"></param> 925 /// <param name="copy"></param>
486 /// <param name="original"></param> 926 /// <param name="original"></param>
487 /// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param> 927 /// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param>
928 /// <remarks>
929 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.SceneObjectPart.Copy"/>
930 /// </remarks>
488 public event SceneObjectPartCopyDelegate OnSceneObjectPartCopy; 931 public event SceneObjectPartCopyDelegate OnSceneObjectPartCopy;
489 public delegate void SceneObjectPartCopyDelegate(SceneObjectPart copy, SceneObjectPart original, bool userExposed); 932 public delegate void SceneObjectPartCopyDelegate(SceneObjectPart copy, SceneObjectPart original, bool userExposed);
490 933
491 public delegate void SceneObjectPartUpdated(SceneObjectPart sop); 934 public delegate void SceneObjectPartUpdated(SceneObjectPart sop, bool full);
492 public event SceneObjectPartUpdated OnSceneObjectPartUpdated; 935 public event SceneObjectPartUpdated OnSceneObjectPartUpdated;
493 936
494 public delegate void ScenePresenceUpdated(ScenePresence sp); 937 public delegate void ScenePresenceUpdated(ScenePresence sp);
@@ -526,9 +969,28 @@ namespace OpenSim.Region.Framework.Scenes
526 public event PrimsLoaded OnPrimsLoaded; 969 public event PrimsLoaded OnPrimsLoaded;
527 970
528 public delegate void TeleportStart(IClientAPI client, GridRegion destination, GridRegion finalDestination, uint teleportFlags, bool gridLogout); 971 public delegate void TeleportStart(IClientAPI client, GridRegion destination, GridRegion finalDestination, uint teleportFlags, bool gridLogout);
972
973 /// <summary>
974 /// Triggered when a teleport starts
975 /// </summary>
976 /// <remarks>
977 /// Triggered by <see cref="TriggerTeleportStart"/>
978 /// in <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.CreateAgent"/>
979 /// and <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.HGEntityTransferModule.CreateAgent"/>
980 /// via <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.DoTeleport"/>
981 /// </remarks>
529 public event TeleportStart OnTeleportStart; 982 public event TeleportStart OnTeleportStart;
530 983
531 public delegate void TeleportFail(IClientAPI client, bool gridLogout); 984 public delegate void TeleportFail(IClientAPI client, bool gridLogout);
985
986 /// <summary>
987 /// Trigered when a teleport fails.
988 /// </summary>
989 /// <remarks>
990 /// Triggered by <see cref="TriggerTeleportFail"/>
991 /// in <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.Fail"/>
992 /// via <see cref="OpenSim.Region.CoreModules.Framework.EntityTransfer.EntityTransferModule.DoTeleport"/>
993 /// </remarks>
532 public event TeleportFail OnTeleportFail; 994 public event TeleportFail OnTeleportFail;
533 995
534 public class MoneyTransferArgs : EventArgs 996 public class MoneyTransferArgs : EventArgs
@@ -536,7 +998,9 @@ namespace OpenSim.Region.Framework.Scenes
536 public UUID sender; 998 public UUID sender;
537 public UUID receiver; 999 public UUID receiver;
538 1000
539 // Always false. The SL protocol sucks. 1001 /// <summary>
1002 /// Always false. The SL protocol sucks.
1003 /// </summary>
540 public bool authenticated = false; 1004 public bool authenticated = false;
541 1005
542 public int amount; 1006 public int amount;
@@ -593,8 +1057,29 @@ namespace OpenSim.Region.Framework.Scenes
593 1057
594 public delegate void LandBuy(Object sender, LandBuyArgs e); 1058 public delegate void LandBuy(Object sender, LandBuyArgs e);
595 1059
1060 /// <summary>
1061 /// Triggered when an attempt to transfer grid currency occurs
1062 /// </summary>
1063 /// <remarks>
1064 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.ProcessMoneyTransferRequest"/>
1065 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.SubscribeToClientGridEvents"/>
1066 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.SubscribeToClientEvents"/>
1067 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/>
1068 /// </remarks>
596 public event MoneyTransferEvent OnMoneyTransfer; 1069 public event MoneyTransferEvent OnMoneyTransfer;
1070
1071 /// <summary>
1072 /// Triggered after after <see cref="OnValidateLandBuy"/>
1073 /// </summary>
597 public event LandBuy OnLandBuy; 1074 public event LandBuy OnLandBuy;
1075
1076 /// <summary>
1077 /// Triggered to allow or prevent a real estate transaction
1078 /// </summary>
1079 /// <remarks>
1080 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.ProcessParcelBuy"/>
1081 /// <seealso cref="OpenSim.Region.OptionalModules.World.MoneyModule.SampleMoneyModule.ValidateLandBuy"/>
1082 /// </remarks>
598 public event LandBuy OnValidateLandBuy; 1083 public event LandBuy OnValidateLandBuy;
599 1084
600 public void TriggerOnAttach(uint localID, UUID itemID, UUID avatarID) 1085 public void TriggerOnAttach(uint localID, UUID itemID, UUID avatarID)
@@ -2031,7 +2516,11 @@ namespace OpenSim.Region.Framework.Scenes
2031 } 2516 }
2032 } 2517 }
2033 2518
2034 // this lets us keep track of nasty script events like timer, etc. 2519 /// <summary>
2520 /// this lets us keep track of nasty script events like timer, etc.
2521 /// </summary>
2522 /// <param name="objLocalID"></param>
2523 /// <param name="Interval"></param>
2035 public void TriggerTimerEvent(uint objLocalID, double Interval) 2524 public void TriggerTimerEvent(uint objLocalID, double Interval)
2036 { 2525 {
2037 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"); 2526 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");
@@ -2093,7 +2582,7 @@ namespace OpenSim.Region.Framework.Scenes
2093 return 6; 2582 return 6;
2094 } 2583 }
2095 2584
2096 public void TriggerOarFileLoaded(Guid requestId, string message) 2585 public void TriggerOarFileLoaded(Guid requestId, List<UUID> loadedScenes, string message)
2097 { 2586 {
2098 OarFileLoaded handlerOarFileLoaded = OnOarFileLoaded; 2587 OarFileLoaded handlerOarFileLoaded = OnOarFileLoaded;
2099 if (handlerOarFileLoaded != null) 2588 if (handlerOarFileLoaded != null)
@@ -2102,7 +2591,7 @@ namespace OpenSim.Region.Framework.Scenes
2102 { 2591 {
2103 try 2592 try
2104 { 2593 {
2105 d(requestId, message); 2594 d(requestId, loadedScenes, message);
2106 } 2595 }
2107 catch (Exception e) 2596 catch (Exception e)
2108 { 2597 {
@@ -2387,7 +2876,7 @@ namespace OpenSim.Region.Framework.Scenes
2387 } 2876 }
2388 } 2877 }
2389 2878
2390 public void TriggerSceneObjectPartUpdated(SceneObjectPart sop) 2879 public void TriggerSceneObjectPartUpdated(SceneObjectPart sop, bool full)
2391 { 2880 {
2392 SceneObjectPartUpdated handler = OnSceneObjectPartUpdated; 2881 SceneObjectPartUpdated handler = OnSceneObjectPartUpdated;
2393 if (handler != null) 2882 if (handler != null)
@@ -2396,7 +2885,7 @@ namespace OpenSim.Region.Framework.Scenes
2396 { 2885 {
2397 try 2886 try
2398 { 2887 {
2399 d(sop); 2888 d(sop, full);
2400 } 2889 }
2401 catch (Exception e) 2890 catch (Exception e)
2402 { 2891 {
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 906c1ee..6208a57 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 private void SendInventoryUpdate(IClientAPI client, InventoryFolderBase folder, bool fetchFolders, bool fetchItems) 1472 public 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,6 +1997,9 @@ 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
2000 if (remoteClient == null) 2003 if (remoteClient == null)
2001 { 2004 {
2002 // Autoreturn has a null client. Nothing else does. So 2005 // 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 e970543..ce6415a 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -38,8 +38,20 @@ 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>
41 public void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName, 53 public void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName,
42 UUID fromID, bool fromAgent, bool broadcast, UUID destination) 54 UUID fromID, UUID targetID, bool fromAgent, bool broadcast)
43 { 55 {
44 OSChatMessage args = new OSChatMessage(); 56 OSChatMessage args = new OSChatMessage();
45 57
@@ -49,7 +61,7 @@ namespace OpenSim.Region.Framework.Scenes
49 args.Position = fromPos; 61 args.Position = fromPos;
50 args.SenderUUID = fromID; 62 args.SenderUUID = fromID;
51 args.Scene = this; 63 args.Scene = this;
52 args.Destination = destination; 64 args.Destination = targetID;
53 65
54 if (fromAgent) 66 if (fromAgent)
55 { 67 {
@@ -66,6 +78,10 @@ namespace OpenSim.Region.Framework.Scenes
66 args.From = fromName; 78 args.From = fromName;
67 //args. 79 //args.
68 80
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
69 if (broadcast) 85 if (broadcast)
70 EventManager.TriggerOnChatBroadcast(this, args); 86 EventManager.TriggerOnChatBroadcast(this, args);
71 else 87 else
@@ -75,7 +91,7 @@ namespace OpenSim.Region.Framework.Scenes
75 protected void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName, 91 protected void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName,
76 UUID fromID, bool fromAgent, bool broadcast) 92 UUID fromID, bool fromAgent, bool broadcast)
77 { 93 {
78 SimChat(message, type, channel, fromPos, fromName, fromID, fromAgent, broadcast, UUID.Zero); 94 SimChat(message, type, channel, fromPos, fromName, fromID, UUID.Zero, fromAgent, broadcast);
79 } 95 }
80 96
81 /// <summary> 97 /// <summary>
@@ -543,7 +559,7 @@ namespace OpenSim.Region.Framework.Scenes
543 if (!InventoryService.AddFolder(folder)) 559 if (!InventoryService.AddFolder(folder))
544 { 560 {
545 m_log.WarnFormat( 561 m_log.WarnFormat(
546 "[AGENT INVENTORY]: Failed to move create folder for user {0} {1}", 562 "[AGENT INVENTORY]: Failed to create folder for user {0} {1}",
547 remoteClient.Name, remoteClient.AgentId); 563 remoteClient.Name, remoteClient.AgentId);
548 } 564 }
549 } 565 }
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 649d545..2543333 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -80,6 +80,11 @@ 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>
83 /// Statistical information for this scene. 88 /// Statistical information for this scene.
84 /// </summary> 89 /// </summary>
85 public SimStatsReporter StatsReporter { get; private set; } 90 public SimStatsReporter StatsReporter { get; private set; }
@@ -103,8 +108,31 @@ namespace OpenSim.Region.Framework.Scenes
103 /// </summary> 108 /// </summary>
104 public bool CollidablePrims { get; private set; } 109 public bool CollidablePrims { get; private set; }
105 110
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>
106 public float m_maxNonphys = 256; 119 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>
107 public float m_maxPhys = 10; 129 public float m_maxPhys = 10;
130
131 /// <summary>
132 /// Max prims an object will hold
133 /// </summary>
134 public int m_linksetCapacity = 0;
135
108 public bool m_clampPrimSize; 136 public bool m_clampPrimSize;
109 public bool m_trustBinaries; 137 public bool m_trustBinaries;
110 public bool m_allowScriptCrossings; 138 public bool m_allowScriptCrossings;
@@ -285,6 +313,31 @@ namespace OpenSim.Region.Framework.Scenes
285 } 313 }
286 private volatile bool m_shuttingDown; 314 private volatile bool m_shuttingDown;
287 315
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
288// private int m_lastUpdate; 341// private int m_lastUpdate;
289 private bool m_firstHeartbeat = true; 342 private bool m_firstHeartbeat = true;
290 343
@@ -746,12 +799,24 @@ namespace OpenSim.Region.Framework.Scenes
746 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true); 799 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true);
747 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true); 800 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true);
748 801
749 m_maxNonphys = startupConfig.GetFloat("NonphysicalPrimMax", m_maxNonphys); 802 m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys);
803 if (RegionInfo.NonphysPrimMin > 0)
804 {
805 m_minNonphys = RegionInfo.NonphysPrimMin;
806 }
807
808 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys);
750 if (RegionInfo.NonphysPrimMax > 0) 809 if (RegionInfo.NonphysPrimMax > 0)
751 { 810 {
752 m_maxNonphys = RegionInfo.NonphysPrimMax; 811 m_maxNonphys = RegionInfo.NonphysPrimMax;
753 } 812 }
754 813
814 m_minPhys = startupConfig.GetFloat("PhysicalPrimMin", m_minPhys);
815 if (RegionInfo.PhysPrimMin > 0)
816 {
817 m_minPhys = RegionInfo.PhysPrimMin;
818 }
819
755 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys); 820 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys);
756 821
757 if (RegionInfo.PhysPrimMax > 0) 822 if (RegionInfo.PhysPrimMax > 0)
@@ -759,6 +824,12 @@ namespace OpenSim.Region.Framework.Scenes
759 m_maxPhys = RegionInfo.PhysPrimMax; 824 m_maxPhys = RegionInfo.PhysPrimMax;
760 } 825 }
761 826
827 m_linksetCapacity = startupConfig.GetInt("LinksetPrims", m_linksetCapacity);
828 if (RegionInfo.LinksetCapacity > 0)
829 {
830 m_linksetCapacity = RegionInfo.LinksetCapacity;
831 }
832
762 SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest"); 833 SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest");
763 TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false); 834 TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false);
764 835
@@ -784,13 +855,6 @@ namespace OpenSim.Region.Framework.Scenes
784 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); 855 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
785 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine); 856 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine);
786 857
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
794 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); 858 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
795 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion); 859 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
796 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false); 860 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false);
@@ -854,6 +918,8 @@ namespace OpenSim.Region.Framework.Scenes
854 } 918 }
855 919
856 // FIXME: Ultimately this should be in a module. 920 // FIXME: Ultimately this should be in a module.
921 SendPeriodicAppearanceUpdates = true;
922
857 IConfig appearanceConfig = m_config.Configs["Appearance"]; 923 IConfig appearanceConfig = m_config.Configs["Appearance"];
858 if (appearanceConfig != null) 924 if (appearanceConfig != null)
859 { 925 {
@@ -1151,6 +1217,14 @@ namespace OpenSim.Region.Framework.Scenes
1151 1217
1152 public void SetSceneCoreDebug(Dictionary<string, string> options) 1218 public void SetSceneCoreDebug(Dictionary<string, string> options)
1153 { 1219 {
1220 if (options.ContainsKey("active"))
1221 {
1222 bool active;
1223
1224 if (bool.TryParse(options["active"], out active))
1225 Active = active;
1226 }
1227
1154 if (options.ContainsKey("scripting")) 1228 if (options.ContainsKey("scripting"))
1155 { 1229 {
1156 bool enableScripts = true; 1230 bool enableScripts = true;
@@ -1226,6 +1300,12 @@ namespace OpenSim.Region.Framework.Scenes
1226 // This is the method that shuts down the scene. 1300 // This is the method that shuts down the scene.
1227 public override void Close() 1301 public override void Close()
1228 { 1302 {
1303 if (m_shuttingDown)
1304 {
1305 m_log.WarnFormat("[SCENE]: Ignoring close request because already closing {0}", Name);
1306 return;
1307 }
1308
1229 m_log.InfoFormat("[SCENE]: Closing down the single simulator: {0}", RegionInfo.RegionName); 1309 m_log.InfoFormat("[SCENE]: Closing down the single simulator: {0}", RegionInfo.RegionName);
1230 1310
1231 StatsReporter.Close(); 1311 StatsReporter.Close();
@@ -1272,6 +1352,14 @@ namespace OpenSim.Region.Framework.Scenes
1272 m_log.Debug("[SCENE]: Graph close"); 1352 m_log.Debug("[SCENE]: Graph close");
1273 m_sceneGraph.Close(); 1353 m_sceneGraph.Close();
1274 1354
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.
1275 if (PhysicsScene != null) 1363 if (PhysicsScene != null)
1276 { 1364 {
1277 m_log.Debug("[SCENE]: Dispose Physics"); 1365 m_log.Debug("[SCENE]: Dispose Physics");
@@ -1281,13 +1369,6 @@ namespace OpenSim.Region.Framework.Scenes
1281 phys.Dispose(); 1369 phys.Dispose();
1282 phys = null; 1370 phys = null;
1283 } 1371 }
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();
1291 } 1372 }
1292 1373
1293 /// <summary> 1374 /// <summary>
@@ -1295,6 +1376,8 @@ namespace OpenSim.Region.Framework.Scenes
1295 /// </summary> 1376 /// </summary>
1296 public void Start() 1377 public void Start()
1297 { 1378 {
1379 m_active = true;
1380
1298// m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName); 1381// m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName);
1299 1382
1300 //m_heartbeatTimer.Enabled = true; 1383 //m_heartbeatTimer.Enabled = true;
@@ -1354,7 +1437,7 @@ namespace OpenSim.Region.Framework.Scenes
1354 #region Update Methods 1437 #region Update Methods
1355 1438
1356 /// <summary> 1439 /// <summary>
1357 /// Performs per-frame updates regularly 1440 /// Activate the various loops necessary to continually update the scene.
1358 /// </summary> 1441 /// </summary>
1359 private void Heartbeat() 1442 private void Heartbeat()
1360 { 1443 {
@@ -1411,7 +1494,7 @@ namespace OpenSim.Region.Framework.Scenes
1411 List<Vector3> coarseLocations; 1494 List<Vector3> coarseLocations;
1412 List<UUID> avatarUUIDs; 1495 List<UUID> avatarUUIDs;
1413 1496
1414 while (!m_shuttingDown && (endRun == null || MaintenanceRun < endRun)) 1497 while (!m_shuttingDown && ((endRun == null && Active) || MaintenanceRun < endRun))
1415 { 1498 {
1416 runtc = Util.EnvironmentTickCount(); 1499 runtc = Util.EnvironmentTickCount();
1417 ++MaintenanceRun; 1500 ++MaintenanceRun;
@@ -1473,7 +1556,7 @@ namespace OpenSim.Region.Framework.Scenes
1473 int sleepMS; 1556 int sleepMS;
1474 int framestart; 1557 int framestart;
1475 1558
1476 while (!m_shuttingDown && (endFrame == null || Frame < endFrame)) 1559 while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame))
1477 { 1560 {
1478 framestart = Util.EnvironmentTickCount(); 1561 framestart = Util.EnvironmentTickCount();
1479 ++Frame; 1562 ++Frame;
@@ -1672,15 +1755,19 @@ namespace OpenSim.Region.Framework.Scenes
1672 1755
1673 private void CheckAtTargets() 1756 private void CheckAtTargets()
1674 { 1757 {
1675 List<SceneObjectGroup> objs = new List<SceneObjectGroup>(); 1758 List<SceneObjectGroup> objs = null;
1759
1676 lock (m_groupsWithTargets) 1760 lock (m_groupsWithTargets)
1677 { 1761 {
1678 foreach (SceneObjectGroup grp in m_groupsWithTargets.Values) 1762 if (m_groupsWithTargets.Count != 0)
1679 objs.Add(grp); 1763 objs = new List<SceneObjectGroup>(m_groupsWithTargets.Values);
1680 } 1764 }
1681 1765
1682 foreach (SceneObjectGroup entry in objs) 1766 if (objs != null)
1683 entry.checkAtTargets(); 1767 {
1768 foreach (SceneObjectGroup entry in objs)
1769 entry.checkAtTargets();
1770 }
1684 } 1771 }
1685 1772
1686 /// <summary> 1773 /// <summary>
@@ -2193,10 +2280,14 @@ namespace OpenSim.Region.Framework.Scenes
2193 public bool AddRestoredSceneObject( 2280 public bool AddRestoredSceneObject(
2194 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 2281 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
2195 { 2282 {
2196 bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); 2283 if (m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates))
2197 if (result) 2284 {
2198 sceneObject.IsDeleted = false; 2285 sceneObject.IsDeleted = false;
2199 return result; 2286 EventManager.TriggerObjectAddedToScene(sceneObject);
2287 return true;
2288 }
2289
2290 return false;
2200 } 2291 }
2201 2292
2202 /// <summary> 2293 /// <summary>
@@ -2837,77 +2928,89 @@ namespace OpenSim.Region.Framework.Scenes
2837 2928
2838 public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type) 2929 public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type)
2839 { 2930 {
2931 ScenePresence sp;
2932 bool vialogin;
2933
2840 // Validation occurs in LLUDPServer 2934 // 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.
2841 AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); 2938 AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode);
2842 2939
2843 bool vialogin 2940 // We lock here on AgentCircuitData to prevent a race condition between the thread adding a new connection
2844 = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 2941 // and a simultaneous one that removes it (as can happen if the client is closed at a particular point
2845 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; 2942 // whilst connecting).
2846 2943 //
2847 CheckHeartbeat(); 2944 // It would be easier to lock across all NewUserConnection(), AddNewClient() and
2848 2945 // RemoveClient() calls for all agents, but this would allow a slow call (e.g. because of slow service
2849 ScenePresence sp = GetScenePresence(client.AgentId); 2946 // response in some module listening to AddNewClient()) from holding up unrelated agent calls.
2850 2947 //
2851 // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this 2948 // In practice, the lock (this) in LLUDPServer.AddNewClient() currently lock across all
2852 // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause 2949 // AddNewClient() operations (though not other ops).
2853 // other problems, and possible the code calling AddNewClient() should ensure that no client is already 2950 // In the future this can be relieved once locking per agent (not necessarily on AgentCircuitData) is improved.
2854 // connected. 2951 lock (aCircuit)
2855 if (sp == null) 2952 {
2856 { 2953 vialogin
2857 m_log.DebugFormat( 2954 = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0
2858 "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", 2955 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2859 client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); 2956
2860 2957 CheckHeartbeat();
2861 m_clientManager.Add(client); 2958
2862 SubscribeToClientEvents(client); 2959 sp = GetScenePresence(client.AgentId);
2863
2864 sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type);
2865 m_eventManager.TriggerOnNewPresence(sp);
2866
2867 sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags;
2868 2960
2869 // The first agent upon login is a root agent by design. 2961 // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this
2870 // For this agent we will have to rez the attachments. 2962 // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause
2871 // All other AddNewClient calls find aCircuit.child to be true. 2963 // other problems, and possible the code calling AddNewClient() should ensure that no client is already
2872 if (aCircuit.child == false) 2964 // connected.
2965 if (sp == null)
2873 { 2966 {
2874 // We have to set SP to be a root agent here so that SP.MakeRootAgent() will later not try to 2967 m_log.DebugFormat(
2875 // start the scripts again (since this is done in RezAttachments()). 2968 "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}",
2876 // XXX: This is convoluted. 2969 client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos);
2877 sp.IsChildAgent = false; 2970
2878 2971 m_clientManager.Add(client);
2879 if (AttachmentsModule != null) 2972 SubscribeToClientEvents(client);
2880 Util.FireAndForget(delegate(object o) { AttachmentsModule.RezAttachments(sp); }); 2973
2974 sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type);
2975 m_eventManager.TriggerOnNewPresence(sp);
2976
2977 sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags;
2978
2979 // The first agent upon login is a root agent by design.
2980 // For this agent we will have to rez the attachments.
2981 // All other AddNewClient calls find aCircuit.child to be true.
2982 if (aCircuit.child == false)
2983 {
2984 // We have to set SP to be a root agent here so that SP.MakeRootAgent() will later not try to
2985 // start the scripts again (since this is done in RezAttachments()).
2986 // XXX: This is convoluted.
2987 sp.IsChildAgent = false;
2988
2989 if (AttachmentsModule != null)
2990 Util.FireAndForget(delegate(object o) { AttachmentsModule.RezAttachments(sp); });
2991 }
2881 } 2992 }
2882 } 2993 else
2883 else 2994 {
2884 { 2995 m_log.WarnFormat(
2885 m_log.WarnFormat( 2996 "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence",
2886 "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", 2997 sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName);
2887 sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); 2998 }
2888 } 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;
2889 3003
2890 // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the 3004 // Cache the user's name
2891 // client is for a root or child agent. 3005 CacheUserName(sp, aCircuit);
2892 client.SceneAgent = sp; 3006
3007 EventManager.TriggerOnNewClient(client);
3008 if (vialogin)
3009 EventManager.TriggerOnClientLogin(client);
3010 }
2893 3011
2894 m_LastLogin = Util.EnvironmentTickCount(); 3012 m_LastLogin = Util.EnvironmentTickCount();
2895 3013
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
2911 return sp; 3014 return sp;
2912 } 3015 }
2913 3016
@@ -3447,110 +3550,132 @@ namespace OpenSim.Region.Framework.Scenes
3447 { 3550 {
3448// CheckHeartbeat(); 3551// CheckHeartbeat();
3449 bool isChildAgent = false; 3552 bool isChildAgent = false;
3450 ScenePresence avatar = GetScenePresence(agentID); 3553 AgentCircuitData acd;
3451 3554
3452 if (avatar == null) 3555 lock (m_removeClientLock)
3453 { 3556 {
3454 m_log.WarnFormat( 3557 acd = m_authenticateHandler.GetAgentCircuitData(agentID);
3455 "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID);
3456
3457 return;
3458 }
3459
3460 try
3461 {
3462 isChildAgent = avatar.IsChildAgent;
3463
3464 m_log.DebugFormat(
3465 "[SCENE]: Removing {0} agent {1} {2} from {3}",
3466 (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName);
3467 3558
3468 // Don't do this to root agents, it's not nice for the viewer 3559 if (acd == null)
3469 if (closeChildAgents && isChildAgent)
3470 { 3560 {
3471 // Tell a single agent to disconnect from the region. 3561 m_log.ErrorFormat("[SCENE]: No agent circuit found for {0}, aborting Scene.RemoveClient", agentID);
3472 IEventQueue eq = RequestModuleInterface<IEventQueue>(); 3562 return;
3473 if (eq != null)
3474 {
3475 eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID);
3476 }
3477 else
3478 {
3479 avatar.ControllingClient.SendShutdownConnectionNotice();
3480 }
3481 } 3563 }
3482 3564 else
3483 // Only applies to root agents.
3484 if (avatar.ParentID != 0)
3485 { 3565 {
3486 avatar.StandUp(); 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);
3487 } 3570 }
3571 }
3488 3572
3489 m_sceneGraph.removeUserCount(!isChildAgent); 3573 lock (acd)
3490 3574 {
3491 // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop 3575 ScenePresence avatar = GetScenePresence(agentID);
3492 // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI 3576
3493 if (closeChildAgents && CapsModule != null) 3577 if (avatar == null)
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 { 3578 {
3502 List<ulong> regions = avatar.KnownRegionHandles; 3579 m_log.WarnFormat(
3503 regions.Remove(RegionInfo.RegionHandle); 3580 "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID);
3504 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); 3581
3582 return;
3505 } 3583 }
3506 3584
3507 m_eventManager.TriggerClientClosed(agentID, this); 3585 try
3508 m_eventManager.TriggerOnRemovePresence(agentID);
3509
3510 if (!isChildAgent)
3511 { 3586 {
3512 if (AttachmentsModule != null) 3587 isChildAgent = avatar.IsChildAgent;
3588
3589 m_log.DebugFormat(
3590 "[SCENE]: Removing {0} agent {1} {2} from {3}",
3591 (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName);
3592
3593 // Don't do this to root agents, it's not nice for the viewer
3594 if (closeChildAgents && isChildAgent)
3513 { 3595 {
3514 AttachmentsModule.DeRezAttachments(avatar); 3596 // Tell a single agent to disconnect from the region.
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 }
3515 } 3606 }
3516 3607
3517 ForEachClient( 3608 // Only applies to root agents.
3518 delegate(IClientAPI client) 3609 if (avatar.ParentID != 0)
3610 {
3611 avatar.StandUp();
3612 }
3613
3614 m_sceneGraph.removeUserCount(!isChildAgent);
3615
3616 // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop
3617 // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI
3618 if (closeChildAgents && CapsModule != null)
3619 CapsModule.RemoveCaps(agentID);
3620
3621// // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever
3622// // this method is doing is HORRIBLE!!!
3623 // Commented pending deletion since this method no longer appears to do anything at all
3624// avatar.Scene.NeedSceneCacheClear(avatar.UUID);
3625
3626 if (closeChildAgents && !isChildAgent)
3627 {
3628 List<ulong> regions = avatar.KnownRegionHandles;
3629 regions.Remove(RegionInfo.RegionHandle);
3630 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions);
3631 }
3632
3633 m_eventManager.TriggerClientClosed(agentID, this);
3634 m_eventManager.TriggerOnRemovePresence(agentID);
3635
3636 if (!isChildAgent)
3637 {
3638 if (AttachmentsModule != null)
3519 { 3639 {
3520 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway 3640 AttachmentsModule.DeRezAttachments(avatar);
3521 try { client.SendKillObject(avatar.RegionHandle, new List<uint> { avatar.LocalId }); } 3641 }
3522 catch (NullReferenceException) { }
3523 });
3524 }
3525
3526 // It's possible for child agents to have transactions if changes are being made cross-border.
3527 if (AgentTransactionsModule != null)
3528 AgentTransactionsModule.RemoveAgentAssetTransactions(agentID);
3529 3642
3530 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); 3643 ForEachClient(
3531 m_log.Debug("[Scene] The avatar has left the building"); 3644 delegate(IClientAPI client)
3532 } 3645 {
3533 catch (Exception e) 3646 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway
3534 { 3647 try { client.SendKillObject(avatar.RegionHandle, new List<uint> { avatar.LocalId }); }
3535 m_log.Error( 3648 catch (NullReferenceException) { }
3536 string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e); 3649 });
3537 } 3650 }
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);
3547 3651
3548 avatar.Close(); 3652 // It's possible for child agents to have transactions if changes are being made cross-border.
3653 if (AgentTransactionsModule != null)
3654 AgentTransactionsModule.RemoveAgentAssetTransactions(agentID);
3655 m_log.Debug("[Scene] The avatar has left the building");
3549 } 3656 }
3550 catch (Exception e) 3657 catch (Exception e)
3551 { 3658 {
3552 m_log.Error( 3659 m_log.Error(
3553 string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e); 3660 string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. 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 }
3554 } 3679 }
3555 } 3680 }
3556 3681
@@ -3609,11 +3734,9 @@ namespace OpenSim.Region.Framework.Scenes
3609 3734
3610 /// <summary> 3735 /// <summary>
3611 /// Do the work necessary to initiate a new user connection for a particular scene. 3736 /// 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.
3615 /// </summary> 3737 /// </summary>
3616 /// <param name="agent">CircuitData of the agent who is connecting</param> 3738 /// <param name="agent">CircuitData of the agent who is connecting</param>
3739 /// <param name="teleportFlags"></param>
3617 /// <param name="reason">Outputs the reason for the false response on this string</param> 3740 /// <param name="reason">Outputs the reason for the false response on this string</param>
3618 /// <returns>True if the region accepts this agent. False if it does not. False will 3741 /// <returns>True if the region accepts this agent. False if it does not. False will
3619 /// also return a reason.</returns> 3742 /// also return a reason.</returns>
@@ -3624,10 +3747,20 @@ namespace OpenSim.Region.Framework.Scenes
3624 3747
3625 /// <summary> 3748 /// <summary>
3626 /// Do the work necessary to initiate a new user connection for a particular scene. 3749 /// Do the work necessary to initiate a new user connection for a particular scene.
3627 /// At the moment, this consists of setting up the caps infrastructure 3750 /// </summary>
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
3628 /// The return bool should allow for connections to be refused, but as not all calling paths 3756 /// The return bool should allow for connections to be refused, but as not all calling paths
3629 /// take proper notice of it let, we allowed banned users in still. 3757 /// take proper notice of it let, we allowed banned users in still.
3630 /// </summary> 3758 ///
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>
3631 /// <param name="agent">CircuitData of the agent who is connecting</param> 3764 /// <param name="agent">CircuitData of the agent who is connecting</param>
3632 /// <param name="reason">Outputs the reason for the false response on this string</param> 3765 /// <param name="reason">Outputs the reason for the false response on this string</param>
3633 /// <param name="requirePresenceLookup">True for normal presence. False for NPC 3766 /// <param name="requirePresenceLookup">True for normal presence. False for NPC
@@ -3726,83 +3859,86 @@ namespace OpenSim.Region.Framework.Scenes
3726 "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", 3859 "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.",
3727 sp.Name, sp.UUID, RegionInfo.RegionName); 3860 sp.Name, sp.UUID, RegionInfo.RegionName);
3728 3861
3729 sp.ControllingClient.Close(); 3862 sp.ControllingClient.Close(true, true);
3730 sp = null; 3863 sp = null;
3731 } 3864 }
3732 3865
3733 3866 lock (agent)
3734 //On login test land permisions
3735 if (vialogin)
3736 { 3867 {
3737 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>(); 3868 //On login test land permisions
3738 if (cache != null) 3869 if (vialogin)
3739 cache.Remove(agent.firstname + " " + agent.lastname);
3740 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y))
3741 { 3870 {
3742 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString()); 3871 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3743 return false; 3872 if (cache != null)
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 }
3744 } 3879 }
3745 }
3746 3880
3747 if (sp == null) // We don't have an [child] agent here already 3881 if (sp == null) // We don't have an [child] agent here already
3748 {
3749 if (requirePresenceLookup)
3750 { 3882 {
3751 try 3883 if (requirePresenceLookup)
3752 { 3884 {
3753 if (!VerifyUserPresence(agent, out reason)) 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);
3754 return false; 3893 return false;
3755 } catch (Exception e) 3894 }
3895 }
3896
3897 try
3898 {
3899 // Always check estate if this is a login. Always
3900 // check if banned regions are to be blacked out.
3901 if (vialogin || (!m_seeIntoBannedRegion))
3902 {
3903 if (!AuthorizeUser(agent, out reason))
3904 return false;
3905 }
3906 }
3907 catch (Exception e)
3756 { 3908 {
3757 m_log.ErrorFormat( 3909 m_log.ErrorFormat(
3758 "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); 3910 "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace);
3759 return false; 3911 return false;
3760 } 3912 }
3761 }
3762 3913
3763 try 3914 m_log.InfoFormat(
3764 { 3915 "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})",
3765 // Always check estate if this is a login. Always 3916 RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname,
3766 // check if banned regions are to be blacked out. 3917 agent.AgentID, agent.circuitcode);
3767 if (vialogin || (!m_seeIntoBannedRegion)) 3918
3919 if (CapsModule != null)
3768 { 3920 {
3769 if (!AuthorizeUser(agent, out reason)) 3921 CapsModule.SetAgentCapsSeeds(agent);
3770 return false; 3922 CapsModule.CreateCaps(agent.AgentID);
3771 } 3923 }
3772 } 3924 }
3773 catch (Exception e) 3925 else
3774 { 3926 {
3775 m_log.ErrorFormat( 3927 // Let the SP know how we got here. This has a lot of interesting
3776 "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); 3928 // uses down the line.
3777 return false; 3929 sp.TeleportFlags = (TPFlags)teleportFlags;
3778 }
3779
3780 m_log.InfoFormat(
3781 "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})",
3782 RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname,
3783 agent.AgentID, agent.circuitcode);
3784 3930
3785 if (CapsModule != null) 3931 if (sp.IsChildAgent)
3786 { 3932 {
3787 CapsModule.SetAgentCapsSeeds(agent); 3933 m_log.DebugFormat(
3788 CapsModule.CreateCaps(agent.AgentID); 3934 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}",
3789 } 3935 agent.AgentID, RegionInfo.RegionName);
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;
3795 3936
3796 if (sp.IsChildAgent) 3937 sp.AdjustKnownSeeds();
3797 {
3798 m_log.DebugFormat(
3799 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}",
3800 agent.AgentID, RegionInfo.RegionName);
3801 3938
3802 sp.AdjustKnownSeeds(); 3939 if (CapsModule != null)
3803 3940 CapsModule.SetAgentCapsSeeds(agent);
3804 if (CapsModule != null) 3941 }
3805 CapsModule.SetAgentCapsSeeds(agent);
3806 } 3942 }
3807 } 3943 }
3808 3944
@@ -4233,8 +4369,9 @@ namespace OpenSim.Region.Framework.Scenes
4233 return false; 4369 return false;
4234 } 4370 }
4235 4371
4236 // We have to wait until the viewer contacts this region after receiving EAC. 4372 // We have to wait until the viewer contacts this region
4237 // That calls AddNewClient, which finally creates the ScenePresence 4373 // after receiving the EnableSimulator HTTP Event Queue message. This triggers the viewer to send
4374 // a UseCircuitCode packet which in turn calls AddNewClient which finally creates the ScenePresence.
4238 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); 4375 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID);
4239 4376
4240 if (childAgentUpdate != null) 4377 if (childAgentUpdate != null)
@@ -4329,15 +4466,18 @@ namespace OpenSim.Region.Framework.Scenes
4329 /// Tell a single agent to disconnect from the region. 4466 /// Tell a single agent to disconnect from the region.
4330 /// </summary> 4467 /// </summary>
4331 /// <param name="agentID"></param> 4468 /// <param name="agentID"></param>
4332 /// <param name="childOnly"></param> 4469 /// <param name="force">
4333 public bool IncomingCloseAgent(UUID agentID, bool childOnly) 4470 /// Force the agent to close even if it might be in the middle of some other operation. You do not want to
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)
4334 { 4474 {
4335 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 4475 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
4336 4476
4337 ScenePresence presence = m_sceneGraph.GetScenePresence(agentID); 4477 ScenePresence presence = m_sceneGraph.GetScenePresence(agentID);
4338 if (presence != null) 4478 if (presence != null)
4339 { 4479 {
4340 presence.ControllingClient.Close(false); 4480 presence.ControllingClient.Close(force, force);
4341 return true; 4481 return true;
4342 } 4482 }
4343 4483
@@ -4543,6 +4683,16 @@ namespace OpenSim.Region.Framework.Scenes
4543 return LandChannel.GetLandObject(x, y).LandData; 4683 return LandChannel.GetLandObject(x, y).LandData;
4544 } 4684 }
4545 4685
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
4546 public LandData GetLandData(uint x, uint y) 4696 public LandData GetLandData(uint x, uint y)
4547 { 4697 {
4548 m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y); 4698 m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y);
@@ -4773,13 +4923,24 @@ namespace OpenSim.Region.Framework.Scenes
4773 /// Get a group via its UUID 4923 /// Get a group via its UUID
4774 /// </summary> 4924 /// </summary>
4775 /// <param name="fullID"></param> 4925 /// <param name="fullID"></param>
4776 /// <returns>null if no group with that name exists</returns> 4926 /// <returns>null if no group with that id exists</returns>
4777 public SceneObjectGroup GetSceneObjectGroup(UUID fullID) 4927 public SceneObjectGroup GetSceneObjectGroup(UUID fullID)
4778 { 4928 {
4779 return m_sceneGraph.GetSceneObjectGroup(fullID); 4929 return m_sceneGraph.GetSceneObjectGroup(fullID);
4780 } 4930 }
4781 4931
4782 /// <summary> 4932 /// <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>
4783 /// Get a group by name from the scene (will return the first 4944 /// Get a group by name from the scene (will return the first
4784 /// found, if there are more than one prim with the same name) 4945 /// found, if there are more than one prim with the same name)
4785 /// </summary> 4946 /// </summary>
@@ -4791,6 +4952,18 @@ namespace OpenSim.Region.Framework.Scenes
4791 } 4952 }
4792 4953
4793 /// <summary> 4954 /// <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>
4794 /// Get a prim by name from the scene (will return the first 4967 /// Get a prim by name from the scene (will return the first
4795 /// found, if there are more than one prim with the same name) 4968 /// found, if there are more than one prim with the same name)
4796 /// </summary> 4969 /// </summary>
@@ -4822,6 +4995,18 @@ namespace OpenSim.Region.Framework.Scenes
4822 } 4995 }
4823 4996
4824 /// <summary> 4997 /// <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>
4825 /// Get a scene object group that contains the prim with the given local id 5010 /// Get a scene object group that contains the prim with the given local id
4826 /// </summary> 5011 /// </summary>
4827 /// <param name="localID"></param> 5012 /// <param name="localID"></param>
@@ -4915,14 +5100,15 @@ namespace OpenSim.Region.Framework.Scenes
4915 client.SendRegionHandle(regionID, handle); 5100 client.SendRegionHandle(regionID, handle);
4916 } 5101 }
4917 5102
4918 public bool NeedSceneCacheClear(UUID agentID) 5103// Commented pending deletion since this method no longer appears to do anything at all
4919 { 5104// public bool NeedSceneCacheClear(UUID agentID)
4920 IInventoryTransferModule inv = RequestModuleInterface<IInventoryTransferModule>(); 5105// {
4921 if (inv == null) 5106// IInventoryTransferModule inv = RequestModuleInterface<IInventoryTransferModule>();
4922 return true; 5107// if (inv == null)
4923 5108// return true;
4924 return inv.NeedSceneCacheClear(agentID, this); 5109//
4925 } 5110// return inv.NeedSceneCacheClear(agentID, this);
5111// }
4926 5112
4927 public void CleanTempObjects() 5113 public void CleanTempObjects()
4928 { 5114 {
@@ -5876,6 +6062,9 @@ Environment.Exit(1);
5876 6062
5877 public string GetExtraSetting(string name) 6063 public string GetExtraSetting(string name)
5878 { 6064 {
6065 if (m_extraSettings == null)
6066 return String.Empty;
6067
5879 string val; 6068 string val;
5880 6069
5881 if (!m_extraSettings.TryGetValue(name, out val)) 6070 if (!m_extraSettings.TryGetValue(name, out val))
@@ -5886,6 +6075,9 @@ Environment.Exit(1);
5886 6075
5887 public void StoreExtraSetting(string name, string val) 6076 public void StoreExtraSetting(string name, string val)
5888 { 6077 {
6078 if (m_extraSettings == null)
6079 return;
6080
5889 string oldVal; 6081 string oldVal;
5890 6082
5891 if (m_extraSettings.TryGetValue(name, out oldVal)) 6083 if (m_extraSettings.TryGetValue(name, out oldVal))
@@ -5903,6 +6095,9 @@ Environment.Exit(1);
5903 6095
5904 public void RemoveExtraSetting(string name) 6096 public void RemoveExtraSetting(string name)
5905 { 6097 {
6098 if (m_extraSettings == null)
6099 return;
6100
5906 if (!m_extraSettings.ContainsKey(name)) 6101 if (!m_extraSettings.ContainsKey(name))
5907 return; 6102 return;
5908 6103
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index af13b46..e599e90 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, true, false); 345 AddNewSceneObject(sceneObject, attachToBackup, false);
346 346
347 if (pos != null) 347 if (pos != null)
348 sceneObject.AbsolutePosition = (Vector3)pos; 348 sceneObject.AbsolutePosition = (Vector3)pos;
@@ -421,12 +421,9 @@ namespace OpenSim.Region.Framework.Scenes
421 { 421 {
422 Vector3 scale = part.Shape.Scale; 422 Vector3 scale = part.Shape.Scale;
423 423
424 if (scale.X > m_parentScene.m_maxNonphys) 424 scale.X = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.X));
425 scale.X = m_parentScene.m_maxNonphys; 425 scale.Y = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Y));
426 if (scale.Y > m_parentScene.m_maxNonphys) 426 scale.Z = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Z));
427 scale.Y = m_parentScene.m_maxNonphys;
428 if (scale.Z > m_parentScene.m_maxNonphys)
429 scale.Z = m_parentScene.m_maxNonphys;
430 427
431 part.Shape.Scale = scale; 428 part.Shape.Scale = scale;
432 } 429 }
@@ -1066,6 +1063,30 @@ namespace OpenSim.Region.Framework.Scenes
1066 } 1063 }
1067 1064
1068 /// <summary> 1065 /// <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>
1069 /// Get a group by name from the scene (will return the first 1090 /// Get a group by name from the scene (will return the first
1070 /// found, if there are more than one prim with the same name) 1091 /// found, if there are more than one prim with the same name)
1071 /// </summary> 1092 /// </summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs
index f1b09ca..dba3a61 100644
--- a/OpenSim/Region/Framework/Scenes/SceneManager.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs
@@ -92,7 +92,11 @@ 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 { return m_instance; } 95 get {
96 if (m_instance == null)
97 m_instance = new SceneManager();
98 return m_instance;
99 }
96 } 100 }
97 101
98 private readonly DoubleDictionary<UUID, string, Scene> m_localScenes = new DoubleDictionary<UUID, string, Scene>(); 102 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 ee61de6..74d2629 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -2747,6 +2747,25 @@ 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
2750 // 'linkPart' == the root of the group being linked into this group 2769 // 'linkPart' == the root of the group being linked into this group
2751 SceneObjectPart linkPart = objectGroup.m_rootPart; 2770 SceneObjectPart linkPart = objectGroup.m_rootPart;
2752 2771
@@ -3492,27 +3511,33 @@ namespace OpenSim.Region.Framework.Scenes
3492 /// <param name="scale"></param> 3511 /// <param name="scale"></param>
3493 public void GroupResize(Vector3 scale) 3512 public void GroupResize(Vector3 scale)
3494 { 3513 {
3495 scale.X = Math.Min(scale.X, Scene.m_maxNonphys); 3514// m_log.DebugFormat(
3496 scale.Y = Math.Min(scale.Y, Scene.m_maxNonphys); 3515// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale);
3497 scale.Z = Math.Min(scale.Z, Scene.m_maxNonphys);
3498 3516
3499 PhysicsActor pa = m_rootPart.PhysActor; 3517 PhysicsActor pa = m_rootPart.PhysActor;
3500 3518
3501 if (pa != null && pa.IsPhysical) 3519 if (Scene != null)
3502 { 3520 {
3503 scale.X = Math.Min(scale.X, Scene.m_maxPhys); 3521 scale.X = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.X));
3504 scale.Y = Math.Min(scale.Y, Scene.m_maxPhys); 3522 scale.Y = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Y));
3505 scale.Z = Math.Min(scale.Z, Scene.m_maxPhys); 3523 scale.Z = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Z));
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 }
3506 } 3531 }
3507 3532
3508 float x = (scale.X / RootPart.Scale.X); 3533 float x = (scale.X / RootPart.Scale.X);
3509 float y = (scale.Y / RootPart.Scale.Y); 3534 float y = (scale.Y / RootPart.Scale.Y);
3510 float z = (scale.Z / RootPart.Scale.Z); 3535 float z = (scale.Z / RootPart.Scale.Z);
3511 3536
3512 SceneObjectPart[] parts; 3537 SceneObjectPart[] parts = m_parts.GetArray();
3513 if (x > 1.0f || y > 1.0f || z > 1.0f) 3538
3539 if (Scene != null & (x > 1.0f || y > 1.0f || z > 1.0f))
3514 { 3540 {
3515 parts = m_parts.GetArray();
3516 for (int i = 0; i < parts.Length; i++) 3541 for (int i = 0; i < parts.Length; i++)
3517 { 3542 {
3518 SceneObjectPart obPart = parts[i]; 3543 SceneObjectPart obPart = parts[i];
@@ -3525,7 +3550,7 @@ namespace OpenSim.Region.Framework.Scenes
3525 3550
3526 if (pa != null && pa.IsPhysical) 3551 if (pa != null && pa.IsPhysical)
3527 { 3552 {
3528 if (oldSize.X * x > m_scene.m_maxPhys) 3553 if (oldSize.X * x > Scene.m_maxPhys)
3529 { 3554 {
3530 f = m_scene.m_maxPhys / oldSize.X; 3555 f = m_scene.m_maxPhys / oldSize.X;
3531 a = f / x; 3556 a = f / x;
@@ -3533,8 +3558,16 @@ namespace OpenSim.Region.Framework.Scenes
3533 y *= a; 3558 y *= a;
3534 z *= a; 3559 z *= a;
3535 } 3560 }
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 }
3536 3569
3537 if (oldSize.Y * y > m_scene.m_maxPhys) 3570 if (oldSize.Y * y > Scene.m_maxPhys)
3538 { 3571 {
3539 f = m_scene.m_maxPhys / oldSize.Y; 3572 f = m_scene.m_maxPhys / oldSize.Y;
3540 a = f / y; 3573 a = f / y;
@@ -3542,8 +3575,16 @@ namespace OpenSim.Region.Framework.Scenes
3542 y *= a; 3575 y *= a;
3543 z *= a; 3576 z *= a;
3544 } 3577 }
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 }
3545 3586
3546 if (oldSize.Z * z > m_scene.m_maxPhys) 3587 if (oldSize.Z * z > Scene.m_maxPhys)
3547 { 3588 {
3548 f = m_scene.m_maxPhys / oldSize.Z; 3589 f = m_scene.m_maxPhys / oldSize.Z;
3549 a = f / z; 3590 a = f / z;
@@ -3551,10 +3592,18 @@ namespace OpenSim.Region.Framework.Scenes
3551 y *= a; 3592 y *= a;
3552 z *= a; 3593 z *= a;
3553 } 3594 }
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 }
3554 } 3603 }
3555 else 3604 else
3556 { 3605 {
3557 if (oldSize.X * x > m_scene.m_maxNonphys) 3606 if (oldSize.X * x > Scene.m_maxNonphys)
3558 { 3607 {
3559 f = m_scene.m_maxNonphys / oldSize.X; 3608 f = m_scene.m_maxNonphys / oldSize.X;
3560 a = f / x; 3609 a = f / x;
@@ -3562,8 +3611,16 @@ namespace OpenSim.Region.Framework.Scenes
3562 y *= a; 3611 y *= a;
3563 z *= a; 3612 z *= a;
3564 } 3613 }
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 }
3565 3622
3566 if (oldSize.Y * y > m_scene.m_maxNonphys) 3623 if (oldSize.Y * y > Scene.m_maxNonphys)
3567 { 3624 {
3568 f = m_scene.m_maxNonphys / oldSize.Y; 3625 f = m_scene.m_maxNonphys / oldSize.Y;
3569 a = f / y; 3626 a = f / y;
@@ -3571,8 +3628,16 @@ namespace OpenSim.Region.Framework.Scenes
3571 y *= a; 3628 y *= a;
3572 z *= a; 3629 z *= a;
3573 } 3630 }
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 }
3574 3639
3575 if (oldSize.Z * z > m_scene.m_maxNonphys) 3640 if (oldSize.Z * z > Scene.m_maxNonphys)
3576 { 3641 {
3577 f = m_scene.m_maxNonphys / oldSize.Z; 3642 f = m_scene.m_maxNonphys / oldSize.Z;
3578 a = f / z; 3643 a = f / z;
@@ -3580,6 +3645,14 @@ namespace OpenSim.Region.Framework.Scenes
3580 y *= a; 3645 y *= a;
3581 z *= a; 3646 z *= a;
3582 } 3647 }
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 }
3583 } 3656 }
3584 } 3657 }
3585 } 3658 }
@@ -3592,7 +3665,6 @@ namespace OpenSim.Region.Framework.Scenes
3592 3665
3593 RootPart.Resize(prevScale); 3666 RootPart.Resize(prevScale);
3594 3667
3595 parts = m_parts.GetArray();
3596 for (int i = 0; i < parts.Length; i++) 3668 for (int i = 0; i < parts.Length; i++)
3597 { 3669 {
3598 SceneObjectPart obPart = parts[i]; 3670 SceneObjectPart obPart = parts[i];
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 165dd85..2191cfa 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.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message); 793 m_log.ErrorFormat("[SCENEOBJECTPART]: GROUP POSITION. {0}", e);
794 } 794 }
795 } 795 }
796 } 796 }
@@ -2864,6 +2864,35 @@ 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
2867 public void PhysicsOutOfBounds(Vector3 pos) 2896 public void PhysicsOutOfBounds(Vector3 pos)
2868 { 2897 {
2869 m_log.Error("[PHYSICS]: Physical Object went out of bounds."); 2898 m_log.Error("[PHYSICS]: Physical Object went out of bounds.");
@@ -2895,38 +2924,6 @@ namespace OpenSim.Region.Framework.Scenes
2895 ScheduleTerseUpdate(); 2924 ScheduleTerseUpdate();
2896 } 2925 }
2897 2926
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
2930 public void RemFlag(PrimFlags flag) 2927 public void RemFlag(PrimFlags flag)
2931 { 2928 {
2932 // PrimFlags prevflag = Flags; 2929 // PrimFlags prevflag = Flags;
@@ -2979,17 +2976,20 @@ namespace OpenSim.Region.Framework.Scenes
2979 /// <param name="scale"></param> 2976 /// <param name="scale"></param>
2980 public void Resize(Vector3 scale) 2977 public void Resize(Vector3 scale)
2981 { 2978 {
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
2986 PhysicsActor pa = PhysActor; 2979 PhysicsActor pa = PhysActor;
2987 2980
2988 if (pa != null && pa.IsPhysical) 2981 if (ParentGroup.Scene != null)
2989 { 2982 {
2990 scale.X = Math.Min(scale.X, ParentGroup.Scene.m_maxPhys); 2983 scale.X = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.X));
2991 scale.Y = Math.Min(scale.Y, ParentGroup.Scene.m_maxPhys); 2984 scale.Y = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Y));
2992 scale.Z = Math.Min(scale.Z, ParentGroup.Scene.m_maxPhys); 2985 scale.Z = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Z));
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); 3089 ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, true);
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); 3123 ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, false);
3124 } 3124 }
3125 3125
3126 public void ScriptSetPhysicsStatus(bool UsePhysics) 3126 public void ScriptSetPhysicsStatus(bool UsePhysics)
@@ -3295,126 +3295,6 @@ 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>
3418 /// Send a terse update to all clients 3298 /// Send a terse update to all clients
3419 /// </summary> 3299 /// </summary>
3420 public void SendTerseUpdateToAllClients() 3300 public void SendTerseUpdateToAllClients()
@@ -3575,23 +3455,32 @@ namespace OpenSim.Region.Framework.Scenes
3575 } 3455 }
3576 3456
3577 /// <summary> 3457 /// <summary>
3578 /// Set the color of prim faces 3458 /// Set the color & alpha of prim faces
3579 /// </summary> 3459 /// </summary>
3580 /// <param name="color"></param>
3581 /// <param name="face"></param> 3460 /// <param name="face"></param>
3582 public void SetFaceColor(Vector3 color, int face) 3461 /// <param name="color"></param>
3462 /// <param name="alpha"></param>
3463 public void SetFaceColorAlpha(int face, Vector3 color, double ?alpha)
3583 { 3464 {
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
3584 // The only way to get a deep copy/ If we don't do this, we can 3469 // The only way to get a deep copy/ If we don't do this, we can
3585 // mever detect color changes further down. 3470 // never detect color changes further down.
3586 Byte[] buf = Shape.Textures.GetBytes(); 3471 Byte[] buf = Shape.Textures.GetBytes();
3587 Primitive.TextureEntry tex = new Primitive.TextureEntry(buf, 0, buf.Length); 3472 Primitive.TextureEntry tex = new Primitive.TextureEntry(buf, 0, buf.Length);
3588 Color4 texcolor; 3473 Color4 texcolor;
3589 if (face >= 0 && face < GetNumberOfSides()) 3474 if (face >= 0 && face < GetNumberOfSides())
3590 { 3475 {
3591 texcolor = tex.CreateFace((uint)face).RGBA; 3476 texcolor = tex.CreateFace((uint)face).RGBA;
3592 texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f); 3477 texcolor.R = clippedColor.X;
3593 texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f); 3478 texcolor.G = clippedColor.Y;
3594 texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f); 3479 texcolor.B = clippedColor.Z;
3480 if (alpha.HasValue)
3481 {
3482 texcolor.A = clippedAlpha;
3483 }
3595 tex.FaceTextures[face].RGBA = texcolor; 3484 tex.FaceTextures[face].RGBA = texcolor;
3596 UpdateTextureEntry(tex.GetBytes()); 3485 UpdateTextureEntry(tex.GetBytes());
3597 return; 3486 return;
@@ -3603,15 +3492,23 @@ namespace OpenSim.Region.Framework.Scenes
3603 if (tex.FaceTextures[i] != null) 3492 if (tex.FaceTextures[i] != null)
3604 { 3493 {
3605 texcolor = tex.FaceTextures[i].RGBA; 3494 texcolor = tex.FaceTextures[i].RGBA;
3606 texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f); 3495 texcolor.R = clippedColor.X;
3607 texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f); 3496 texcolor.G = clippedColor.Y;
3608 texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f); 3497 texcolor.B = clippedColor.Z;
3498 if (alpha.HasValue)
3499 {
3500 texcolor.A = clippedAlpha;
3501 }
3609 tex.FaceTextures[i].RGBA = texcolor; 3502 tex.FaceTextures[i].RGBA = texcolor;
3610 } 3503 }
3611 texcolor = tex.DefaultTexture.RGBA; 3504 texcolor = tex.DefaultTexture.RGBA;
3612 texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f); 3505 texcolor.R = clippedColor.X;
3613 texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f); 3506 texcolor.G = clippedColor.Y;
3614 texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f); 3507 texcolor.B = clippedColor.Z;
3508 if (alpha.HasValue)
3509 {
3510 texcolor.A = clippedAlpha;
3511 }
3615 tex.DefaultTexture.RGBA = texcolor; 3512 tex.DefaultTexture.RGBA = texcolor;
3616 } 3513 }
3617 UpdateTextureEntry(tex.GetBytes()); 3514 UpdateTextureEntry(tex.GetBytes());
@@ -4899,6 +4796,57 @@ namespace OpenSim.Region.Framework.Scenes
4899 ScheduleFullUpdate(); 4796 ScheduleFullUpdate();
4900 } 4797 }
4901 4798
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
4902 /// <summary> 4850 /// <summary>
4903 /// If the part is a sculpt/mesh, retrieve the mesh data and reinsert it into the shape so that the physics 4851 /// If the part is a sculpt/mesh, retrieve the mesh data and reinsert it into the shape so that the physics
4904 /// engine can use it. 4852 /// engine can use it.
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index e010864..3a9a146 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -97,6 +97,15 @@ 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 }
100 109
101 /// <summary> 110 /// <summary>
102 /// Constructor 111 /// Constructor
@@ -235,31 +244,52 @@ namespace OpenSim.Region.Framework.Scenes
235 if (m_part == null || m_part.ParentGroup == null || m_part.ParentGroup.Scene == null) 244 if (m_part == null || m_part.ParentGroup == null || m_part.ParentGroup.Scene == null)
236 return; 245 return;
237 246
238 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
239 if (engines == null) // No engine at all
240 return;
241
242 Items.LockItemsForRead(true); 247 Items.LockItemsForRead(true);
243 foreach (TaskInventoryItem item in Items.Values) 248 foreach (TaskInventoryItem item in Items.Values)
244 { 249 {
245 if (item.InvType == (int)InventoryType.LSL) 250 if (item.InvType == (int)InventoryType.LSL)
246 { 251 {
247 foreach (IScriptModule e in engines) 252 bool running;
248 { 253 if (TryGetScriptInstanceRunning(m_part.ParentGroup.Scene, item, out running))
249 bool running; 254 item.ScriptRunning = running;
250
251 if (e.HasScript(item.ItemID, out running))
252 {
253 item.ScriptRunning = running;
254 break;
255 }
256 }
257 } 255 }
258 } 256 }
259 257
260 Items.LockItemsForRead(false); 258 Items.LockItemsForRead(false);
261 } 259 }
262 260
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
263 public int CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) 293 public int CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource)
264 { 294 {
265 int scriptsValidForStarting = 0; 295 int scriptsValidForStarting = 0;
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index a8aa551..2c18397 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,14 +69,15 @@ namespace OpenSim.Region.Framework.Scenes
69 public ScriptControlled eventControls; 69 public ScriptControlled eventControls;
70 } 70 }
71 71
72 public delegate void SendCourseLocationsMethod(UUID scene, ScenePresence presence, List<Vector3> coarseLocations, List<UUID> avatarUUIDs); 72 public delegate void SendCoarseLocationsMethod(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.Debug("[SCENE PRESENCE] Destructor called"); 78// m_log.DebugFormat("[SCENE PRESENCE]: Destructor called on {0}", Name);
79// } 79// }
80
80 private void TriggerScenePresenceUpdated() 81 private void TriggerScenePresenceUpdated()
81 { 82 {
82 if (m_scene != null) 83 if (m_scene != null)
@@ -188,7 +189,7 @@ namespace OpenSim.Region.Framework.Scenes
188 /// </summary> 189 /// </summary>
189 public bool SitGround { get; private set; } 190 public bool SitGround { get; private set; }
190 191
191 private SendCourseLocationsMethod m_sendCourseLocationsMethod; 192 private SendCoarseLocationsMethod m_sendCoarseLocationsMethod;
192 193
193 //private Vector3 m_requestedSitOffset = new Vector3(); 194 //private Vector3 m_requestedSitOffset = new Vector3();
194 195
@@ -546,7 +547,7 @@ namespace OpenSim.Region.Framework.Scenes
546 { 547 {
547 try 548 try
548 { 549 {
549 PhysicsActor.Velocity = value; 550 PhysicsActor.TargetVelocity = value;
550 } 551 }
551 catch (Exception e) 552 catch (Exception e)
552 { 553 {
@@ -711,7 +712,7 @@ namespace OpenSim.Region.Framework.Scenes
711 AttachmentsSyncLock = new Object(); 712 AttachmentsSyncLock = new Object();
712 AllowMovement = true; 713 AllowMovement = true;
713 IsChildAgent = true; 714 IsChildAgent = true;
714 m_sendCourseLocationsMethod = SendCoarseLocationsDefault; 715 m_sendCoarseLocationsMethod = SendCoarseLocationsDefault;
715 Animator = new ScenePresenceAnimator(this); 716 Animator = new ScenePresenceAnimator(this);
716 PresenceType = type; 717 PresenceType = type;
717 DrawDistance = world.DefaultDrawDistance; 718 DrawDistance = world.DefaultDrawDistance;
@@ -974,7 +975,9 @@ namespace OpenSim.Region.Framework.Scenes
974 { 975 {
975 if (wasChild && HasAttachments()) 976 if (wasChild && HasAttachments())
976 { 977 {
977 m_log.DebugFormat("[SCENE PRESENCE]: Restarting scripts in attachments..."); 978 m_log.DebugFormat(
979 "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name);
980
978 // Resume scripts 981 // Resume scripts
979 Util.FireAndForget(delegate(object x) { 982 Util.FireAndForget(delegate(object x) {
980 foreach (SceneObjectGroup sog in m_attachments) 983 foreach (SceneObjectGroup sog in m_attachments)
@@ -1530,17 +1533,22 @@ namespace OpenSim.Region.Framework.Scenes
1530 bool DCFlagKeyPressed = false; 1533 bool DCFlagKeyPressed = false;
1531 Vector3 agent_control_v3 = Vector3.Zero; 1534 Vector3 agent_control_v3 = Vector3.Zero;
1532 1535
1533 bool oldflying = Flying; 1536 bool newFlying = actor.Flying;
1534 1537
1535 if (ForceFly) 1538 if (ForceFly)
1536 actor.Flying = true; 1539 newFlying = true;
1537 else if (FlyDisabled) 1540 else if (FlyDisabled)
1538 actor.Flying = false; 1541 newFlying = false;
1539 else 1542 else
1540 actor.Flying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); 1543 newFlying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
1541 1544
1542 if (actor.Flying != oldflying) 1545 if (actor.Flying != newFlying)
1546 {
1547 // Note: ScenePresence.Flying is actually fetched from the physical actor
1548 // so setting PhysActor.Flying here also sets the ScenePresence's value.
1549 actor.Flying = newFlying;
1543 update_movementflag = true; 1550 update_movementflag = true;
1551 }
1544 1552
1545 if (ParentID == 0) 1553 if (ParentID == 0)
1546 { 1554 {
@@ -2622,17 +2630,17 @@ namespace OpenSim.Region.Framework.Scenes
2622 2630
2623 public void SendCoarseLocations(List<Vector3> coarseLocations, List<UUID> avatarUUIDs) 2631 public void SendCoarseLocations(List<Vector3> coarseLocations, List<UUID> avatarUUIDs)
2624 { 2632 {
2625 SendCourseLocationsMethod d = m_sendCourseLocationsMethod; 2633 SendCoarseLocationsMethod d = m_sendCoarseLocationsMethod;
2626 if (d != null) 2634 if (d != null)
2627 { 2635 {
2628 d.Invoke(m_scene.RegionInfo.originRegionID, this, coarseLocations, avatarUUIDs); 2636 d.Invoke(m_scene.RegionInfo.originRegionID, this, coarseLocations, avatarUUIDs);
2629 } 2637 }
2630 } 2638 }
2631 2639
2632 public void SetSendCourseLocationMethod(SendCourseLocationsMethod d) 2640 public void SetSendCoarseLocationMethod(SendCoarseLocationsMethod d)
2633 { 2641 {
2634 if (d != null) 2642 if (d != null)
2635 m_sendCourseLocationsMethod = d; 2643 m_sendCoarseLocationsMethod = d;
2636 } 2644 }
2637 2645
2638 public void SendCoarseLocationsDefault(UUID sceneId, ScenePresence p, List<Vector3> coarseLocations, List<UUID> avatarUUIDs) 2646 public void SendCoarseLocationsDefault(UUID sceneId, ScenePresence p, List<Vector3> coarseLocations, List<UUID> avatarUUIDs)
@@ -2836,7 +2844,7 @@ namespace OpenSim.Region.Framework.Scenes
2836 #region Significant Movement Method 2844 #region Significant Movement Method
2837 2845
2838 /// <summary> 2846 /// <summary>
2839 /// This checks for a significant movement and sends a courselocationchange update 2847 /// This checks for a significant movement and sends a coarselocationchange update
2840 /// </summary> 2848 /// </summary>
2841 protected void CheckForSignificantMovement() 2849 protected void CheckForSignificantMovement()
2842 { 2850 {
@@ -3269,6 +3277,7 @@ namespace OpenSim.Region.Framework.Scenes
3269 } 3277 }
3270 catch { } 3278 catch { }
3271 cAgent.DefaultAnim = Animator.Animations.DefaultAnimation; 3279 cAgent.DefaultAnim = Animator.Animations.DefaultAnimation;
3280 cAgent.AnimState = Animator.Animations.ImplicitDefaultAnimation;
3272 3281
3273 if (Scene.AttachmentsModule != null) 3282 if (Scene.AttachmentsModule != null)
3274 Scene.AttachmentsModule.CopyAttachments(this, cAgent); 3283 Scene.AttachmentsModule.CopyAttachments(this, cAgent);
@@ -3345,6 +3354,8 @@ namespace OpenSim.Region.Framework.Scenes
3345 Animator.Animations.FromArray(cAgent.Anims); 3354 Animator.Animations.FromArray(cAgent.Anims);
3346 if (cAgent.DefaultAnim != null) 3355 if (cAgent.DefaultAnim != null)
3347 Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero); 3356 Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero);
3357 if (cAgent.AnimState != null)
3358 Animator.Animations.SetImplicitDefaultAnimation(cAgent.AnimState.AnimID, cAgent.AnimState.SequenceNum, UUID.Zero);
3348 3359
3349 if (Scene.AttachmentsModule != null) 3360 if (Scene.AttachmentsModule != null)
3350 Scene.AttachmentsModule.CopyAttachments(cAgent, this); 3361 Scene.AttachmentsModule.CopyAttachments(cAgent, this);
@@ -3627,13 +3638,16 @@ namespace OpenSim.Region.Framework.Scenes
3627 public List<SceneObjectGroup> GetAttachments(uint attachmentPoint) 3638 public List<SceneObjectGroup> GetAttachments(uint attachmentPoint)
3628 { 3639 {
3629 List<SceneObjectGroup> attachments = new List<SceneObjectGroup>(); 3640 List<SceneObjectGroup> attachments = new List<SceneObjectGroup>();
3630 3641
3631 lock (m_attachments) 3642 if (attachmentPoint >= 0)
3632 { 3643 {
3633 foreach (SceneObjectGroup so in m_attachments) 3644 lock (m_attachments)
3634 { 3645 {
3635 if (attachmentPoint == so.AttachmentPoint) 3646 foreach (SceneObjectGroup so in m_attachments)
3636 attachments.Add(so); 3647 {
3648 if (attachmentPoint == so.AttachmentPoint)
3649 attachments.Add(so);
3650 }
3637 } 3651 }
3638 } 3652 }
3639 3653
diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
index 756b1f4..5398ab9 100644
--- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
+++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
@@ -47,6 +47,7 @@ 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";
50 51
51 public delegate void SendStatResult(SimStats stats); 52 public delegate void SendStatResult(SimStats stats);
52 53
@@ -129,6 +130,16 @@ namespace OpenSim.Region.Framework.Scenes
129 } 130 }
130 131
131 /// <summary> 132 /// <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>
132 /// Extra sim statistics that are used by monitors but not sent to the client. 143 /// Extra sim statistics that are used by monitors but not sent to the client.
133 /// </summary> 144 /// </summary>
134 /// <value> 145 /// <value>
@@ -226,6 +237,24 @@ namespace OpenSim.Region.Framework.Scenes
226 237
227 if (StatsManager.SimExtraStats != null) 238 if (StatsManager.SimExtraStats != null)
228 OnSendStatsResult += StatsManager.SimExtraStats.ReceiveClassicSimStatsPacket; 239 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);
229 } 258 }
230 259
231 public void Close() 260 public void Close()
@@ -443,6 +472,7 @@ namespace OpenSim.Region.Framework.Scenes
443 lock (m_lastReportedExtraSimStats) 472 lock (m_lastReportedExtraSimStats)
444 { 473 {
445 m_lastReportedExtraSimStats[LastReportedObjectUpdateStatName] = m_objectUpdates / m_statsUpdateFactor; 474 m_lastReportedExtraSimStats[LastReportedObjectUpdateStatName] = m_objectUpdates / m_statsUpdateFactor;
475 m_lastReportedExtraSimStats[SlowFramesStat.ShortName] = (float)SlowFramesStat.Value;
446 476
447 Dictionary<string, float> physicsStats = m_scene.PhysicsScene.GetStats(); 477 Dictionary<string, float> physicsStats = m_scene.PhysicsScene.GetStats();
448 478
@@ -563,6 +593,11 @@ namespace OpenSim.Region.Framework.Scenes
563 public void addFrameMS(int ms) 593 public void addFrameMS(int ms)
564 { 594 {
565 m_frameMS += ms; 595 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++;
566 } 601 }
567 602
568 public void addNetMS(int ms) 603 public void addNetMS(int ms)
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
index 5758869..5faf131 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); 144 scene.IncomingCloseAgent(sp.UUID, false);
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 d722a09..ac3da1e 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs
@@ -65,5 +65,22 @@ 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 }
68 } 85 }
69} \ No newline at end of file 86} \ 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 44d2d45..9457ebb 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs
@@ -50,9 +50,41 @@ 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 53 public class UserInventoryTests : OpenSimTestCase
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]
56 public void TestGiveInventoryItem() 88 public void TestGiveInventoryItem()
57 { 89 {
58 TestHelpers.InMethod(); 90 TestHelpers.InMethod();
@@ -83,7 +115,7 @@ namespace OpenSim.Region.Framework.Tests
83 public void TestGiveInventoryFolder() 115 public void TestGiveInventoryFolder()
84 { 116 {
85 TestHelpers.InMethod(); 117 TestHelpers.InMethod();
86// log4net.Config.XmlConfigurator.Configure(); 118// TestHelpers.EnableLogging();
87 119
88 Scene scene = new SceneHelpers().SetupScene(); 120 Scene scene = new SceneHelpers().SetupScene();
89 UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001)); 121 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 411e421..2279e62 100644
--- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
+++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
@@ -52,26 +52,23 @@ 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;
66 55
67 /// <summary> 56 protected IAssetService m_assetService;
68 /// Signal whether we are currently waiting for the asset service to deliver an asset. 57
69 /// </summary> 58// /// <summary>
70 private bool m_waitingForObjectAsset; 59// /// Used as a temporary store of an asset which represents an object. This can be a null if no appropriate
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;
71 68
72 public UuidGatherer(IAssetService assetCache) 69 public UuidGatherer(IAssetService assetService)
73 { 70 {
74 m_assetCache = assetCache; 71 m_assetService = assetService;
75 } 72 }
76 73
77 /// <summary> 74 /// <summary>
@@ -191,18 +188,18 @@ namespace OpenSim.Region.Framework.Scenes
191 } 188 }
192 } 189 }
193 190
194 /// <summary> 191// /// <summary>
195 /// The callback made when we request the asset for an object from the asset service. 192// /// The callback made when we request the asset for an object from the asset service.
196 /// </summary> 193// /// </summary>
197 private void AssetReceived(string id, Object sender, AssetBase asset) 194// private void AssetReceived(string id, Object sender, AssetBase asset)
198 { 195// {
199 lock (this) 196// lock (this)
200 { 197// {
201 m_requestedObjectAsset = asset; 198// m_requestedObjectAsset = asset;
202 m_waitingForObjectAsset = false; 199// m_waitingForObjectAsset = false;
203 Monitor.Pulse(this); 200// Monitor.Pulse(this);
204 } 201// }
205 } 202// }
206 203
207 /// <summary> 204 /// <summary>
208 /// Get an asset synchronously, potentially using an asynchronous callback. If the 205 /// Get an asset synchronously, potentially using an asynchronous callback. If the
@@ -212,25 +209,29 @@ namespace OpenSim.Region.Framework.Scenes
212 /// <returns></returns> 209 /// <returns></returns>
213 protected virtual AssetBase GetAsset(UUID uuid) 210 protected virtual AssetBase GetAsset(UUID uuid)
214 { 211 {
215 m_waitingForObjectAsset = true; 212 return m_assetService.Get(uuid.ToString());
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 }
232 213
233 return m_requestedObjectAsset; 214 // XXX: Switching to do this synchronously where the call was async before but we always waited for it
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;
234 } 235 }
235 236
236 /// <summary> 237 /// <summary>
@@ -361,4 +362,47 @@ namespace OpenSim.Region.Framework.Scenes
361 } 362 }
362 } 363 }
363 } 364 }
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 }
364} 408}
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
index a484300..c363fd3 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
@@ -890,10 +890,10 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
890 890
891 public void Close() 891 public void Close()
892 { 892 {
893 Close(true); 893 Close(true, false);
894 } 894 }
895 895
896 public void Close(bool sendStop) 896 public void Close(bool sendStop, bool force)
897 { 897 {
898 Disconnect(); 898 Disconnect();
899 } 899 }
@@ -958,7 +958,8 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
958 958
959 } 959 }
960 960
961 public void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, byte source, byte audible) 961 public void SendChatMessage(
962 string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, UUID ownerID, byte source, byte audible)
962 { 963 {
963 if (audible > 0 && message.Length > 0) 964 if (audible > 0 && message.Length > 0)
964 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 41ec14f..7639c6c 100644
--- a/OpenSim/Region/OptionalModules/Asset/AssetInfoModule.cs
+++ b/OpenSim/Region/OptionalModules/Asset/AssetInfoModule.cs
@@ -127,6 +127,9 @@ 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;
130 133
131 using (FileStream fs = new FileStream(fileName, FileMode.CreateNew)) 134 using (FileStream fs = new FileStream(fileName, FileMode.CreateNew))
132 { 135 {
diff --git a/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs b/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs
index d68aabc..68bcb4a 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", 36)); 149 ct.Columns.Add(new ConsoleDisplayTableColumn("Attachment Name", 50));
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 31d0034..17971e3 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 void llAttachToAvatarTemp(UUID host, UUID script, int attachmentPoint) 133 private int 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; 138 return 0;
139 139
140 if (hostPart.ParentGroup.IsAttachment) 140 if (hostPart.ParentGroup.IsAttachment)
141 return; 141 return 0;
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; 145 return 0;
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; 149 return 0;
150 150
151 if ((item.PermsMask & 32) == 0) // PERMISSION_ATTACH 151 if ((item.PermsMask & 32) == 0) // PERMISSION_ATTACH
152 return; 152 return 0;
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; 156 return 0;
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; 163 return 0;
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 attachmentsModule.AttachObject(target, hostPart.ParentGroup, (uint)attachmentPoint, false, true, true); 186 return attachmentsModule.AttachObject(target, hostPart.ParentGroup, (uint)attachmentPoint, false, true, true) ? 1 : 0;
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 ca956fb..a014798 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 if randomizing is enabled 234 // Generate an initial nickname
235 235
236 if (m_randomizeNick) 236 if (m_randomizeNick)
237 {
238 m_nick = m_baseNick + Util.RandomClass.Next(1, 99); 237 m_nick = m_baseNick + Util.RandomClass.Next(1, 99);
239 } 238 else
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 e22618d..5c3be29 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs
@@ -546,8 +546,9 @@ 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(msg, (byte) ChatTypeEnum.Say, PosOfGod, m_whoami, UUID.Zero, 549 agent.ControllingClient.SendChatMessage(
550 (byte)ChatSourceType.Object, (byte)ChatAudibleLevel.Fully); 550 msg, (byte) ChatTypeEnum.Say, PosOfGod, m_whoami, UUID.Zero, UUID.Zero,
551 (byte)ChatSourceType.Object, (byte)ChatAudibleLevel.Fully);
551 } 552 }
552 553
553 private static void checkStringParameters(XmlRpcRequest request, string[] param) 554 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 7b20446..f292a75 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.X, avatar.AbsolutePosition.Y); 450 LandData land = scene.GetLandData(avatar.AbsolutePosition);
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 a30a38d..8a8a31c 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.X, avatar.AbsolutePosition.Y); 626 LandData land = scene.GetLandData(avatar.AbsolutePosition);
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 10b83e6..1528330 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Linq;
30using System.Reflection; 31using System.Reflection;
31using log4net; 32using log4net;
32using Mono.Addins; 33using Mono.Addins;
@@ -36,6 +37,8 @@ using OpenMetaverse.StructuredData;
36using OpenSim.Framework; 37using OpenSim.Framework;
37using OpenSim.Region.Framework.Interfaces; 38using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes; 39using OpenSim.Region.Framework.Scenes;
40using OpenSim.Services.Interfaces;
41using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
39 42
40namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups 43namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
41{ 44{
@@ -45,6 +48,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 49
47 private List<Scene> m_sceneList = new List<Scene>(); 50 private List<Scene> m_sceneList = new List<Scene>();
51 private IPresenceService m_presenceService;
48 52
49 private IMessageTransferModule m_msgTransferModule = null; 53 private IMessageTransferModule m_msgTransferModule = null;
50 54
@@ -54,6 +58,27 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
54 private bool m_groupMessagingEnabled = false; 58 private bool m_groupMessagingEnabled = false;
55 private bool m_debugEnabled = true; 59 private bool m_debugEnabled = true;
56 60
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
57 #region IRegionModuleBase Members 82 #region IRegionModuleBase Members
58 83
59 public void Initialise(IConfigSource config) 84 public void Initialise(IConfigSource config)
@@ -83,10 +108,17 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
83 return; 108 return;
84 } 109 }
85 110
111 m_messageOnlineAgentsOnly = groupsConfig.GetBoolean("MessageOnlineUsersOnly", false);
112
113 if (m_messageOnlineAgentsOnly)
114 m_usersOnlineCache = new ExpiringCache<UUID, PresenceInfo[]>();
115
86 m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", true); 116 m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", true);
87 } 117 }
88 118
89 m_log.Info("[GROUPS-MESSAGING]: GroupsMessagingModule starting up"); 119 m_log.InfoFormat(
120 "[GROUPS-MESSAGING]: GroupsMessagingModule enabled with MessageOnlineOnly = {0}, DebugEnabled = {1}",
121 m_messageOnlineAgentsOnly, m_debugEnabled);
90 } 122 }
91 123
92 public void AddRegion(Scene scene) 124 public void AddRegion(Scene scene)
@@ -126,6 +158,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
126 return; 158 return;
127 } 159 }
128 160
161 if (m_presenceService == null)
162 m_presenceService = scene.PresenceService;
129 163
130 m_sceneList.Add(scene); 164 m_sceneList.Add(scene);
131 165
@@ -207,12 +241,42 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
207 public void SendMessageToGroup(GridInstantMessage im, UUID groupID) 241 public void SendMessageToGroup(GridInstantMessage im, UUID groupID)
208 { 242 {
209 List<GroupMembersData> groupMembers = m_groupData.GetGroupMembers(new UUID(im.fromAgentID), groupID); 243 List<GroupMembersData> groupMembers = m_groupData.GetGroupMembers(new UUID(im.fromAgentID), groupID);
210 244 int groupMembersCount = groupMembers.Count;
211 if (m_debugEnabled) 245
212 m_log.DebugFormat( 246 if (m_messageOnlineAgentsOnly)
213 "[GROUPS-MESSAGING]: SendMessageToGroup called for group {0} with {1} visible members", 247 {
214 groupID, groupMembers.Count); 248 string[] t1 = groupMembers.ConvertAll<string>(gmd => gmd.AgentID.ToString()).ToArray();
215 249
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
216 foreach (GroupMembersData member in groupMembers) 280 foreach (GroupMembersData member in groupMembers)
217 { 281 {
218 if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID, groupID)) 282 if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID, groupID))
@@ -254,6 +318,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
254 ProcessMessageFromGroupSession(msg); 318 ProcessMessageFromGroupSession(msg);
255 } 319 }
256 } 320 }
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);
257 } 327 }
258 328
259 #region SimGridEventHandlers 329 #region SimGridEventHandlers
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
index 65bd26c..79e9994 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs
@@ -123,7 +123,36 @@ 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 {
126 scene.RegisterModuleInterface<IGroupsModule>(this); 127 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);
127 } 156 }
128 157
129 public void RegionLoaded(Scene scene) 158 public void RegionLoaded(Scene scene)
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs
index 311531c..732c28f 100644
--- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs
@@ -175,14 +175,15 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
175 /// 175 ///
176 /// </summary> 176 /// </summary>
177 // ----------------------------------------------------------------- 177 // -----------------------------------------------------------------
178 public bool CreateStore(string value, out UUID result) 178 public bool CreateStore(string value, ref UUID result)
179 { 179 {
180 result = UUID.Zero; 180 if (result == UUID.Zero)
181 result = UUID.Random();
182
183 JsonStore map = null;
181 184
182 if (! m_enabled) return false; 185 if (! m_enabled) return false;
183 186
184 UUID uuid = UUID.Random();
185 JsonStore map = null;
186 187
187 try 188 try
188 { 189 {
@@ -195,9 +196,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
195 } 196 }
196 197
197 lock (m_JsonValueStore) 198 lock (m_JsonValueStore)
198 m_JsonValueStore.Add(uuid,map); 199 m_JsonValueStore.Add(result,map);
199 200
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 true; 234 return false;
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 eaba816..6910d14 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, out uuid)) 230 if (! m_store.CreateStore(value, ref 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 aa23fee..5ed1514 100644
--- a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs
@@ -821,8 +821,11 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule
821 { 821 {
822 if (!CanEdit()) 822 if (!CanEdit())
823 return; 823 return;
824 824 ISoundModule module = m_rootScene.RequestModuleInterface<ISoundModule>();
825 GetSOP().SendSound(asset.ToString(), volume, true, 0, 0, false, false); 825 if (module != null)
826 {
827 module.SendSound(GetSOP().UUID, asset, volume, true, 0, 0, false, false);
828 }
826 } 829 }
827 830
828 #endregion 831 #endregion
diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs
index fff3a32..bad75f7 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, string message) 184 void OnOarFileLoaded(Guid requestId, List<UUID> loadedScenes, string message)
185 { 185 {
186 m_oarFileLoading = true; 186 m_oarFileLoading = true;
187 187
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
index 7c693b6..5471afa 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])); 151 UUID.Zero, false, Position, new byte[0], true));
152 } 152 }
153 153
154 public void SendAgentOffline(UUID[] agentIDs) 154 public void SendAgentOffline(UUID[] agentIDs)
@@ -607,13 +607,15 @@ namespace OpenSim.Region.OptionalModules.World.NPC
607 { 607 {
608 } 608 }
609 609
610 public virtual void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, 610 public virtual void SendChatMessage(
611 UUID fromAgentID, byte source, byte audible) 611 string message, byte type, Vector3 fromPos, string fromName,
612 UUID fromAgentID, UUID ownerID, byte source, byte audible)
612 { 613 {
613 } 614 }
614 615
615 public virtual void SendChatMessage(byte[] message, byte type, Vector3 fromPos, string fromName, 616 public virtual void SendChatMessage(
616 UUID fromAgentID, byte source, byte audible) 617 byte[] message, byte type, Vector3 fromPos, string fromName,
618 UUID fromAgentID, UUID ownerID, byte source, byte audible)
617 { 619 {
618 } 620 }
619 621
@@ -909,11 +911,13 @@ namespace OpenSim.Region.OptionalModules.World.NPC
909 911
910 public void Close() 912 public void Close()
911 { 913 {
912 Close(true); 914 Close(true, false);
913 } 915 }
914 916
915 public void Close(bool sendStop) 917 public void Close(bool sendStop, bool force)
916 { 918 {
919 // Remove ourselves from the scene
920 m_scene.RemoveClient(AgentId, false);
917 } 921 }
918 922
919 public void Start() 923 public void Start()
diff --git a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
index 9179966..52ed846 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
@@ -117,6 +117,12 @@ 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));
120 } 126 }
121 127
122 [Test] 128 [Test]
@@ -136,6 +142,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
136 ScenePresence deletedNpc = m_scene.GetScenePresence(npcId); 142 ScenePresence deletedNpc = m_scene.GetScenePresence(npcId);
137 143
138 Assert.That(deletedNpc, Is.Null); 144 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));
139 } 150 }
140 151
141 [Test] 152 [Test]
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs
index 683bc51..3306a97 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs
@@ -34,6 +34,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
34 34
35public class BS6DofConstraint : 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
37 // Create a btGeneric6DofConstraint 41 // Create a btGeneric6DofConstraint
38 public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, 42 public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2,
39 Vector3 frame1, Quaternion frame1rot, 43 Vector3 frame1, Quaternion frame1rot,
@@ -44,11 +48,14 @@ public class BS6DofConstraint : BSConstraint
44 m_body1 = obj1; 48 m_body1 = obj1;
45 m_body2 = obj2; 49 m_body2 = obj2;
46 m_constraint = new BulletConstraint( 50 m_constraint = new BulletConstraint(
47 BulletSimAPI.Create6DofConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr, 51 BulletSimAPI.Create6DofConstraint2(m_world.ptr, m_body1.ptr, m_body2.ptr,
48 frame1, frame1rot, 52 frame1, frame1rot,
49 frame2, frame2rot, 53 frame2, frame2rot,
50 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); 54 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
51 m_enabled = true; 55 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"));
52 } 59 }
53 60
54 public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, 61 public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2,
@@ -58,11 +65,36 @@ public class BS6DofConstraint : BSConstraint
58 m_world = world; 65 m_world = world;
59 m_body1 = obj1; 66 m_body1 = obj1;
60 m_body2 = obj2; 67 m_body2 = obj2;
61 m_constraint = new BulletConstraint( 68 if (obj1.ptr == IntPtr.Zero || obj2.ptr == IntPtr.Zero)
62 BulletSimAPI.Create6DofConstraintToPoint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr, 69 {
63 joinPoint, 70 world.physicsScene.DetailLog("{0},BS6DOFConstraint,badBodyPtr,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}",
64 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); 71 BSScene.DetailLogZero, world.worldID,
65 m_enabled = true; 72 obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X"));
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 "[BULLETSIM 6DOF CONSTRAINT]", world.worldID,
75 obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X"));
76 m_enabled = false;
77 }
78 else
79 {
80 m_constraint = new BulletConstraint(
81 BulletSimAPI.Create6DofConstraintToPoint2(m_world.ptr, m_body1.ptr, m_body2.ptr,
82 joinPoint,
83 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
84 world.physicsScene.DetailLog("{0},BS6DofConstraint,createMidPoint,wID={1}, csrt={2}, rID={3}, rBody={4}, cID={5}, cBody={6}",
85 BSScene.DetailLogZero, world.worldID, m_constraint.ptr.ToString("X"),
86 obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X"));
87 if (m_constraint.ptr == IntPtr.Zero)
88 {
89 world.physicsScene.Logger.ErrorFormat("{0} Failed creation of 6Dof constraint. rootID={1}, childID={2}",
90 LogHeader, obj1.ID, obj2.ID);
91 m_enabled = false;
92 }
93 else
94 {
95 m_enabled = true;
96 }
97 }
66 } 98 }
67 99
68 public bool SetFrames(Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot) 100 public bool SetFrames(Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot)
@@ -70,7 +102,7 @@ public class BS6DofConstraint : BSConstraint
70 bool ret = false; 102 bool ret = false;
71 if (m_enabled) 103 if (m_enabled)
72 { 104 {
73 BulletSimAPI.SetFrames2(m_constraint.Ptr, frameA, frameArot, frameB, frameBrot); 105 BulletSimAPI.SetFrames2(m_constraint.ptr, frameA, frameArot, frameB, frameBrot);
74 ret = true; 106 ret = true;
75 } 107 }
76 return ret; 108 return ret;
@@ -81,9 +113,9 @@ public class BS6DofConstraint : BSConstraint
81 bool ret = false; 113 bool ret = false;
82 if (m_enabled) 114 if (m_enabled)
83 { 115 {
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_CFM, cfm, 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_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL);
86 BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL); 118 BulletSimAPI.SetConstraintParam2(m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL);
87 ret = true; 119 ret = true;
88 } 120 }
89 return ret; 121 return ret;
@@ -94,7 +126,7 @@ public class BS6DofConstraint : BSConstraint
94 bool ret = false; 126 bool ret = false;
95 float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; 127 float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
96 if (m_enabled) 128 if (m_enabled)
97 ret = BulletSimAPI.UseFrameOffset2(m_constraint.Ptr, onOff); 129 ret = BulletSimAPI.UseFrameOffset2(m_constraint.ptr, onOff);
98 return ret; 130 return ret;
99 } 131 }
100 132
@@ -103,7 +135,7 @@ public class BS6DofConstraint : BSConstraint
103 bool ret = false; 135 bool ret = false;
104 float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; 136 float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
105 if (m_enabled) 137 if (m_enabled)
106 ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.Ptr, onOff, targetVelocity, maxMotorForce); 138 ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.ptr, onOff, targetVelocity, maxMotorForce);
107 return ret; 139 return ret;
108 } 140 }
109 141
@@ -111,7 +143,7 @@ public class BS6DofConstraint : BSConstraint
111 { 143 {
112 bool ret = false; 144 bool ret = false;
113 if (m_enabled) 145 if (m_enabled)
114 ret = BulletSimAPI.SetBreakingImpulseThreshold2(m_constraint.Ptr, threshold); 146 ret = BulletSimAPI.SetBreakingImpulseThreshold2(m_constraint.ptr, threshold);
115 return ret; 147 return ret;
116 } 148 }
117} 149}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index e2f7af9..a041ba8 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -28,62 +28,48 @@ using System;
28using System.Collections.Generic; 28using System.Collections.Generic;
29using System.Reflection; 29using System.Reflection;
30using log4net; 30using log4net;
31using OpenMetaverse; 31using OMV = 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 class BSCharacter : PhysicsActor 37public class BSCharacter : BSPhysObject
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;
45 // private bool _stopped; 42 // private bool _stopped;
46 private Vector3 _size; 43 private OMV.Vector3 _size;
47 private Vector3 _scale;
48 private PrimitiveBaseShape _pbs;
49 private uint _localID = 0;
50 private bool _grabbed; 44 private bool _grabbed;
51 private bool _selected; 45 private bool _selected;
52 private Vector3 _position; 46 private OMV.Vector3 _position;
53 private float _mass; 47 private float _mass;
54 public float _density; 48 private float _avatarDensity;
55 public float _avatarVolume; 49 private float _avatarVolume;
56 private Vector3 _force; 50 private OMV.Vector3 _force;
57 private Vector3 _velocity; 51 private OMV.Vector3 _velocity;
58 private Vector3 _torque; 52 private OMV.Vector3 _torque;
59 private float _collisionScore; 53 private float _collisionScore;
60 private Vector3 _acceleration; 54 private OMV.Vector3 _acceleration;
61 private Quaternion _orientation; 55 private OMV.Quaternion _orientation;
62 private int _physicsActorType; 56 private int _physicsActorType;
63 private bool _isPhysical; 57 private bool _isPhysical;
64 private bool _flying; 58 private bool _flying;
65 private bool _setAlwaysRun; 59 private bool _setAlwaysRun;
66 private bool _throttleUpdates; 60 private bool _throttleUpdates;
67 private bool _isColliding; 61 private bool _isColliding;
68 private long _collidingStep;
69 private bool _collidingGround;
70 private long _collidingGroundStep;
71 private bool _collidingObj; 62 private bool _collidingObj;
72 private bool _floatOnWater; 63 private bool _floatOnWater;
73 private Vector3 _rotationalVelocity; 64 private OMV.Vector3 _rotationalVelocity;
74 private bool _kinematic; 65 private bool _kinematic;
75 private float _buoyancy; 66 private float _buoyancy;
76 67
77 private BulletBody m_body; 68 // The friction and velocity of the avatar is modified depending on whether walking or not.
78 public BulletBody Body { 69 private OMV.Vector3 _appliedVelocity; // the last velocity applied to the avatar
79 get { return m_body; } 70 private float _currentFriction; // the friction currently being used (changed by setVelocity).
80 set { m_body = value; }
81 }
82
83 private int _subscribedEventsMs = 0;
84 private int _nextCollisionOkTime = 0;
85 71
86 private Vector3 _PIDTarget; 72 private OMV.Vector3 _PIDTarget;
87 private bool _usePID; 73 private bool _usePID;
88 private float _PIDTau; 74 private float _PIDTau;
89 private bool _useHoverPID; 75 private bool _useHoverPID;
@@ -91,332 +77,504 @@ public class BSCharacter : PhysicsActor
91 private PIDHoverType _PIDHoverType; 77 private PIDHoverType _PIDHoverType;
92 private float _PIDHoverTao; 78 private float _PIDHoverTao;
93 79
94 public BSCharacter(uint localID, String avName, BSScene parent_scene, Vector3 pos, Vector3 size, bool isFlying) 80 public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying)
95 { 81 {
96 _localID = localID; 82 base.BaseInitialize(parent_scene, localID, avName, "BSCharacter");
97 _avName = avName; 83 _physicsActorType = (int)ActorTypes.Agent;
98 _scene = parent_scene;
99 _position = pos; 84 _position = pos;
100 _size = size; 85 _size = size;
101 _flying = isFlying; 86 _flying = isFlying;
102 _orientation = Quaternion.Identity; 87 _orientation = OMV.Quaternion.Identity;
103 _velocity = Vector3.Zero; 88 _velocity = OMV.Vector3.Zero;
89 _appliedVelocity = OMV.Vector3.Zero;
104 _buoyancy = ComputeBuoyancyFromFlying(isFlying); 90 _buoyancy = ComputeBuoyancyFromFlying(isFlying);
91 _currentFriction = PhysicsScene.Params.avatarStandingFriction;
92 _avatarDensity = PhysicsScene.Params.avatarDensity;
93
105 // The dimensions of the avatar capsule are kept in the scale. 94 // The dimensions of the avatar capsule are kept in the scale.
106 // Physics creates a unit capsule which is scaled by the physics engine. 95 // Physics creates a unit capsule which is scaled by the physics engine.
107 _scale = new Vector3(_scene.Params.avatarCapsuleRadius, _scene.Params.avatarCapsuleRadius, size.Z); 96 ComputeAvatarScale(_size);
108 _density = _scene.Params.avatarDensity; 97 // set _avatarVolume and _mass based on capsule size, _density and Scale
109 ComputeAvatarVolumeAndMass(); // set _avatarVolume and _mass based on capsule size, _density and _scale 98 ComputeAvatarVolumeAndMass();
99 DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}",
100 LocalID, _size, Scale, _avatarDensity, _avatarVolume, MassRaw);
110 101
111 ShapeData shapeData = new ShapeData(); 102 ShapeData shapeData = new ShapeData();
112 shapeData.ID = _localID; 103 shapeData.ID = LocalID;
113 shapeData.Type = ShapeData.PhysicsShapeType.SHAPE_AVATAR; 104 shapeData.Type = ShapeData.PhysicsShapeType.SHAPE_AVATAR;
114 shapeData.Position = _position; 105 shapeData.Position = _position;
115 shapeData.Rotation = _orientation; 106 shapeData.Rotation = _orientation;
116 shapeData.Velocity = _velocity; 107 shapeData.Velocity = _velocity;
117 shapeData.Scale = _scale; 108 shapeData.Size = Scale; // capsule is a native shape but scale is not just <1,1,1>
109 shapeData.Scale = Scale;
118 shapeData.Mass = _mass; 110 shapeData.Mass = _mass;
119 shapeData.Buoyancy = _buoyancy; 111 shapeData.Buoyancy = _buoyancy;
120 shapeData.Static = ShapeData.numericFalse; 112 shapeData.Static = ShapeData.numericFalse;
121 shapeData.Friction = _scene.Params.avatarFriction; 113 shapeData.Friction = PhysicsScene.Params.avatarStandingFriction;
122 shapeData.Restitution = _scene.Params.avatarRestitution; 114 shapeData.Restitution = PhysicsScene.Params.avatarRestitution;
123 115
124 // do actual create at taint time 116 // do actual create at taint time
125 _scene.TaintedObject("BSCharacter.create", delegate() 117 PhysicsScene.TaintedObject("BSCharacter.create", delegate()
126 { 118 {
127 BulletSimAPI.CreateObject(parent_scene.WorldID, shapeData); 119 DetailLog("{0},BSCharacter.create,taint", LocalID);
120 // New body and shape into BSBody and BSShape
121 PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this, shapeData, null, null, null);
128 122
129 m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); 123 SetPhysicalProperties();
130 // avatars get all collisions no matter what
131 BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
132 }); 124 });
133
134 return; 125 return;
135 } 126 }
136 127
137 // called when this character is being destroyed and the resources should be released 128 // called when this character is being destroyed and the resources should be released
138 public void Destroy() 129 public override void Destroy()
139 { 130 {
140 // DetailLog("{0},BSCharacter.Destroy", LocalID); 131 DetailLog("{0},BSCharacter.Destroy", LocalID);
141 _scene.TaintedObject("BSCharacter.destroy", delegate() 132 PhysicsScene.TaintedObject("BSCharacter.destroy", delegate()
142 { 133 {
143 BulletSimAPI.DestroyObject(_scene.WorldID, _localID); 134 PhysicsScene.Shapes.DereferenceBody(BSBody, true, null);
135 PhysicsScene.Shapes.DereferenceShape(BSShape, true, null);
144 }); 136 });
145 } 137 }
146 138
139 private void SetPhysicalProperties()
140 {
141 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, BSBody.ptr);
142
143 ZeroMotion();
144 ForcePosition = _position;
145 // Set the velocity and compute the proper friction
146 ForceVelocity = _velocity;
147
148 BulletSimAPI.SetRestitution2(BSBody.ptr, PhysicsScene.Params.avatarRestitution);
149 BulletSimAPI.SetMargin2(BSShape.ptr, PhysicsScene.Params.collisionMargin);
150 BulletSimAPI.SetLocalScaling2(BSShape.ptr, Scale);
151 BulletSimAPI.SetContactProcessingThreshold2(BSBody.ptr, PhysicsScene.Params.contactProcessingThreshold);
152 if (PhysicsScene.Params.ccdMotionThreshold > 0f)
153 {
154 BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold);
155 BulletSimAPI.SetCcdSweepSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius);
156 }
157
158 OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw);
159 BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia);
160
161 // Make so capsule does not fall over
162 BulletSimAPI.SetAngularFactorV2(BSBody.ptr, OMV.Vector3.Zero);
163
164 BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_CHARACTER_OBJECT);
165
166 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, BSBody.ptr);
167
168 // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ACTIVE_TAG);
169 BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_DEACTIVATION);
170 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, BSBody.ptr);
171
172 // Do this after the object has been added to the world
173 BulletSimAPI.SetCollisionFilterMask2(BSBody.ptr,
174 (uint)CollisionFilterGroups.AvatarFilter,
175 (uint)CollisionFilterGroups.AvatarMask);
176 }
177
147 public override void RequestPhysicsterseUpdate() 178 public override void RequestPhysicsterseUpdate()
148 { 179 {
149 base.RequestPhysicsterseUpdate(); 180 base.RequestPhysicsterseUpdate();
150 } 181 }
151 // No one calls this method so I don't know what it could possibly mean 182 // No one calls this method so I don't know what it could possibly mean
152 public override bool Stopped { 183 public override bool Stopped { get { return false; } }
153 get { return false; } 184
154 } 185 public override OMV.Vector3 Size {
155 public override Vector3 Size {
156 get 186 get
157 { 187 {
158 // Avatar capsule size is kept in the scale parameter. 188 // Avatar capsule size is kept in the scale parameter.
159 return new Vector3(_scale.X * 2, _scale.Y * 2, _scale.Z); 189 // return _size;
190 return new OMV.Vector3(Scale.X * 2f, Scale.Y * 2f, Scale.Z);
160 } 191 }
161 192
162 set { 193 set {
163 // When an avatar's size is set, only the height is changed 194 // When an avatar's size is set, only the height is changed.
164 // and that really only depends on the radius.
165 _size = value; 195 _size = value;
166 _scale.Z = (_size.Z * 1.15f) - (_scale.X + _scale.Y); 196 ComputeAvatarScale(_size);
167
168 // TODO: something has to be done with the avatar's vertical position
169
170 ComputeAvatarVolumeAndMass(); 197 ComputeAvatarVolumeAndMass();
198 DetailLog("{0},BSCharacter.setSize,call,scale={1},density={2},volume={3},mass={4}",
199 LocalID, Scale, _avatarDensity, _avatarVolume, MassRaw);
171 200
172 _scene.TaintedObject("BSCharacter.setSize", delegate() 201 PhysicsScene.TaintedObject("BSCharacter.setSize", delegate()
173 { 202 {
174 BulletSimAPI.SetObjectScaleMass(_scene.WorldID, LocalID, _scale, _mass, true); 203 BulletSimAPI.SetLocalScaling2(BSShape.ptr, Scale);
204 OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(BSShape.ptr, MassRaw);
205 BulletSimAPI.SetMassProps2(BSBody.ptr, MassRaw, localInertia);
175 }); 206 });
176 207
177 }
178 }
179 public override PrimitiveBaseShape Shape {
180 set { _pbs = value;
181 }
182 }
183 public override uint LocalID {
184 set { _localID = value;
185 } 208 }
186 get { return _localID; }
187 } 209 }
188 public override bool Grabbed { 210
189 set { _grabbed = value; 211 public override OMV.Vector3 Scale { get; set; }
190 } 212
213 public override PrimitiveBaseShape Shape
214 {
215 set { BaseShape = value; }
216 }
217
218 public override bool Grabbed {
219 set { _grabbed = value; }
191 } 220 }
192 public override bool Selected { 221 public override bool Selected {
193 set { _selected = value; 222 set { _selected = value; }
194 }
195 } 223 }
196 public override void CrossingFailure() { return; } 224 public override void CrossingFailure() { return; }
197 public override void link(PhysicsActor obj) { return; } 225 public override void link(PhysicsActor obj) { return; }
198 public override void delink() { return; } 226 public override void delink() { return; }
199 public override void LockAngularMotion(Vector3 axis) { return; }
200 227
201 public override Vector3 Position { 228 // Set motion values to zero.
229 // Do it to the properties so the values get set in the physics engine.
230 // Push the setting of the values to the viewer.
231 // Called at taint time!
232 public override void ZeroMotion()
233 {
234 _velocity = OMV.Vector3.Zero;
235 _acceleration = OMV.Vector3.Zero;
236 _rotationalVelocity = OMV.Vector3.Zero;
237
238 // Zero some other properties directly into the physics engine
239 BulletSimAPI.SetLinearVelocity2(BSBody.ptr, OMV.Vector3.Zero);
240 BulletSimAPI.SetAngularVelocity2(BSBody.ptr, OMV.Vector3.Zero);
241 BulletSimAPI.SetInterpolationVelocity2(BSBody.ptr, OMV.Vector3.Zero, OMV.Vector3.Zero);
242 BulletSimAPI.ClearForces2(BSBody.ptr);
243 }
244
245 public override void LockAngularMotion(OMV.Vector3 axis) { return; }
246
247 public override OMV.Vector3 Position {
202 get { 248 get {
203 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 249 // _position = BulletSimAPI.GetObjectPosition2(Scene.World.ptr, LocalID);
204 return _position; 250 return _position;
205 } 251 }
206 set { 252 set {
207 _position = value; 253 _position = value;
208 PositionSanityCheck(); 254 PositionSanityCheck();
209 255
210 _scene.TaintedObject("BSCharacter.setPosition", delegate() 256 PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate()
211 { 257 {
212 DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 258 DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
213 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 259 BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation);
214 }); 260 });
215 } 261 }
262 }
263 public override OMV.Vector3 ForcePosition {
264 get {
265 _position = BulletSimAPI.GetPosition2(BSBody.ptr);
266 return _position;
267 }
268 set {
269 _position = value;
270 PositionSanityCheck();
271 BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation);
272 }
216 } 273 }
217 274
275
218 // Check that the current position is sane and, if not, modify the position to make it so. 276 // Check that the current position is sane and, if not, modify the position to make it so.
219 // Check for being below terrain and being out of bounds. 277 // Check for being below terrain or on water.
220 // Returns 'true' of the position was made sane by some action. 278 // Returns 'true' of the position was made sane by some action.
221 private bool PositionSanityCheck() 279 private bool PositionSanityCheck()
222 { 280 {
223 bool ret = false; 281 bool ret = false;
224 282
225 // If below the ground, move the avatar up 283 // If below the ground, move the avatar up
226 float terrainHeight = Scene.GetTerrainHeightAtXYZ(_position); 284 float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position);
227 if (_position.Z < terrainHeight) 285 if (Position.Z < terrainHeight)
228 { 286 {
229 DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},orient={2}", LocalID, _position, _orientation); 287 DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight);
230 _position.Z = terrainHeight + 2.0f; 288 _position.Z = terrainHeight + 2.0f;
231 ret = true; 289 ret = true;
232 } 290 }
291 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0)
292 {
293 float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position);
294 if (Position.Z < waterHeight)
295 {
296 _position.Z = waterHeight;
297 ret = true;
298 }
299 }
233 300
234 // TODO: check for out of bounds 301 // TODO: check for out of bounds
235
236 return ret; 302 return ret;
237 } 303 }
238 304
239 public override float Mass { 305 // A version of the sanity check that also makes sure a new position value is
240 get { 306 // pushed back to the physics engine. This routine would be used by anyone
241 return _mass; 307 // who is not already pushing the value.
242 } 308 private bool PositionSanityCheck(bool inTaintTime)
309 {
310 bool ret = false;
311 if (PositionSanityCheck())
312 {
313 // The new position value must be pushed into the physics engine but we can't
314 // just assign to "Position" because of potential call loops.
315 BSScene.TaintCallback sanityOperation = delegate()
316 {
317 DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
318 BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation);
319 };
320 if (inTaintTime)
321 sanityOperation();
322 else
323 PhysicsScene.TaintedObject("BSCharacter.PositionSanityCheck", sanityOperation);
324 ret = true;
325 }
326 return ret;
243 } 327 }
244 public override Vector3 Force { 328
245 get { return _force; } 329 public override float Mass { get { return _mass; } }
330
331 // used when we only want this prim's mass and not the linkset thing
332 public override float MassRaw { get {return _mass; } }
333
334 public override OMV.Vector3 Force {
335 get { return _force; }
246 set { 336 set {
247 _force = value; 337 _force = value;
248 // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force); 338 // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force);
249 Scene.TaintedObject("BSCharacter.SetForce", delegate() 339 PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate()
250 { 340 {
251 DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force); 341 DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force);
252 BulletSimAPI.SetObjectForce(Scene.WorldID, LocalID, _force); 342 BulletSimAPI.SetObjectForce2(BSBody.ptr, _force);
253 }); 343 });
254 } 344 }
255 } 345 }
256 346
257 public override int VehicleType { 347 // Avatars don't do vehicles
258 get { return 0; } 348 public override int VehicleType { get { return (int)Vehicle.TYPE_NONE; } set { return; } }
259 set { return; }
260 }
261 public override void VehicleFloatParam(int param, float value) { } 349 public override void VehicleFloatParam(int param, float value) { }
262 public override void VehicleVectorParam(int param, Vector3 value) {} 350 public override void VehicleVectorParam(int param, OMV.Vector3 value) {}
263 public override void VehicleRotationParam(int param, Quaternion rotation) { } 351 public override void VehicleRotationParam(int param, OMV.Quaternion rotation) { }
264 public override void VehicleFlags(int param, bool remove) { } 352 public override void VehicleFlags(int param, bool remove) { }
265 353
266 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more 354 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more
267 public override void SetVolumeDetect(int param) { return; } 355 public override void SetVolumeDetect(int param) { return; }
268 356
269 public override Vector3 GeometricCenter { get { return Vector3.Zero; } } 357 public override OMV.Vector3 GeometricCenter { get { return OMV.Vector3.Zero; } }
270 public override Vector3 CenterOfMass { get { return Vector3.Zero; } } 358 public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } }
271 public override Vector3 Velocity { 359 public override OMV.Vector3 Velocity {
272 get { return _velocity; } 360 get { return _velocity; }
273 set { 361 set {
274 _velocity = value; 362 _velocity = value;
275 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity); 363 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity);
276 _scene.TaintedObject("BSCharacter.setVelocity", delegate() 364 PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate()
277 { 365 {
278 DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity); 366 DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity);
279 BulletSimAPI.SetObjectVelocity(_scene.WorldID, _localID, _velocity); 367 ForceVelocity = _velocity;
280 }); 368 });
281 } 369 }
282 } 370 }
283 public override Vector3 Torque { 371 public override OMV.Vector3 ForceVelocity {
284 get { return _torque; } 372 get { return _velocity; }
285 set { _torque = value; 373 set {
286 } 374 // Depending on whether the avatar is moving or not, change the friction
375 // to keep the avatar from slipping around
376 if (_velocity.Length() == 0)
377 {
378 if (_currentFriction != PhysicsScene.Params.avatarStandingFriction)
379 {
380 _currentFriction = PhysicsScene.Params.avatarStandingFriction;
381 BulletSimAPI.SetFriction2(BSBody.ptr, _currentFriction);
382 }
383 }
384 else
385 {
386 if (_currentFriction != PhysicsScene.Params.avatarFriction)
387 {
388 _currentFriction = PhysicsScene.Params.avatarFriction;
389 BulletSimAPI.SetFriction2(BSBody.ptr, _currentFriction);
390 }
391 }
392 _velocity = value;
393 // Remember the set velocity so we can suppress the reduction by friction, ...
394 _appliedVelocity = value;
395
396 BulletSimAPI.SetLinearVelocity2(BSBody.ptr, _velocity);
397 BulletSimAPI.Activate2(BSBody.ptr, true);
398 }
287 } 399 }
288 public override float CollisionScore { 400 public override OMV.Vector3 Torque {
289 get { return _collisionScore; } 401 get { return _torque; }
290 set { _collisionScore = value; 402 set { _torque = value;
291 } 403 }
404 }
405 public override float CollisionScore {
406 get { return _collisionScore; }
407 set { _collisionScore = value;
408 }
292 } 409 }
293 public override Vector3 Acceleration { 410 public override OMV.Vector3 Acceleration {
294 get { return _acceleration; } 411 get { return _acceleration; }
295 set { _acceleration = value; } 412 set { _acceleration = value; }
296 } 413 }
297 public override Quaternion Orientation { 414 public override OMV.Quaternion Orientation {
298 get { return _orientation; } 415 get { return _orientation; }
299 set { 416 set {
300 _orientation = value; 417 _orientation = value;
301 // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation); 418 // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation);
302 _scene.TaintedObject("BSCharacter.setOrientation", delegate() 419 PhysicsScene.TaintedObject("BSCharacter.setOrientation", delegate()
303 { 420 {
304 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 421 // _position = BulletSimAPI.GetPosition2(BSBody.ptr);
305 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 422 BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation);
306 }); 423 });
307 } 424 }
425 }
426 // Go directly to Bullet to get/set the value.
427 public override OMV.Quaternion ForceOrientation
428 {
429 get
430 {
431 _orientation = BulletSimAPI.GetOrientation2(BSBody.ptr);
432 return _orientation;
433 }
434 set
435 {
436 _orientation = value;
437 BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation);
438 }
308 } 439 }
309 public override int PhysicsActorType { 440 public override int PhysicsActorType {
310 get { return _physicsActorType; } 441 get { return _physicsActorType; }
311 set { _physicsActorType = value; 442 set { _physicsActorType = value;
312 } 443 }
313 } 444 }
314 public override bool IsPhysical { 445 public override bool IsPhysical {
315 get { return _isPhysical; } 446 get { return _isPhysical; }
316 set { _isPhysical = value; 447 set { _isPhysical = value;
317 } 448 }
449 }
450 public override bool IsSolid {
451 get { return true; }
318 } 452 }
319 public override bool Flying { 453 public override bool IsStatic {
320 get { return _flying; } 454 get { return false; }
455 }
456 public override bool Flying {
457 get { return _flying; }
321 set { 458 set {
322 if (_flying != value) 459 _flying = value;
323 { 460 // simulate flying by changing the effect of gravity
324 _flying = value; 461 Buoyancy = ComputeBuoyancyFromFlying(_flying);
325 // simulate flying by changing the effect of gravity 462 }
326 this.Buoyancy = ComputeBuoyancyFromFlying(_flying);
327 }
328 }
329 } 463 }
464 // Flying is implimented by changing the avatar's buoyancy.
465 // Would this be done better with a vehicle type?
330 private float ComputeBuoyancyFromFlying(bool ifFlying) { 466 private float ComputeBuoyancyFromFlying(bool ifFlying) {
331 return ifFlying ? 1f : 0f; 467 return ifFlying ? 1f : 0f;
332 } 468 }
333 public override bool 469 public override bool
334 SetAlwaysRun { 470 SetAlwaysRun {
335 get { return _setAlwaysRun; } 471 get { return _setAlwaysRun; }
336 set { _setAlwaysRun = value; } 472 set { _setAlwaysRun = value; }
337 } 473 }
338 public override bool ThrottleUpdates { 474 public override bool ThrottleUpdates {
339 get { return _throttleUpdates; } 475 get { return _throttleUpdates; }
340 set { _throttleUpdates = value; } 476 set { _throttleUpdates = value; }
341 } 477 }
342 public override bool IsColliding { 478 public override bool IsColliding {
343 get { return (_collidingStep == _scene.SimulationStep); } 479 get { return (CollidingStep == PhysicsScene.SimulationStep); }
344 set { _isColliding = value; } 480 set { _isColliding = value; }
345 } 481 }
346 public override bool CollidingGround { 482 public override bool CollidingGround {
347 get { return (_collidingGroundStep == _scene.SimulationStep); } 483 get { return (CollidingGroundStep == PhysicsScene.SimulationStep); }
348 set { _collidingGround = value; } 484 set { CollidingGround = value; }
349 } 485 }
350 public override bool CollidingObj { 486 public override bool CollidingObj {
351 get { return _collidingObj; } 487 get { return _collidingObj; }
352 set { _collidingObj = value; } 488 set { _collidingObj = value; }
353 } 489 }
354 public override bool FloatOnWater { 490 public override bool FloatOnWater {
355 set { _floatOnWater = value; } 491 set {
492 _floatOnWater = value;
493 PhysicsScene.TaintedObject("BSCharacter.setFloatOnWater", delegate()
494 {
495 if (_floatOnWater)
496 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER);
497 else
498 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER);
499 });
500 }
501 }
502 public override OMV.Vector3 RotationalVelocity {
503 get { return _rotationalVelocity; }
504 set { _rotationalVelocity = value; }
356 } 505 }
357 public override Vector3 RotationalVelocity { 506 public override OMV.Vector3 ForceRotationalVelocity {
358 get { return _rotationalVelocity; } 507 get { return _rotationalVelocity; }
359 set { _rotationalVelocity = value; } 508 set { _rotationalVelocity = value; }
360 } 509 }
361 public override bool Kinematic { 510 public override bool Kinematic {
362 get { return _kinematic; } 511 get { return _kinematic; }
363 set { _kinematic = value; } 512 set { _kinematic = value; }
364 } 513 }
365 // neg=fall quickly, 0=1g, 1=0g, pos=float up 514 // neg=fall quickly, 0=1g, 1=0g, pos=float up
366 public override float Buoyancy { 515 public override float Buoyancy {
367 get { return _buoyancy; } 516 get { return _buoyancy; }
368 set { _buoyancy = value; 517 set { _buoyancy = value;
369 _scene.TaintedObject("BSCharacter.setBuoyancy", delegate() 518 PhysicsScene.TaintedObject("BSCharacter.setBuoyancy", delegate()
370 { 519 {
371 DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 520 DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
372 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy); 521 ForceBuoyancy = _buoyancy;
373 }); 522 });
374 } 523 }
524 }
525 public override float ForceBuoyancy {
526 get { return _buoyancy; }
527 set { _buoyancy = value;
528 DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
529 // Buoyancy is faked by changing the gravity applied to the object
530 float grav = PhysicsScene.Params.gravity * (1f - _buoyancy);
531 BulletSimAPI.SetGravity2(BSBody.ptr, new OMV.Vector3(0f, 0f, grav));
532 }
375 } 533 }
376 534
377 // Used for MoveTo 535 // Used for MoveTo
378 public override Vector3 PIDTarget { 536 public override OMV.Vector3 PIDTarget {
379 set { _PIDTarget = value; } 537 set { _PIDTarget = value; }
380 } 538 }
381 public override bool PIDActive { 539 public override bool PIDActive {
382 set { _usePID = value; } 540 set { _usePID = value; }
383 } 541 }
384 public override float PIDTau { 542 public override float PIDTau {
385 set { _PIDTau = value; } 543 set { _PIDTau = value; }
386 } 544 }
387 545
388 // Used for llSetHoverHeight and maybe vehicle height 546 // Used for llSetHoverHeight and maybe vehicle height
389 // Hover Height will override MoveTo target's Z 547 // Hover Height will override MoveTo target's Z
390 public override bool PIDHoverActive { 548 public override bool PIDHoverActive {
391 set { _useHoverPID = value; } 549 set { _useHoverPID = value; }
392 } 550 }
393 public override float PIDHoverHeight { 551 public override float PIDHoverHeight {
394 set { _PIDHoverHeight = value; } 552 set { _PIDHoverHeight = value; }
395 } 553 }
396 public override PIDHoverType PIDHoverType { 554 public override PIDHoverType PIDHoverType {
397 set { _PIDHoverType = value; } 555 set { _PIDHoverType = value; }
398 } 556 }
399 public override float PIDHoverTau { 557 public override float PIDHoverTau {
400 set { _PIDHoverTao = value; } 558 set { _PIDHoverTao = value; }
401 } 559 }
402 560
403 // For RotLookAt 561 // For RotLookAt
404 public override Quaternion APIDTarget { set { return; } } 562 public override OMV.Quaternion APIDTarget { set { return; } }
405 public override bool APIDActive { set { return; } } 563 public override bool APIDActive { set { return; } }
406 public override float APIDStrength { set { return; } } 564 public override float APIDStrength { set { return; } }
407 public override float APIDDamping { set { return; } } 565 public override float APIDDamping { set { return; } }
408 566
409 public override void AddForce(Vector3 force, bool pushforce) { 567 public override void AddForce(OMV.Vector3 force, bool pushforce) {
410 if (force.IsFinite()) 568 if (force.IsFinite())
411 { 569 {
412 _force.X += force.X; 570 _force.X += force.X;
413 _force.Y += force.Y; 571 _force.Y += force.Y;
414 _force.Z += force.Z; 572 _force.Z += force.Z;
415 // m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force); 573 // m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force);
416 _scene.TaintedObject("BSCharacter.AddForce", delegate() 574 PhysicsScene.TaintedObject("BSCharacter.AddForce", delegate()
417 { 575 {
418 DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force); 576 DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force);
419 BulletSimAPI.AddObjectForce2(Body.Ptr, _force); 577 BulletSimAPI.SetObjectForce2(BSBody.ptr, _force);
420 }); 578 });
421 } 579 }
422 else 580 else
@@ -426,129 +584,75 @@ public class BSCharacter : PhysicsActor
426 //m_lastUpdateSent = false; 584 //m_lastUpdateSent = false;
427 } 585 }
428 586
429 public override void AddAngularForce(Vector3 force, bool pushforce) { 587 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
430 } 588 }
431 public override void SetMomentum(Vector3 momentum) { 589 public override void SetMomentum(OMV.Vector3 momentum) {
432 } 590 }
433 591
434 // Turn on collision events at a rate no faster than one every the given milliseconds 592 private void ComputeAvatarScale(OMV.Vector3 size)
435 public override void SubscribeEvents(int ms) { 593 {
436 _subscribedEventsMs = ms; 594 // The 'size' given by the simulator is the mid-point of the avatar
437 if (ms > 0) 595 // and X and Y are unspecified.
438 {
439 // make sure first collision happens
440 _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs;
441 596
442 Scene.TaintedObject("BSCharacter.SubscribeEvents", delegate() 597 OMV.Vector3 newScale = OMV.Vector3.Zero;
443 { 598 newScale.X = PhysicsScene.Params.avatarCapsuleRadius;
444 BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 599 newScale.Y = PhysicsScene.Params.avatarCapsuleRadius;
445 }); 600
446 } 601 // From the total height, remove the capsule half spheres that are at each end
447 } 602 newScale.Z = size.Z- (newScale.X + newScale.Y);
448 // Stop collision events 603 Scale = newScale;
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);
460 } 604 }
461 605
462 // set _avatarVolume and _mass based on capsule size, _density and _scale 606 // set _avatarVolume and _mass based on capsule size, _density and Scale
463 private void ComputeAvatarVolumeAndMass() 607 private void ComputeAvatarVolumeAndMass()
464 { 608 {
465 _avatarVolume = (float)( 609 _avatarVolume = (float)(
466 Math.PI 610 Math.PI
467 * _scale.X 611 * Scale.X
468 * _scale.Y // the area of capsule cylinder 612 * Scale.Y // the area of capsule cylinder
469 * _scale.Z // times height of capsule cylinder 613 * Scale.Z // times height of capsule cylinder
470 + 1.33333333f 614 + 1.33333333f
471 * Math.PI 615 * Math.PI
472 * _scale.X 616 * Scale.X
473 * Math.Min(_scale.X, _scale.Y) 617 * Math.Min(Scale.X, Scale.Y)
474 * _scale.Y // plus the volume of the capsule end caps 618 * Scale.Y // plus the volume of the capsule end caps
475 ); 619 );
476 _mass = _density * _avatarVolume; 620 _mass = _avatarDensity * _avatarVolume;
477 } 621 }
478 622
479 // The physics engine says that properties have updated. Update same and inform 623 // The physics engine says that properties have updated. Update same and inform
480 // the world that things have changed. 624 // the world that things have changed.
481 public void UpdateProperties(EntityProperties entprop) 625 public override void UpdateProperties(EntityProperties entprop)
482 { 626 {
483 _position = entprop.Position; 627 _position = entprop.Position;
484 _orientation = entprop.Rotation; 628 _orientation = entprop.Rotation;
485 _velocity = entprop.Velocity; 629 _velocity = entprop.Velocity;
486 _acceleration = entprop.Acceleration; 630 _acceleration = entprop.Acceleration;
487 _rotationalVelocity = entprop.RotationalVelocity; 631 _rotationalVelocity = entprop.RotationalVelocity;
488 // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. 632 // Do some sanity checking for the avatar. Make sure it's above ground and inbounds.
489 // base.RequestPhysicsterseUpdate(); 633 PositionSanityCheck(true);
490 634
491 /* 635 // remember the current and last set values
492 DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", 636 LastEntityProperties = CurrentEntityProperties;
493 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, 637 CurrentEntityProperties = entprop;
494 entprop.Acceleration, entprop.RotationalVelocity);
495 */
496 }
497
498 // Called by the scene when a collision with this object is reported
499 // The collision, if it should be reported to the character, is placed in a collection
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);
505 638
506 // The following makes IsColliding() and IsCollidingGround() work 639 if (entprop.Velocity != LastEntityProperties.Velocity)
507 _collidingStep = _scene.SimulationStep;
508 if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID)
509 { 640 {
510 _collidingGroundStep = _scene.SimulationStep; 641 // Changes in the velocity are suppressed in avatars.
642 // That's just the way they are defined.
643 OMV.Vector3 avVel = new OMV.Vector3(_appliedVelocity.X, _appliedVelocity.Y, entprop.Velocity.Z);
644 _velocity = avVel;
645 BulletSimAPI.SetLinearVelocity2(BSBody.ptr, avVel);
511 } 646 }
512 // DetailLog("{0},BSCharacter.Collison,call,with={1}", LocalID, collidingWith);
513 647
514 // throttle collisions to the rate specified in the subscription 648 // Tell the linkset about value changes
515 if (_subscribedEventsMs != 0) { 649 Linkset.UpdateProperties(this);
516 int nowTime = _scene.SimulationNowTime;
517 if (nowTime >= _nextCollisionOkTime) {
518 _nextCollisionOkTime = nowTime + _subscribedEventsMs;
519 650
520 if (collisionCollection == null) 651 // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop.
521 collisionCollection = new CollisionEventUpdate(); 652 // base.RequestPhysicsterseUpdate();
522 collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
523 }
524 }
525 }
526 653
527 public void SendCollisions() 654 DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
528 { 655 LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
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);
552 } 656 }
553} 657}
554} 658}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
index 25084d8..f017cdd 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
@@ -34,6 +34,8 @@ 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
37 protected BulletSim m_world; 39 protected BulletSim m_world;
38 protected BulletBody m_body1; 40 protected BulletBody m_body1;
39 protected BulletBody m_body2; 41 protected BulletBody m_body2;
@@ -48,22 +50,31 @@ public abstract class BSConstraint : IDisposable
48 { 50 {
49 if (m_enabled) 51 if (m_enabled)
50 { 52 {
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;
55 m_enabled = false; 53 m_enabled = false;
54 if (m_constraint.ptr != IntPtr.Zero)
55 {
56 bool success = BulletSimAPI.DestroyConstraint2(m_world.ptr, m_constraint.ptr);
57 m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,id1={1},body1={2},id2={3},body2={4},success={5}",
58 BSScene.DetailLogZero,
59 m_body1.ID, m_body1.ptr.ToString("X"),
60 m_body2.ID, m_body2.ptr.ToString("X"),
61 success);
62 m_constraint.ptr = System.IntPtr.Zero;
63 }
56 } 64 }
57 } 65 }
58 66
59 public BulletBody Body1 { get { return m_body1; } } 67 public BulletBody Body1 { get { return m_body1; } }
60 public BulletBody Body2 { get { return m_body2; } } 68 public BulletBody Body2 { get { return m_body2; } }
69 public BulletConstraint Constraint { get { return m_constraint; } }
70 public abstract ConstraintType Type { get; }
71
61 72
62 public virtual bool SetLinearLimits(Vector3 low, Vector3 high) 73 public virtual bool SetLinearLimits(Vector3 low, Vector3 high)
63 { 74 {
64 bool ret = false; 75 bool ret = false;
65 if (m_enabled) 76 if (m_enabled)
66 ret = BulletSimAPI.SetLinearLimits2(m_constraint.Ptr, low, high); 77 ret = BulletSimAPI.SetLinearLimits2(m_constraint.ptr, low, high);
67 return ret; 78 return ret;
68 } 79 }
69 80
@@ -71,7 +82,18 @@ public abstract class BSConstraint : IDisposable
71 { 82 {
72 bool ret = false; 83 bool ret = false;
73 if (m_enabled) 84 if (m_enabled)
74 ret = BulletSimAPI.SetAngularLimits2(m_constraint.Ptr, low, high); 85 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 }
75 return ret; 97 return ret;
76 } 98 }
77 99
@@ -81,7 +103,7 @@ public abstract class BSConstraint : IDisposable
81 if (m_enabled) 103 if (m_enabled)
82 { 104 {
83 // Recompute the internal transforms 105 // Recompute the internal transforms
84 BulletSimAPI.CalculateTransforms2(m_constraint.Ptr); 106 BulletSimAPI.CalculateTransforms2(m_constraint.ptr);
85 ret = true; 107 ret = true;
86 } 108 }
87 return ret; 109 return ret;
@@ -97,13 +119,14 @@ public abstract class BSConstraint : IDisposable
97 ret = CalculateTransforms(); 119 ret = CalculateTransforms();
98 if (ret) 120 if (ret)
99 { 121 {
100 // m_world.scene.PhysicsLogging.Write("{0},BSConstraint.RecomputeConstraintVariables,taint,enabling,A={1},B={2}", 122 // Setting an object's mass to zero (making it static like when it's selected)
101 // BSScene.DetailLogZero, Body1.ID, Body2.ID); 123 // automatically disables the constraints.
102 BulletSimAPI.SetConstraintEnable2(m_constraint.Ptr, m_world.scene.NumericBool(true)); 124 // If the link is enabled, be sure to set the constraint itself to enabled.
125 BulletSimAPI.SetConstraintEnable2(m_constraint.ptr, m_world.physicsScene.NumericBool(true));
103 } 126 }
104 else 127 else
105 { 128 {
106 m_world.scene.Logger.ErrorFormat("[BULLETSIM CONSTRAINT] CalculateTransforms failed. A={0}, B={1}", Body1.ID, Body2.ID); 129 m_world.physicsScene.Logger.ErrorFormat("{0} CalculateTransforms failed. A={1}, B={2}", LogHeader, Body1.ID, Body2.ID);
107 } 130 }
108 } 131 }
109 return ret; 132 return ret;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index 5a9f135..117c878 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.
@@ -54,17 +54,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
54{ 54{
55 public class BSDynamics 55 public class BSDynamics
56 { 56 {
57 private int frcount = 0; // Used to limit dynamics debug output to 57 private BSScene PhysicsScene { get; set; }
58 // every 100th frame 58 // the prim this dynamic controller belongs to
59 59 private BSPrim Prim { get; set; }
60 private BSPrim m_prim; // the prim this dynamic controller belongs to
61 60
62 // Vehicle properties 61 // Vehicle properties
63 private Vehicle m_type = Vehicle.TYPE_NONE; // If a 'VEHICLE', and what kind 62 public Vehicle Type { get; set; }
64 public Vehicle Type 63
65 {
66 get { return m_type; }
67 }
68 // private Quaternion m_referenceFrame = Quaternion.Identity; // Axis modifier 64 // private Quaternion m_referenceFrame = Quaternion.Identity; // Axis modifier
69 private VehicleFlag m_flags = (VehicleFlag) 0; // Boolean settings: 65 private VehicleFlag m_flags = (VehicleFlag) 0; // Boolean settings:
70 // HOVER_TERRAIN_ONLY 66 // HOVER_TERRAIN_ONLY
@@ -74,13 +70,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
74 // HOVER_UP_ONLY 70 // HOVER_UP_ONLY
75 // LIMIT_MOTOR_UP 71 // LIMIT_MOTOR_UP
76 // LIMIT_ROLL_ONLY 72 // LIMIT_ROLL_ONLY
77 private VehicleFlag m_Hoverflags = (VehicleFlag)0;
78 private Vector3 m_BlockingEndPoint = Vector3.Zero; 73 private Vector3 m_BlockingEndPoint = Vector3.Zero;
79 private Quaternion m_RollreferenceFrame = Quaternion.Identity; 74 private Quaternion m_RollreferenceFrame = Quaternion.Identity;
80 // Linear properties 75 // Linear properties
81 private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time 76 private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time
82 private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL 77 private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL
83 private Vector3 m_dir = Vector3.Zero; // velocity applied to body 78 private Vector3 m_newVelocity = Vector3.Zero; // velocity computed to be applied to body
84 private Vector3 m_linearFrictionTimescale = Vector3.Zero; 79 private Vector3 m_linearFrictionTimescale = Vector3.Zero;
85 private float m_linearMotorDecayTimescale = 0; 80 private float m_linearMotorDecayTimescale = 0;
86 private float m_linearMotorTimescale = 0; 81 private float m_linearMotorTimescale = 0;
@@ -97,7 +92,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
97 private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate 92 private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate
98 private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate 93 private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate
99 private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body 94 private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body
100 // private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body 95 private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body
101 96
102 //Deflection properties 97 //Deflection properties
103 // private float m_angularDeflectionEfficiency = 0; 98 // private float m_angularDeflectionEfficiency = 0;
@@ -124,86 +119,74 @@ namespace OpenSim.Region.Physics.BulletSPlugin
124 private float m_verticalAttractionEfficiency = 1.0f; // damped 119 private float m_verticalAttractionEfficiency = 1.0f; // damped
125 private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor. 120 private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor.
126 121
127 public BSDynamics(BSPrim myPrim) 122 public BSDynamics(BSScene myScene, BSPrim myPrim)
128 { 123 {
129 m_prim = myPrim; 124 PhysicsScene = myScene;
130 m_type = Vehicle.TYPE_NONE; 125 Prim = myPrim;
126 Type = Vehicle.TYPE_NONE;
131 } 127 }
132 128
133 internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue, float timestep) 129 // Return 'true' if this vehicle is doing vehicle things
130 public bool IsActive
134 { 131 {
135 DetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); 132 get { return Type != Vehicle.TYPE_NONE; }
133 }
134
135 internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue)
136 {
137 VDetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue);
136 switch (pParam) 138 switch (pParam)
137 { 139 {
138 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: 140 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
139 if (pValue < 0.01f) pValue = 0.01f; 141 // m_angularDeflectionEfficiency = Math.Max(pValue, 0.01f);
140 // m_angularDeflectionEfficiency = pValue;
141 break; 142 break;
142 case Vehicle.ANGULAR_DEFLECTION_TIMESCALE: 143 case Vehicle.ANGULAR_DEFLECTION_TIMESCALE:
143 if (pValue < 0.01f) pValue = 0.01f; 144 // m_angularDeflectionTimescale = Math.Max(pValue, 0.01f);
144 // m_angularDeflectionTimescale = pValue;
145 break; 145 break;
146 case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE: 146 case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE:
147 if (pValue < 0.01f) pValue = 0.01f; 147 m_angularMotorDecayTimescale = Math.Max(pValue, 0.01f);
148 m_angularMotorDecayTimescale = pValue;
149 break; 148 break;
150 case Vehicle.ANGULAR_MOTOR_TIMESCALE: 149 case Vehicle.ANGULAR_MOTOR_TIMESCALE:
151 if (pValue < 0.01f) pValue = 0.01f; 150 m_angularMotorTimescale = Math.Max(pValue, 0.01f);
152 m_angularMotorTimescale = pValue;
153 break; 151 break;
154 case Vehicle.BANKING_EFFICIENCY: 152 case Vehicle.BANKING_EFFICIENCY:
155 if (pValue < 0.01f) pValue = 0.01f; 153 // m_bankingEfficiency = Math.Max(pValue, 0.01f);
156 // m_bankingEfficiency = pValue;
157 break; 154 break;
158 case Vehicle.BANKING_MIX: 155 case Vehicle.BANKING_MIX:
159 if (pValue < 0.01f) pValue = 0.01f; 156 // m_bankingMix = Math.Max(pValue, 0.01f);
160 // m_bankingMix = pValue;
161 break; 157 break;
162 case Vehicle.BANKING_TIMESCALE: 158 case Vehicle.BANKING_TIMESCALE:
163 if (pValue < 0.01f) pValue = 0.01f; 159 // m_bankingTimescale = Math.Max(pValue, 0.01f);
164 // m_bankingTimescale = pValue;
165 break; 160 break;
166 case Vehicle.BUOYANCY: 161 case Vehicle.BUOYANCY:
167 if (pValue < -1f) pValue = -1f; 162 m_VehicleBuoyancy = Math.Max(-1f, Math.Min(pValue, 1f));
168 if (pValue > 1f) pValue = 1f;
169 m_VehicleBuoyancy = pValue;
170 break; 163 break;
171// case Vehicle.HOVER_EFFICIENCY: 164// case Vehicle.HOVER_EFFICIENCY:
172// if (pValue < 0f) pValue = 0f; 165// m_VhoverEfficiency = Math.Max(0f, Math.Min(pValue, 1f));
173// if (pValue > 1f) pValue = 1f;
174// m_VhoverEfficiency = pValue;
175// break; 166// break;
176 case Vehicle.HOVER_HEIGHT: 167 case Vehicle.HOVER_HEIGHT:
177 m_VhoverHeight = pValue; 168 m_VhoverHeight = pValue;
178 break; 169 break;
179 case Vehicle.HOVER_TIMESCALE: 170 case Vehicle.HOVER_TIMESCALE:
180 if (pValue < 0.01f) pValue = 0.01f; 171 m_VhoverTimescale = Math.Max(pValue, 0.01f);
181 m_VhoverTimescale = pValue;
182 break; 172 break;
183 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY: 173 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
184 if (pValue < 0.01f) pValue = 0.01f; 174 // m_linearDeflectionEfficiency = Math.Max(pValue, 0.01f);
185 // m_linearDeflectionEfficiency = pValue;
186 break; 175 break;
187 case Vehicle.LINEAR_DEFLECTION_TIMESCALE: 176 case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
188 if (pValue < 0.01f) pValue = 0.01f; 177 // m_linearDeflectionTimescale = Math.Max(pValue, 0.01f);
189 // m_linearDeflectionTimescale = pValue;
190 break; 178 break;
191 case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE: 179 case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE:
192 if (pValue < 0.01f) pValue = 0.01f; 180 m_linearMotorDecayTimescale = Math.Max(pValue, 0.01f);
193 m_linearMotorDecayTimescale = pValue;
194 break; 181 break;
195 case Vehicle.LINEAR_MOTOR_TIMESCALE: 182 case Vehicle.LINEAR_MOTOR_TIMESCALE:
196 if (pValue < 0.01f) pValue = 0.01f; 183 m_linearMotorTimescale = Math.Max(pValue, 0.01f);
197 m_linearMotorTimescale = pValue;
198 break; 184 break;
199 case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY: 185 case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
200 if (pValue < 0.1f) pValue = 0.1f; // Less goes unstable 186 m_verticalAttractionEfficiency = Math.Max(0.1f, Math.Min(pValue, 1f));
201 if (pValue > 1.0f) pValue = 1.0f;
202 m_verticalAttractionEfficiency = pValue;
203 break; 187 break;
204 case Vehicle.VERTICAL_ATTRACTION_TIMESCALE: 188 case Vehicle.VERTICAL_ATTRACTION_TIMESCALE:
205 if (pValue < 0.01f) pValue = 0.01f; 189 m_verticalAttractionTimescale = Math.Max(pValue, 0.01f);
206 m_verticalAttractionTimescale = pValue;
207 break; 190 break;
208 191
209 // These are vector properties but the engine lets you use a single float value to 192 // These are vector properties but the engine lets you use a single float value to
@@ -229,9 +212,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
229 } 212 }
230 }//end ProcessFloatVehicleParam 213 }//end ProcessFloatVehicleParam
231 214
232 internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue, float timestep) 215 internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue)
233 { 216 {
234 DetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); 217 VDetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue);
235 switch (pParam) 218 switch (pParam)
236 { 219 {
237 case Vehicle.ANGULAR_FRICTION_TIMESCALE: 220 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
@@ -266,7 +249,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
266 249
267 internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) 250 internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue)
268 { 251 {
269 DetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); 252 VDetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue);
270 switch (pParam) 253 switch (pParam)
271 { 254 {
272 case Vehicle.REFERENCE_FRAME: 255 case Vehicle.REFERENCE_FRAME:
@@ -280,166 +263,29 @@ namespace OpenSim.Region.Physics.BulletSPlugin
280 263
281 internal void ProcessVehicleFlags(int pParam, bool remove) 264 internal void ProcessVehicleFlags(int pParam, bool remove)
282 { 265 {
283 DetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", m_prim.LocalID, pParam, remove); 266 VDetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", Prim.LocalID, pParam, remove);
267 VehicleFlag parm = (VehicleFlag)pParam;
284 if (remove) 268 if (remove)
285 { 269 {
286 if (pParam == -1) 270 if (pParam == -1)
287 { 271 {
288 m_flags = (VehicleFlag)0; 272 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 } 273 }
322 if ((pParam & (int)VehicleFlag.MOUSELOOK_BANK) == (int)VehicleFlag.MOUSELOOK_BANK) 274 else
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 { 275 {
369 if ((m_flags & VehicleFlag.LOCK_ROTATION) != (VehicleFlag)0) 276 m_flags &= ~parm;
370 m_flags &= ~(VehicleFlag.LOCK_ROTATION);
371 } 277 }
372 } 278 }
373 else 279 else {
374 { 280 m_flags |= parm;
375 if ((pParam & (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) == (int)VehicleFlag.HOVER_GLOBAL_HEIGHT)
376 {
377 m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT | m_flags);
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 }
435 } 281 }
436 }//end ProcessVehicleFlags 282 }//end ProcessVehicleFlags
437 283
438 internal void ProcessTypeChange(Vehicle pType) 284 internal void ProcessTypeChange(Vehicle pType)
439 { 285 {
440 DetailLog("{0},ProcessTypeChange,type={1}", m_prim.LocalID, pType); 286 VDetailLog("{0},ProcessTypeChange,type={1}", Prim.LocalID, pType);
441 // Set Defaults For Type 287 // Set Defaults For Type
442 m_type = pType; 288 Type = pType;
443 switch (pType) 289 switch (pType)
444 { 290 {
445 case Vehicle.TYPE_NONE: 291 case Vehicle.TYPE_NONE:
@@ -478,10 +324,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
478 // m_bankingMix = 1; 324 // m_bankingMix = 1;
479 // m_bankingTimescale = 10; 325 // m_bankingTimescale = 10;
480 // m_referenceFrame = Quaternion.Identity; 326 // m_referenceFrame = Quaternion.Identity;
481 m_Hoverflags &= 327 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
328 m_flags &=
482 ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | 329 ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
483 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); 330 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
484 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
485 break; 331 break;
486 case Vehicle.TYPE_CAR: 332 case Vehicle.TYPE_CAR:
487 m_linearFrictionTimescale = new Vector3(100, 2, 1000); 333 m_linearFrictionTimescale = new Vector3(100, 2, 1000);
@@ -506,10 +352,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
506 // m_bankingMix = 1; 352 // m_bankingMix = 1;
507 // m_bankingTimescale = 1; 353 // m_bankingTimescale = 1;
508 // m_referenceFrame = Quaternion.Identity; 354 // m_referenceFrame = Quaternion.Identity;
509 m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT); 355 m_flags |= (VehicleFlag.NO_DEFLECTION_UP
510 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | 356 | VehicleFlag.LIMIT_ROLL_ONLY
511 VehicleFlag.LIMIT_MOTOR_UP); 357 | VehicleFlag.LIMIT_MOTOR_UP);
512 m_Hoverflags |= (VehicleFlag.HOVER_UP_ONLY); 358 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT);
359 m_flags |= (VehicleFlag.HOVER_UP_ONLY);
513 break; 360 break;
514 case Vehicle.TYPE_BOAT: 361 case Vehicle.TYPE_BOAT:
515 m_linearFrictionTimescale = new Vector3(10, 3, 2); 362 m_linearFrictionTimescale = new Vector3(10, 3, 2);
@@ -534,12 +381,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
534 // m_bankingMix = 0.8f; 381 // m_bankingMix = 0.8f;
535 // m_bankingTimescale = 1; 382 // m_bankingTimescale = 1;
536 // m_referenceFrame = Quaternion.Identity; 383 // m_referenceFrame = Quaternion.Identity;
537 m_Hoverflags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY | 384 m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY
538 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); 385 | VehicleFlag.HOVER_GLOBAL_HEIGHT
539 m_flags &= ~(VehicleFlag.LIMIT_ROLL_ONLY); 386 | VehicleFlag.LIMIT_ROLL_ONLY
540 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | 387 | VehicleFlag.HOVER_UP_ONLY);
541 VehicleFlag.LIMIT_MOTOR_UP); 388 m_flags |= (VehicleFlag.NO_DEFLECTION_UP
542 m_Hoverflags |= (VehicleFlag.HOVER_WATER_ONLY); 389 | VehicleFlag.LIMIT_MOTOR_UP
390 | VehicleFlag.HOVER_WATER_ONLY);
543 break; 391 break;
544 case Vehicle.TYPE_AIRPLANE: 392 case Vehicle.TYPE_AIRPLANE:
545 m_linearFrictionTimescale = new Vector3(200, 10, 5); 393 m_linearFrictionTimescale = new Vector3(200, 10, 5);
@@ -564,9 +412,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
564 // m_bankingMix = 0.7f; 412 // m_bankingMix = 0.7f;
565 // m_bankingTimescale = 2; 413 // m_bankingTimescale = 2;
566 // m_referenceFrame = Quaternion.Identity; 414 // m_referenceFrame = Quaternion.Identity;
567 m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | 415 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY
568 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); 416 | VehicleFlag.HOVER_TERRAIN_ONLY
569 m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP); 417 | VehicleFlag.HOVER_GLOBAL_HEIGHT
418 | VehicleFlag.HOVER_UP_ONLY
419 | VehicleFlag.NO_DEFLECTION_UP
420 | VehicleFlag.LIMIT_MOTOR_UP);
570 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); 421 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
571 break; 422 break;
572 case Vehicle.TYPE_BALLOON: 423 case Vehicle.TYPE_BALLOON:
@@ -592,50 +443,67 @@ namespace OpenSim.Region.Physics.BulletSPlugin
592 // m_bankingMix = 0.7f; 443 // m_bankingMix = 0.7f;
593 // m_bankingTimescale = 5; 444 // m_bankingTimescale = 5;
594 // m_referenceFrame = Quaternion.Identity; 445 // m_referenceFrame = Quaternion.Identity;
595 m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | 446 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY
596 VehicleFlag.HOVER_UP_ONLY); 447 | VehicleFlag.HOVER_TERRAIN_ONLY
597 m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP); 448 | VehicleFlag.HOVER_UP_ONLY
598 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); 449 | VehicleFlag.NO_DEFLECTION_UP
599 m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT); 450 | VehicleFlag.LIMIT_MOTOR_UP);
451 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY
452 | VehicleFlag.HOVER_GLOBAL_HEIGHT);
600 break; 453 break;
601 } 454 }
602 }//end SetDefaultsForType 455 }//end SetDefaultsForType
603 456
604 internal void Step(float pTimestep) 457 // Some of the properties of this prim may have changed.
458 // Do any updating needed for a vehicle
459 public void Refresh()
605 { 460 {
606 if (m_type == Vehicle.TYPE_NONE) return; 461 if (!IsActive)
462 return;
463
464 // Set the prim's inertia to zero. The vehicle code handles that and this
465 // removes the motion and torque actions introduced by Bullet.
466 Vector3 inertia = Vector3.Zero;
467 // comment out for DEBUG test
468 // BulletSimAPI.SetMassProps2(Prim.BSBody.ptr, Prim.MassRaw, inertia);
469 // BulletSimAPI.UpdateInertiaTensor2(Prim.BSBody.ptr);
470 }
607 471
608 frcount++; // used to limit debug comment output 472 // One step of the vehicle properties for the next 'pTimestep' seconds.
609 if (frcount > 100) 473 internal void Step(float pTimestep)
610 frcount = 0; 474 {
475 if (!IsActive) return;
611 476
612 MoveLinear(pTimestep); 477 MoveLinear(pTimestep);
613 MoveAngular(pTimestep); 478 MoveAngular(pTimestep);
614 LimitRotation(pTimestep); 479 LimitRotation(pTimestep);
615 480
616 DetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", 481 // remember the position so next step we can limit absolute movement effects
617 m_prim.LocalID, m_prim.Position, m_prim.Force, m_prim.Velocity, m_prim.RotationalVelocity); 482 m_lastPositionVector = Prim.ForcePosition;
483
484 VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}",
485 Prim.LocalID, Prim.ForcePosition, Prim.Force, Prim.ForceVelocity, Prim.RotationalVelocity);
618 }// end Step 486 }// end Step
619 487
488 // Apply the effect of the linear motor.
489 // Also does hover and float.
620 private void MoveLinear(float pTimestep) 490 private void MoveLinear(float pTimestep)
621 { 491 {
622 // requested m_linearMotorDirection is significant 492 // m_linearMotorDirection is the direction we are moving relative to the vehicle coordinates
623 // if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) 493 // m_lastLinearVelocityVector is the speed we are moving in that direction
624 if (m_linearMotorDirection.LengthSquared() > 0.0001f) 494 if (m_linearMotorDirection.LengthSquared() > 0.001f)
625 { 495 {
626 Vector3 origDir = m_linearMotorDirection; 496 Vector3 origDir = m_linearMotorDirection;
627 Vector3 origVel = m_lastLinearVelocityVector; 497 Vector3 origVel = m_lastLinearVelocityVector;
628 498
629 // add drive to body 499 // add drive to body
630 // Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep); 500 // Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale / pTimestep);
631 Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale); 501 Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/(m_linearMotorTimescale / pTimestep);
632 // lastLinearVelocityVector is the current body velocity vector? 502 // lastLinearVelocityVector is the current body velocity vector
633 // RA: Not sure what the *10 is for. A correction for pTimestep? 503 // RA: Not sure what the *10 is for. A correction for pTimestep?
634 // m_lastLinearVelocityVector += (addAmount*10); 504 // m_lastLinearVelocityVector += (addAmount*10);
635 m_lastLinearVelocityVector += addAmount; 505 m_lastLinearVelocityVector += addAmount;
636 506
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 507 // 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)) 508 if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X))
641 m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X; 509 m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X;
@@ -644,124 +512,87 @@ namespace OpenSim.Region.Physics.BulletSPlugin
644 if (Math.Abs(m_lastLinearVelocityVector.Z) > Math.Abs(m_linearMotorDirectionLASTSET.Z)) 512 if (Math.Abs(m_lastLinearVelocityVector.Z) > Math.Abs(m_linearMotorDirectionLASTSET.Z))
645 m_lastLinearVelocityVector.Z = m_linearMotorDirectionLASTSET.Z; 513 m_lastLinearVelocityVector.Z = m_linearMotorDirectionLASTSET.Z;
646 514
515 /*
647 // decay applied velocity 516 // decay applied velocity
648 Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep))); 517 Vector3 decayfraction = Vector3.One/(m_linearMotorDecayTimescale / pTimestep);
518 // (RA: do not know where the 0.5f comes from)
649 m_linearMotorDirection -= m_linearMotorDirection * decayfraction * 0.5f; 519 m_linearMotorDirection -= m_linearMotorDirection * decayfraction * 0.5f;
650
651 /*
652 Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/m_linearMotorTimescale;
653 m_lastLinearVelocityVector += addAmount;
654
655 float decayfraction = (1.0f - 1.0f / m_linearMotorDecayTimescale);
656 m_linearMotorDirection *= decayfraction;
657
658 */ 520 */
521 float keepfraction = 1.0f - (1.0f / (m_linearMotorDecayTimescale / pTimestep));
522 m_linearMotorDirection *= keepfraction;
659 523
660 DetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},add={3},decay={4},dir={5},vel={6}", 524 VDetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},add={3},notDecay={4},dir={5},vel={6}",
661 m_prim.LocalID, origDir, origVel, addAmount, decayfraction, m_linearMotorDirection, m_lastLinearVelocityVector); 525 Prim.LocalID, origDir, origVel, addAmount, keepfraction, m_linearMotorDirection, m_lastLinearVelocityVector);
662 } 526 }
663 else 527 else
664 { 528 {
665 // if what remains of applied is small, zero it. 529 // if what remains of direction is very small, zero it.
666 // if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f))
667 // m_lastLinearVelocityVector = Vector3.Zero;
668 m_linearMotorDirection = Vector3.Zero; 530 m_linearMotorDirection = Vector3.Zero;
669 m_lastLinearVelocityVector = Vector3.Zero; 531 m_lastLinearVelocityVector = Vector3.Zero;
532 VDetailLog("{0},MoveLinear,zeroed", Prim.LocalID);
670 } 533 }
671 534
672 // convert requested object velocity to world-referenced vector 535 // convert requested object velocity to object relative vector
673 Quaternion rotq = m_prim.Orientation; 536 Quaternion rotq = Prim.ForceOrientation;
674 m_dir = m_lastLinearVelocityVector * rotq; 537 m_newVelocity = m_lastLinearVelocityVector * rotq;
675 538
676 // Add the various forces into m_dir which will be our new direction vector (velocity) 539 // Add the various forces into m_dir which will be our new direction vector (velocity)
677 540
678 // add Gravity and Buoyancy 541 // 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;
683 // There is some gravity, make a gravity force vector that is applied after object velocity. 542 // There is some gravity, make a gravity force vector that is applied after object velocity.
684 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; 543 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
685 grav.Z = m_prim.Scene.DefaultGravity.Z * m_prim.Mass * (1f - m_VehicleBuoyancy); 544 Vector3 grav = Prim.PhysicsScene.DefaultGravity * (Prim.Linkset.LinksetMass * (1f - m_VehicleBuoyancy));
545
546 /*
547 * RA: Not sure why one would do this
686 // Preserve the current Z velocity 548 // Preserve the current Z velocity
687 Vector3 vel_now = m_prim.Velocity; 549 Vector3 vel_now = m_prim.Velocity;
688 m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity 550 m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity
551 */
689 552
690 Vector3 pos = m_prim.Position; 553 Vector3 pos = Prim.ForcePosition;
691 Vector3 posChange = pos;
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); 554// 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 }
729 555
730 // If below the terrain, move us above the ground a little. 556 // If below the terrain, move us above the ground a little.
731 if (pos.Z < m_prim.Scene.GetTerrainHeightAtXYZ(pos)) 557 float terrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos);
558 // Taking the rotated size doesn't work here because m_prim.Size is the size of the root prim and not the linkset.
559 // Need to add a m_prim.LinkSet.Size similar to m_prim.LinkSet.Mass.
560 // Vector3 rotatedSize = m_prim.Size * m_prim.ForceOrientation;
561 // if (rotatedSize.Z < terrainHeight)
562 if (pos.Z < terrainHeight)
732 { 563 {
733 pos.Z = m_prim.Scene.GetTerrainHeightAtXYZ(pos) + 2; 564 pos.Z = terrainHeight + 2;
734 m_prim.Position = pos; 565 Prim.ForcePosition = pos;
735 DetailLog("{0},MoveLinear,terrainHeight,pos={1}", m_prim.LocalID, pos); 566 VDetailLog("{0},MoveLinear,terrainHeight,terrainHeight={1},pos={2}", Prim.LocalID, terrainHeight, pos);
736 } 567 }
737 568
738 // Check if hovering 569 // Check if hovering
739 if ((m_Hoverflags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) 570 if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0)
740 { 571 {
741 // We should hover, get the target height 572 // We should hover, get the target height
742 if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != 0) 573 if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0)
743 { 574 {
744 m_VhoverTargetHeight = m_prim.Scene.GetWaterLevel() + m_VhoverHeight; 575 m_VhoverTargetHeight = Prim.PhysicsScene.GetWaterLevelAtXYZ(pos) + m_VhoverHeight;
745 } 576 }
746 if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0) 577 if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
747 { 578 {
748 m_VhoverTargetHeight = m_prim.Scene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight; 579 m_VhoverTargetHeight = terrainHeight + m_VhoverHeight;
749 } 580 }
750 if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0) 581 if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0)
751 { 582 {
752 m_VhoverTargetHeight = m_VhoverHeight; 583 m_VhoverTargetHeight = m_VhoverHeight;
753 } 584 }
754 585
755 if ((m_Hoverflags & VehicleFlag.HOVER_UP_ONLY) != 0) 586 if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0)
756 { 587 {
757 // If body is aready heigher, use its height as target height 588 // If body is aready heigher, use its height as target height
758 if (pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z; 589 if (pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z;
759 } 590 }
760 if ((m_Hoverflags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) 591 if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0)
761 { 592 {
762 if ((pos.Z - m_VhoverTargetHeight) > .2 || (pos.Z - m_VhoverTargetHeight) < -.2) 593 if ((pos.Z - m_VhoverTargetHeight) > .2 || (pos.Z - m_VhoverTargetHeight) < -.2)
763 { 594 {
764 m_prim.Position = pos; 595 Prim.ForcePosition = pos;
765 } 596 }
766 } 597 }
767 else 598 else
@@ -770,85 +601,99 @@ namespace OpenSim.Region.Physics.BulletSPlugin
770 // Replace Vertical speed with correction figure if significant 601 // Replace Vertical speed with correction figure if significant
771 if (Math.Abs(herr0) > 0.01f) 602 if (Math.Abs(herr0) > 0.01f)
772 { 603 {
773 m_dir.Z = -((herr0 * pTimestep * 50.0f) / m_VhoverTimescale); 604 m_newVelocity.Z = -((herr0 * pTimestep * 50.0f) / m_VhoverTimescale);
774 //KF: m_VhoverEfficiency is not yet implemented 605 //KF: m_VhoverEfficiency is not yet implemented
775 } 606 }
776 else 607 else
777 { 608 {
778 m_dir.Z = 0f; 609 m_newVelocity.Z = 0f;
779 } 610 }
780 } 611 }
781 612
782 DetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", m_prim.LocalID, pos, m_dir, m_VhoverHeight, m_VhoverTargetHeight); 613 VDetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", Prim.LocalID, pos, m_newVelocity, m_VhoverHeight, m_VhoverTargetHeight);
614 }
783 615
784// m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped 616 Vector3 posChange = pos - m_lastPositionVector;
785// m_VhoverTimescale = 0f; // time to acheive height 617 if (m_BlockingEndPoint != Vector3.Zero)
786// pTimestep is time since last frame,in secs 618 {
619 bool changed = false;
620 if (pos.X >= (m_BlockingEndPoint.X - (float)1))
621 {
622 pos.X -= posChange.X + 1;
623 changed = true;
624 }
625 if (pos.Y >= (m_BlockingEndPoint.Y - (float)1))
626 {
627 pos.Y -= posChange.Y + 1;
628 changed = true;
629 }
630 if (pos.Z >= (m_BlockingEndPoint.Z - (float)1))
631 {
632 pos.Z -= posChange.Z + 1;
633 changed = true;
634 }
635 if (pos.X <= 0)
636 {
637 pos.X += posChange.X + 1;
638 changed = true;
639 }
640 if (pos.Y <= 0)
641 {
642 pos.Y += posChange.Y + 1;
643 changed = true;
644 }
645 if (changed)
646 {
647 Prim.ForcePosition = pos;
648 VDetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}",
649 Prim.LocalID, m_BlockingEndPoint, posChange, pos);
650 }
787 } 651 }
788 652
653 // Limit absolute vertical change
654 float Zchange = Math.Abs(posChange.Z);
789 if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) 655 if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0)
790 { 656 {
791 //Start Experimental Values
792 if (Zchange > .3) 657 if (Zchange > .3)
793 {
794 grav.Z = (float)(grav.Z * 3); 658 grav.Z = (float)(grav.Z * 3);
795 }
796 if (Zchange > .15) 659 if (Zchange > .15)
797 {
798 grav.Z = (float)(grav.Z * 2); 660 grav.Z = (float)(grav.Z * 2);
799 }
800 if (Zchange > .75) 661 if (Zchange > .75)
801 {
802 grav.Z = (float)(grav.Z * 1.5); 662 grav.Z = (float)(grav.Z * 1.5);
803 }
804 if (Zchange > .05) 663 if (Zchange > .05)
805 {
806 grav.Z = (float)(grav.Z * 1.25); 664 grav.Z = (float)(grav.Z * 1.25);
807 }
808 if (Zchange > .025) 665 if (Zchange > .025)
809 {
810 grav.Z = (float)(grav.Z * 1.125); 666 grav.Z = (float)(grav.Z * 1.125);
811 } 667 float postemp = (pos.Z - terrainHeight);
812 float terraintemp = m_prim.Scene.GetTerrainHeightAtXYZ(pos);
813 float postemp = (pos.Z - terraintemp);
814 if (postemp > 2.5f) 668 if (postemp > 2.5f)
815 {
816 grav.Z = (float)(grav.Z * 1.037125); 669 grav.Z = (float)(grav.Z * 1.037125);
817 } 670 VDetailLog("{0},MoveLinear,limitMotorUp,grav={1}", Prim.LocalID, grav);
818 DetailLog("{0},MoveLinear,limitMotorUp,grav={1}", m_prim.LocalID, grav);
819 //End Experimental Values
820 } 671 }
672
673 // If not changing some axis, reduce out velocity
821 if ((m_flags & (VehicleFlag.NO_X)) != 0) 674 if ((m_flags & (VehicleFlag.NO_X)) != 0)
822 { 675 m_newVelocity.X = 0;
823 m_dir.X = 0;
824 }
825 if ((m_flags & (VehicleFlag.NO_Y)) != 0) 676 if ((m_flags & (VehicleFlag.NO_Y)) != 0)
826 { 677 m_newVelocity.Y = 0;
827 m_dir.Y = 0;
828 }
829 if ((m_flags & (VehicleFlag.NO_Z)) != 0) 678 if ((m_flags & (VehicleFlag.NO_Z)) != 0)
830 { 679 m_newVelocity.Z = 0;
831 m_dir.Z = 0;
832 }
833
834 m_lastPositionVector = m_prim.Position;
835 680
836 // Apply velocity 681 // Apply velocity
837 m_prim.Velocity = m_dir; 682 Prim.ForceVelocity = m_newVelocity;
838 // apply gravity force 683 // apply gravity force
839 // Why is this set here? The physics engine already does gravity. 684 // Why is this set here? The physics engine already does gravity.
840 // m_prim.AddForce(grav, false); 685 Prim.AddForce(grav, false, true);
841 // m_prim.Force = grav;
842 686
843 // Apply friction 687 // Apply friction
844 Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep); 688 Vector3 keepFraction = Vector3.One - (Vector3.One / (m_linearFrictionTimescale / pTimestep));
845 m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount; 689 m_lastLinearVelocityVector *= keepFraction;
846 690
847 DetailLog("{0},MoveLinear,done,pos={1},vel={2},force={3},decay={4}", 691 VDetailLog("{0},MoveLinear,done,lmDir={1},lmVel={2},newVel={3},grav={4},1Mdecay={5}",
848 m_prim.LocalID, m_lastPositionVector, m_dir, grav, decayamount); 692 Prim.LocalID, m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity, grav, keepFraction);
849 693
850 } // end MoveLinear() 694 } // end MoveLinear()
851 695
696 // Apply the effect of the angular motor.
852 private void MoveAngular(float pTimestep) 697 private void MoveAngular(float pTimestep)
853 { 698 {
854 // m_angularMotorDirection // angular velocity requested by LSL motor 699 // m_angularMotorDirection // angular velocity requested by LSL motor
@@ -860,7 +705,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
860 // m_lastAngularVelocity // what was last applied to body 705 // m_lastAngularVelocity // what was last applied to body
861 706
862 // Get what the body is doing, this includes 'external' influences 707 // Get what the body is doing, this includes 'external' influences
863 Vector3 angularVelocity = m_prim.RotationalVelocity; 708 Vector3 angularVelocity = Prim.ForceRotationalVelocity;
864 709
865 if (m_angularMotorApply > 0) 710 if (m_angularMotorApply > 0)
866 { 711 {
@@ -868,48 +713,58 @@ namespace OpenSim.Region.Physics.BulletSPlugin
868 // a newly set velocity, this routine steps the value from the previous 713 // a newly set velocity, this routine steps the value from the previous
869 // value (m_angularMotorVelocity) to the requested value (m_angularMotorDirection). 714 // value (m_angularMotorVelocity) to the requested value (m_angularMotorDirection).
870 // There are m_angularMotorApply steps. 715 // There are m_angularMotorApply steps.
871 Vector3 origAngularVelocity = m_angularMotorVelocity; 716 Vector3 origVel = m_angularMotorVelocity;
717 Vector3 origDir = m_angularMotorDirection;
718
872 // ramp up to new value 719 // ramp up to new value
873 // current velocity += error / (time to get there / step interval) 720 // new velocity += error / ( time to get there / step interval)
874 // requested speed - last motor speed 721 // requested speed - last motor speed
875 m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / pTimestep); 722 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); 723 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); 724 m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep);
878 725
879 DetailLog("{0},MoveAngular,angularMotorApply,apply={1},origvel={2},dir={3},vel={4}", 726 VDetailLog("{0},MoveAngular,angularMotorApply,apply={1},angTScale={2},timeStep={3},origvel={4},origDir={5},vel={6}",
880 m_prim.LocalID,m_angularMotorApply,origAngularVelocity, m_angularMotorDirection, m_angularMotorVelocity); 727 Prim.LocalID, m_angularMotorApply, m_angularMotorTimescale, pTimestep, origVel, origDir, m_angularMotorVelocity);
881 728
882 m_angularMotorApply--; // This is done so that if script request rate is less than phys frame rate the expected 729 m_angularMotorApply--;
883 // velocity may still be acheived.
884 } 730 }
885 else 731 else
886 { 732 {
887 // No motor recently applied, keep the body velocity 733 // No motor recently applied, keep the body velocity
888 // and decay the velocity 734 // and decay the velocity
889 m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep); 735 m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep);
736 if (m_angularMotorVelocity.LengthSquared() < 0.00001)
737 m_angularMotorVelocity = Vector3.Zero;
890 } // end motor section 738 } // end motor section
891 739
892 // Vertical attractor section 740 // Vertical attractor section
893 Vector3 vertattr = Vector3.Zero; 741 Vector3 vertattr = Vector3.Zero;
894 if (m_verticalAttractionTimescale < 300) 742 Vector3 deflection = Vector3.Zero;
743 Vector3 banking = Vector3.Zero;
744
745 if (m_verticalAttractionTimescale < 300 && m_lastAngularVelocity != Vector3.Zero)
895 { 746 {
896 float VAservo = 0.2f / (m_verticalAttractionTimescale * pTimestep); 747 float VAservo = 0.2f / (m_verticalAttractionTimescale / pTimestep);
748 VAservo *= (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency);
749
897 // get present body rotation 750 // get present body rotation
898 Quaternion rotq = m_prim.Orientation; 751 Quaternion rotq = Prim.ForceOrientation;
899 // make a vector pointing up 752 // vector pointing up
900 Vector3 verterr = Vector3.Zero; 753 Vector3 verterr = Vector3.Zero;
901 verterr.Z = 1.0f; 754 verterr.Z = 1.0f;
755
902 // rotate it to Body Angle 756 // rotate it to Body Angle
903 verterr = verterr * rotq; 757 verterr = verterr * rotq;
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. 758 // verterr.X and .Y are the World error amounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1.
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 759 // 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
906 // negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body. 760 // negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body.
761
762 // Error is 0 (no error) to +/- 2 (max error)
907 if (verterr.Z < 0.0f) 763 if (verterr.Z < 0.0f)
908 { 764 {
909 verterr.X = 2.0f - verterr.X; 765 verterr.X = 2.0f - verterr.X;
910 verterr.Y = 2.0f - verterr.Y; 766 verterr.Y = 2.0f - verterr.Y;
911 } 767 }
912 // Error is 0 (no error) to +/- 2 (max error)
913 // scale it by VAservo 768 // scale it by VAservo
914 verterr = verterr * VAservo; 769 verterr = verterr * VAservo;
915 770
@@ -924,12 +779,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
924 vertattr.X += bounce * angularVelocity.X; 779 vertattr.X += bounce * angularVelocity.X;
925 vertattr.Y += bounce * angularVelocity.Y; 780 vertattr.Y += bounce * angularVelocity.Y;
926 781
927 DetailLog("{0},MoveAngular,verticalAttraction,verterr={1},bounce={2},vertattr={3}", 782 VDetailLog("{0},MoveAngular,verticalAttraction,verterr={1},bounce={2},vertattr={3}",
928 m_prim.LocalID, verterr, bounce, vertattr); 783 Prim.LocalID, verterr, bounce, vertattr);
929 784
930 } // else vertical attractor is off 785 } // else vertical attractor is off
931 786
932 // m_lastVertAttractor = vertattr; 787 m_lastVertAttractor = vertattr;
933 788
934 // Bank section tba 789 // Bank section tba
935 790
@@ -937,18 +792,18 @@ namespace OpenSim.Region.Physics.BulletSPlugin
937 792
938 // Sum velocities 793 // Sum velocities
939 m_lastAngularVelocity = m_angularMotorVelocity + vertattr; // + bank + deflection 794 m_lastAngularVelocity = m_angularMotorVelocity + vertattr; // + bank + deflection
940 795
941 if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) 796 if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0)
942 { 797 {
943 m_lastAngularVelocity.X = 0; 798 m_lastAngularVelocity.X = 0;
944 m_lastAngularVelocity.Y = 0; 799 m_lastAngularVelocity.Y = 0;
945 DetailLog("{0},MoveAngular,noDeflectionUp,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity); 800 VDetailLog("{0},MoveAngular,noDeflectionUp,lastAngular={1}", Prim.LocalID, m_lastAngularVelocity);
946 } 801 }
947 802
948 if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f)) 803 if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f))
949 { 804 {
950 m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero. 805 m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero.
951 DetailLog("{0},MoveAngular,zeroSmallValues,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity); 806 VDetailLog("{0},MoveAngular,zeroSmallValues,lastAngular={1}", Prim.LocalID, m_lastAngularVelocity);
952 } 807 }
953 808
954 // apply friction 809 // apply friction
@@ -956,14 +811,14 @@ namespace OpenSim.Region.Physics.BulletSPlugin
956 m_lastAngularVelocity -= m_lastAngularVelocity * decayamount; 811 m_lastAngularVelocity -= m_lastAngularVelocity * decayamount;
957 812
958 // Apply to the body 813 // Apply to the body
959 m_prim.RotationalVelocity = m_lastAngularVelocity; 814 Prim.ForceRotationalVelocity = m_lastAngularVelocity;
960 815
961 DetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", m_prim.LocalID, decayamount, m_lastAngularVelocity); 816 VDetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", Prim.LocalID, decayamount, m_lastAngularVelocity);
962 } //end MoveAngular 817 } //end MoveAngular
963 818
964 internal void LimitRotation(float timestep) 819 internal void LimitRotation(float timestep)
965 { 820 {
966 Quaternion rotq = m_prim.Orientation; 821 Quaternion rotq = Prim.ForceOrientation;
967 Quaternion m_rot = rotq; 822 Quaternion m_rot = rotq;
968 bool changed = false; 823 bool changed = false;
969 if (m_RollreferenceFrame != Quaternion.Identity) 824 if (m_RollreferenceFrame != Quaternion.Identity)
@@ -996,23 +851,19 @@ namespace OpenSim.Region.Physics.BulletSPlugin
996 m_rot.Y = 0; 851 m_rot.Y = 0;
997 changed = true; 852 changed = true;
998 } 853 }
999 if ((m_flags & VehicleFlag.LOCK_ROTATION) != 0) 854 if (changed)
1000 { 855 {
1001 m_rot.X = 0; 856 Prim.ForceOrientation = m_rot;
1002 m_rot.Y = 0; 857 VDetailLog("{0},LimitRotation,done,orig={1},new={2}", Prim.LocalID, rotq, m_rot);
1003 changed = true;
1004 } 858 }
1005 if (changed)
1006 m_prim.Orientation = m_rot;
1007 859
1008 DetailLog("{0},LimitRotation,done,changed={1},orig={2},new={3}", m_prim.LocalID, changed, rotq, m_rot);
1009 } 860 }
1010 861
1011 // Invoke the detailed logger and output something if it's enabled. 862 // Invoke the detailed logger and output something if it's enabled.
1012 private void DetailLog(string msg, params Object[] args) 863 private void VDetailLog(string msg, params Object[] args)
1013 { 864 {
1014 if (m_prim.Scene.VehicleLoggingEnabled) 865 if (Prim.PhysicsScene.VehicleLoggingEnabled)
1015 m_prim.Scene.PhysicsLogging.Write(msg, args); 866 Prim.PhysicsScene.DetailLog(msg, args);
1016 } 867 }
1017 } 868 }
1018} 869}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs
index d68048b..7c8a215 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs
@@ -1,55 +1,57 @@
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
35class BSHingeConstraint : BSConstraint 35class BSHingeConstraint : BSConstraint
36{ 36{
37 public BSHingeConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, 37 public override ConstraintType Type { get { return ConstraintType.HINGE_CONSTRAINT_TYPE; } }
38 Vector3 pivotInA, Vector3 pivotInB, 38
39 Vector3 axisInA, Vector3 axisInB, 39 public BSHingeConstraint(BulletSim world, BulletBody obj1, BulletBody obj2,
40 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) 40 Vector3 pivotInA, Vector3 pivotInB,
41 { 41 Vector3 axisInA, Vector3 axisInB,
42 m_world = world; 42 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
43 m_body1 = obj1; 43 {
44 m_body2 = obj2; 44 m_world = world;
45 m_constraint = new BulletConstraint( 45 m_body1 = obj1;
46 BulletSimAPI.CreateHingeConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr, 46 m_body2 = obj2;
47 pivotInA, pivotInB, 47 m_constraint = new BulletConstraint(
48 axisInA, axisInB, 48 BulletSimAPI.CreateHingeConstraint2(m_world.ptr, m_body1.ptr, m_body2.ptr,
49 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); 49 pivotInA, pivotInB,
50 m_enabled = true; 50 axisInA, axisInB,
51 } 51 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
52 52 m_enabled = true;
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 087b9bb..c984824 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -32,29 +32,56 @@ using OMV = OpenMetaverse;
32 32
33namespace OpenSim.Region.Physics.BulletSPlugin 33namespace OpenSim.Region.Physics.BulletSPlugin
34{ 34{
35public class BSLinkset 35public abstract class BSLinkset
36{ 36{
37 private static string LogHeader = "[BULLETSIM LINKSET]"; 37 // private static string LogHeader = "[BULLETSIM LINKSET]";
38 38
39 private BSPrim m_linksetRoot; 39 // Create the correct type of linkset for this child
40 public BSPrim LinksetRoot { get { return m_linksetRoot; } } 40 public static BSLinkset Factory(BSScene physScene, BSPhysObject parent)
41 {
42 BSLinkset ret = null;
43 /*
44 if (parent.IsPhysical)
45 ret = new BSLinksetConstraints(physScene, parent);
46 else
47 ret = new BSLinksetManual(physScene, parent);
48 */
49
50 // at the moment, there is only one
51 ret = new BSLinksetConstraints(physScene, parent);
52
53 return ret;
54 }
55
56 public BSPhysObject LinksetRoot { get; protected set; }
57
58 public BSScene PhysicsScene { get; private set; }
41 59
42 private BSScene m_physicsScene; 60 static int m_nextLinksetID = 1;
43 public BSScene PhysicsScene { get { return m_physicsScene; } } 61 public int LinksetID { get; private set; }
44 62
45 // The children under the root in this linkset 63 // The children under the root in this linkset.
46 private List<BSPrim> m_children; 64 // There are two lists of children: the current children at runtime
65 // and the children at taint-time. For instance, if you delink a
66 // child from the linkset, the child is removed from m_children
67 // but the constraint won't be removed until taint time.
68 // Two lists lets this track the 'current' children and
69 // the physical 'taint' children separately.
70 // After taint processing and before the simulation step, these
71 // two lists must be the same.
72 protected HashSet<BSPhysObject> m_children;
73 protected HashSet<BSPhysObject> m_taintChildren;
47 74
48 // We lock the diddling of linkset classes to prevent any badness. 75 // We lock the diddling of linkset classes to prevent any badness.
49 // This locks the modification of the instances of this class. Changes 76 // This locks the modification of the instances of this class. Changes
50 // to the physical representation is done via the tainting mechenism. 77 // to the physical representation is done via the tainting mechenism.
51 private object m_linksetActivityLock = new Object(); 78 protected object m_linksetActivityLock = new Object();
52 79
53 // We keep the prim's mass in the linkset structure since it could be dependent on other prims 80 // We keep the prim's mass in the linkset structure since it could be dependent on other prims
54 private float m_mass; 81 protected float m_mass;
55 public float LinksetMass 82 public float LinksetMass
56 { 83 {
57 get 84 get
58 { 85 {
59 m_mass = ComputeLinksetMass(); 86 m_mass = ComputeLinksetMass();
60 return m_mass; 87 return m_mass;
@@ -71,23 +98,31 @@ public class BSLinkset
71 get { return ComputeLinksetGeometricCenter(); } 98 get { return ComputeLinksetGeometricCenter(); }
72 } 99 }
73 100
74 public BSLinkset(BSScene scene, BSPrim parent) 101 protected void Initialize(BSScene scene, BSPhysObject parent)
75 { 102 {
76 // A simple linkset of one (no children) 103 // A simple linkset of one (no children)
77 m_physicsScene = scene; 104 LinksetID = m_nextLinksetID++;
78 m_linksetRoot = parent; 105 // We create LOTS of linksets.
79 m_children = new List<BSPrim>(); 106 if (m_nextLinksetID <= 0)
107 m_nextLinksetID = 1;
108 PhysicsScene = scene;
109 LinksetRoot = parent;
110 m_children = new HashSet<BSPhysObject>();
111 m_taintChildren = new HashSet<BSPhysObject>();
80 m_mass = parent.MassRaw; 112 m_mass = parent.MassRaw;
81 } 113 }
82 114
83 // Link to a linkset where the child knows the parent. 115 // Link to a linkset where the child knows the parent.
84 // Parent changing should not happen so do some sanity checking. 116 // Parent changing should not happen so do some sanity checking.
85 // We return the parent's linkset so the child can track its membership. 117 // We return the parent's linkset so the child can track its membership.
86 public BSLinkset AddMeToLinkset(BSPrim child) 118 // Called at runtime.
119 public BSLinkset AddMeToLinkset(BSPhysObject child)
87 { 120 {
88 lock (m_linksetActivityLock) 121 lock (m_linksetActivityLock)
89 { 122 {
90 AddChildToLinkset(child); 123 // Don't add the root to its own linkset
124 if (!IsRoot(child))
125 AddChildToLinkset(child);
91 } 126 }
92 return this; 127 return this;
93 } 128 }
@@ -95,36 +130,28 @@ public class BSLinkset
95 // Remove a child from a linkset. 130 // Remove a child from a linkset.
96 // Returns a new linkset for the child which is a linkset of one (just the 131 // Returns a new linkset for the child which is a linkset of one (just the
97 // orphened child). 132 // orphened child).
98 public BSLinkset RemoveMeFromLinkset(BSPrim child) 133 // Called at runtime.
134 public BSLinkset RemoveMeFromLinkset(BSPhysObject child)
99 { 135 {
100 lock (m_linksetActivityLock) 136 lock (m_linksetActivityLock)
101 { 137 {
102 if (IsRoot(child)) 138 if (IsRoot(child))
103 { 139 {
104 // if root of linkset, take the linkset apart 140 // Cannot remove the root from a linkset.
105 while (m_children.Count > 0) 141 return this;
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);
117 } 142 }
143
144 RemoveChildFromLinkset(child);
118 } 145 }
119 146
120 // The child is down to a linkset of just itself 147 // The child is down to a linkset of just itself
121 return new BSLinkset(PhysicsScene, child); 148 return BSLinkset.Factory(PhysicsScene, child);
122 } 149 }
123 150
124 // Return 'true' if the passed object is the root object of this linkset 151 // Return 'true' if the passed object is the root object of this linkset
125 public bool IsRoot(BSPrim requestor) 152 public bool IsRoot(BSPhysObject requestor)
126 { 153 {
127 return (requestor.LocalID == m_linksetRoot.LocalID); 154 return (requestor.LocalID == LinksetRoot.LocalID);
128 } 155 }
129 156
130 public int NumberOfChildren { get { return m_children.Count; } } 157 public int NumberOfChildren { get { return m_children.Count; } }
@@ -133,12 +160,15 @@ public class BSLinkset
133 public bool HasAnyChildren { get { return (m_children.Count > 0); } } 160 public bool HasAnyChildren { get { return (m_children.Count > 0); } }
134 161
135 // Return 'true' if this child is in this linkset 162 // Return 'true' if this child is in this linkset
136 public bool HasChild(BSPrim child) 163 public bool HasChild(BSPhysObject child)
137 { 164 {
138 bool ret = false; 165 bool ret = false;
139 lock (m_linksetActivityLock) 166 lock (m_linksetActivityLock)
140 { 167 {
141 foreach (BSPrim bp in m_children) 168 if (m_children.Contains(child))
169 ret = true;
170 /*
171 foreach (BSPhysObject bp in m_children)
142 { 172 {
143 if (child.LocalID == bp.LocalID) 173 if (child.LocalID == bp.LocalID)
144 { 174 {
@@ -146,28 +176,73 @@ public class BSLinkset
146 break; 176 break;
147 } 177 }
148 } 178 }
179 */
149 } 180 }
150 return ret; 181 return ret;
151 } 182 }
152 183
153 private float ComputeLinksetMass() 184 // When physical properties are changed the linkset needs to recalculate
185 // its internal properties.
186 // May be called at runtime or taint-time (just pass the appropriate flag).
187 public abstract void Refresh(BSPhysObject requestor, bool inTaintTime);
188
189 // The object is going dynamic (physical). Do any setup necessary
190 // for a dynamic linkset.
191 // Only the state of the passed object can be modified. The rest of the linkset
192 // has not yet been fully constructed.
193 // Return 'true' if any properties updated on the passed object.
194 // Called at taint-time!
195 public abstract bool MakeDynamic(BSPhysObject child);
196
197 // The object is going static (non-physical). Do any setup necessary
198 // for a static linkset.
199 // Return 'true' if any properties updated on the passed object.
200 // Called at taint-time!
201 public abstract bool MakeStatic(BSPhysObject child);
202
203 // Called when a parameter update comes from the physics engine for any object
204 // of the linkset is received.
205 // Called at taint-time!!
206 public abstract void UpdateProperties(BSPhysObject physObject);
207
208 // Routine used when rebuilding the body of the root of the linkset
209 // Destroy all the constraints have have been made to root.
210 // This is called when the root body is changing.
211 // Returns 'true' of something was actually removed and would need restoring
212 // Called at taint-time!!
213 public abstract bool RemoveBodyDependencies(BSPrim child);
214
215 // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true',
216 // this routine will restore the removed constraints.
217 // Called at taint-time!!
218 public abstract void RestoreBodyDependencies(BSPrim child);
219
220 // ================================================================
221 // Below this point is internal magic
222
223 protected virtual float ComputeLinksetMass()
154 { 224 {
155 float mass = m_linksetRoot.MassRaw; 225 float mass;
156 foreach (BSPrim bp in m_children) 226 lock (m_linksetActivityLock)
157 { 227 {
158 mass += bp.MassRaw; 228 mass = LinksetRoot.MassRaw;
229 foreach (BSPhysObject bp in m_taintChildren)
230 {
231 mass += bp.MassRaw;
232 }
159 } 233 }
160 return mass; 234 return mass;
161 } 235 }
162 236
163 private OMV.Vector3 ComputeLinksetCenterOfMass() 237 protected virtual OMV.Vector3 ComputeLinksetCenterOfMass()
164 { 238 {
165 OMV.Vector3 com = m_linksetRoot.Position * m_linksetRoot.MassRaw; 239 OMV.Vector3 com;
166 float totalMass = m_linksetRoot.MassRaw;
167
168 lock (m_linksetActivityLock) 240 lock (m_linksetActivityLock)
169 { 241 {
170 foreach (BSPrim bp in m_children) 242 com = LinksetRoot.Position * LinksetRoot.MassRaw;
243 float totalMass = LinksetRoot.MassRaw;
244
245 foreach (BSPhysObject bp in m_taintChildren)
171 { 246 {
172 com += bp.Position * bp.MassRaw; 247 com += bp.Position * bp.MassRaw;
173 totalMass += bp.MassRaw; 248 totalMass += bp.MassRaw;
@@ -179,241 +254,43 @@ public class BSLinkset
179 return com; 254 return com;
180 } 255 }
181 256
182 private OMV.Vector3 ComputeLinksetGeometricCenter() 257 protected virtual OMV.Vector3 ComputeLinksetGeometricCenter()
183 { 258 {
184 OMV.Vector3 com = m_linksetRoot.Position; 259 OMV.Vector3 com;
185
186 lock (m_linksetActivityLock) 260 lock (m_linksetActivityLock)
187 { 261 {
188 foreach (BSPrim bp in m_children) 262 com = LinksetRoot.Position;
263
264 foreach (BSPhysObject bp in m_taintChildren)
189 { 265 {
190 com += bp.Position * bp.MassRaw; 266 com += bp.Position * bp.MassRaw;
191 } 267 }
192 com /= (m_children.Count + 1); 268 com /= (m_taintChildren.Count + 1);
193 } 269 }
194 270
195 return com; 271 return com;
196 } 272 }
197 273
198 // When physical properties are changed the linkset needs to recalculate
199 // its internal properties.
200 public void Refresh(BSPrim requestor)
201 {
202 // If there are no children, there aren't any constraints to recompute
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)
225 {
226 foreach (BSPrim child in m_children)
227 {
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
236 {
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);
243 }
244 }
245 }
246 return false;
247 }
248
249 // I am the root of a linkset and a new child is being added 274 // I am the root of a linkset and a new child is being added
250 // Called while LinkActivity is locked. 275 // Called while LinkActivity is locked.
251 private void AddChildToLinkset(BSPrim child) 276 protected abstract void AddChildToLinkset(BSPhysObject child);
252 {
253 if (!HasChild(child))
254 {
255 m_children.Add(child);
256
257 BSPrim rootx = LinksetRoot; // capture the root as of now
258 BSPrim childx = child;
259 m_physicsScene.TaintedObject("AddChildToLinkset", delegate()
260 {
261 // DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, m_linksetRoot.LocalID);
262 // DetailLog("{0},AddChildToLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
263 PhysicallyLinkAChildToRoot(rootx, childx); // build the physical binding between me and the child
264 });
265 }
266 return;
267 }
268 277
269 // Forcefully removing a child from a linkset. 278 // 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 279 // 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. 280 // it's still connected to the linkset.
272 // Normal OpenSimulator operation will never do this because other SceneObjectPart information 281 // Normal OpenSimulator operation will never do this because other SceneObjectPart information
273 // has to be updated also (like pointer to prim's parent). 282 // also has to be updated (like pointer to prim's parent).
274 private void RemoveChildFromOtherLinkset(BSPrim pchild) 283 protected abstract void RemoveChildFromOtherLinkset(BSPhysObject pchild);
275 {
276 pchild.Linkset = new BSLinkset(m_physicsScene, pchild);
277 RemoveChildFromLinkset(pchild);
278 }
279 284
280 // I am the root of a linkset and one of my children is being removed. 285 // 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. 286 // Safe to call even if the child is not really in my linkset.
282 private void RemoveChildFromLinkset(BSPrim child) 287 protected abstract void RemoveChildFromLinkset(BSPhysObject child);
283 {
284 if (m_children.Remove(child))
285 {
286 BSPrim rootx = LinksetRoot; // capture the root as of now
287 BSPrim childx = child;
288 m_physicsScene.TaintedObject("RemoveChildFromLinkset", delegate()
289 {
290 // DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID);
291 // DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
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);
302 }
303 return;
304 }
305
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);
411 }
412 288
413 // Invoke the detailed logger and output something if it's enabled. 289 // Invoke the detailed logger and output something if it's enabled.
414 private void DetailLog(string msg, params Object[] args) 290 protected void DetailLog(string msg, params Object[] args)
415 { 291 {
416 m_physicsScene.PhysicsLogging.Write(msg, args); 292 if (PhysicsScene.PhysicsLogging.Enabled)
293 PhysicsScene.DetailLog(msg, args);
417 } 294 }
418 295
419} 296}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
new file mode 100755
index 0000000..8a750b5
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
@@ -0,0 +1,385 @@
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 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 // May be called at runtime or taint-time (just pass the appropriate flag).
47 public override void Refresh(BSPhysObject requestor, bool inTaintTime)
48 {
49 // If there are no children or not root, I am not the one that recomputes the constraints
50 if (!HasAnyChildren || !IsRoot(requestor))
51 return;
52
53 BSScene.TaintCallback refreshOperation = delegate()
54 {
55 RecomputeLinksetConstraintVariables();
56 DetailLog("{0},BSLinkset.Refresh,complete,rBody={1}",
57 LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"));
58 };
59 if (inTaintTime)
60 refreshOperation();
61 else
62 PhysicsScene.TaintedObject("BSLinkSet.Refresh", refreshOperation);
63 }
64
65 // The object is going dynamic (physical). Do any setup necessary
66 // for a dynamic linkset.
67 // Only the state of the passed object can be modified. The rest of the linkset
68 // has not yet been fully constructed.
69 // Return 'true' if any properties updated on the passed object.
70 // Called at taint-time!
71 public override bool MakeDynamic(BSPhysObject child)
72 {
73 // What is done for each object in BSPrim is what we want.
74 return false;
75 }
76
77 // The object is going static (non-physical). Do any setup necessary
78 // for a static linkset.
79 // Return 'true' if any properties updated on the passed object.
80 // Called at taint-time!
81 public override bool MakeStatic(BSPhysObject child)
82 {
83 // What is done for each object in BSPrim is what we want.
84 return false;
85 }
86
87 // Called at taint-time!!
88 public override void UpdateProperties(BSPhysObject updated)
89 {
90 // Nothing to do for constraints on property updates
91 }
92
93 // Routine used when rebuilding the body of the root of the linkset
94 // Destroy all the constraints have have been made to root.
95 // This is called when the root body is changing.
96 // Returns 'true' of something eas actually removed and would need restoring
97 // Called at taint-time!!
98 public override bool RemoveBodyDependencies(BSPrim child)
99 {
100 bool ret = false;
101
102 lock (m_linksetActivityLock)
103 {
104 if (IsRoot(child))
105 {
106 // If the one with the dependency is root, must undo all children
107 DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}",
108 child.LocalID, LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"));
109
110 ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot);
111 }
112 else
113 {
114 DetailLog("{0},BSLinkset.RemoveBodyDependencies,removeSingleChild,rID={1},rBody={2},cID={3},cBody={4}",
115 child.LocalID,
116 LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"),
117 child.LocalID, child.BSBody.ptr.ToString("X"));
118 // ret = PhysicallyUnlinkAChildFromRoot(LinksetRoot, child);
119 // Despite the function name, this removes any link to the specified object.
120 ret = PhysicallyUnlinkAllChildrenFromRoot(child);
121 }
122 }
123 return ret;
124 }
125
126 // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true',
127 // this routine will restore the removed constraints.
128 // Called at taint-time!!
129 public override void RestoreBodyDependencies(BSPrim child)
130 {
131 lock (m_linksetActivityLock)
132 {
133 if (IsRoot(child))
134 {
135 DetailLog("{0},BSLinkset.RestoreBodyDependencies,restoreChildrenForRoot,rID={1},numChild={2}",
136 child.LocalID, LinksetRoot.LocalID, m_taintChildren.Count);
137 foreach (BSPhysObject bpo in m_taintChildren)
138 {
139 PhysicallyLinkAChildToRoot(LinksetRoot, bpo);
140 }
141 }
142 else
143 {
144 DetailLog("{0},BSLinkset.RestoreBodyDependencies,restoreSingleChild,rID={1},rBody={2},cID={3},cBody={4}",
145 LinksetRoot.LocalID,
146 LinksetRoot.LocalID, LinksetRoot.BSBody.ptr.ToString("X"),
147 child.LocalID, child.BSBody.ptr.ToString("X"));
148 PhysicallyLinkAChildToRoot(LinksetRoot, child);
149 }
150 }
151 }
152
153 // ================================================================
154 // Below this point is internal magic
155
156 // I am the root of a linkset and a new child is being added
157 // Called while LinkActivity is locked.
158 protected override void AddChildToLinkset(BSPhysObject child)
159 {
160 if (!HasChild(child))
161 {
162 m_children.Add(child);
163
164 BSPhysObject rootx = LinksetRoot; // capture the root as of now
165 BSPhysObject childx = child;
166
167 DetailLog("{0},AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID);
168
169 PhysicsScene.TaintedObject("AddChildToLinkset", delegate()
170 {
171 DetailLog("{0},AddChildToLinkset,taint,rID={1},rBody={2},cID={3},cBody={4}",
172 rootx.LocalID,
173 rootx.LocalID, rootx.BSBody.ptr.ToString("X"),
174 childx.LocalID, childx.BSBody.ptr.ToString("X"));
175 // Since this is taint-time, the body and shape could have changed for the child
176 rootx.ForcePosition = rootx.Position; // DEBUG
177 childx.ForcePosition = childx.Position; // DEBUG
178 PhysicallyLinkAChildToRoot(rootx, childx);
179 m_taintChildren.Add(child);
180 });
181 }
182 return;
183 }
184
185 // Forcefully removing a child from a linkset.
186 // This is not being called by the child so we have to make sure the child doesn't think
187 // it's still connected to the linkset.
188 // Normal OpenSimulator operation will never do this because other SceneObjectPart information
189 // also has to be updated (like pointer to prim's parent).
190 protected override void RemoveChildFromOtherLinkset(BSPhysObject pchild)
191 {
192 pchild.Linkset = BSLinkset.Factory(PhysicsScene, pchild);
193 RemoveChildFromLinkset(pchild);
194 }
195
196 // I am the root of a linkset and one of my children is being removed.
197 // Safe to call even if the child is not really in my linkset.
198 protected override void RemoveChildFromLinkset(BSPhysObject child)
199 {
200 if (m_children.Remove(child))
201 {
202 BSPhysObject rootx = LinksetRoot; // capture the root and body as of now
203 BSPhysObject childx = child;
204
205 DetailLog("{0},RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}",
206 childx.LocalID,
207 rootx.LocalID, rootx.BSBody.ptr.ToString("X"),
208 childx.LocalID, childx.BSBody.ptr.ToString("X"));
209
210 PhysicsScene.TaintedObject("RemoveChildFromLinkset", delegate()
211 {
212 m_taintChildren.Remove(child);
213 PhysicallyUnlinkAChildFromRoot(rootx, childx);
214 RecomputeLinksetConstraintVariables();
215 });
216
217 }
218 else
219 {
220 // This will happen if we remove the root of the linkset first. Non-fatal occurance.
221 // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader);
222 }
223 return;
224 }
225
226 // Create a constraint between me (root of linkset) and the passed prim (the child).
227 // Called at taint time!
228 private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BSPhysObject childPrim)
229 {
230 // Zero motion for children so they don't interpolate
231 childPrim.ZeroMotion();
232
233 // Relative position normalized to the root prim
234 // Essentually a vector pointing from center of rootPrim to center of childPrim
235 OMV.Vector3 childRelativePosition = childPrim.Position - rootPrim.Position;
236
237 // real world coordinate of midpoint between the two objects
238 OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2);
239
240 DetailLog("{0},BSLinkset.PhysicallyLinkAChildToRoot,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}",
241 rootPrim.LocalID,
242 rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"),
243 childPrim.LocalID, childPrim.BSBody.ptr.ToString("X"),
244 rootPrim.Position, childPrim.Position, midPoint);
245
246 // create a constraint that allows no freedom of movement between the two objects
247 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
248
249 BS6DofConstraint constrain = new BS6DofConstraint(
250 PhysicsScene.World, rootPrim.BSBody, childPrim.BSBody, midPoint, true, true );
251
252 /* NOTE: below is an attempt to build constraint with full frame computation, etc.
253 * Using the midpoint is easier since it lets the Bullet code manipulate the transforms
254 * of the objects.
255 * Code left as a warning to future programmers.
256 // ==================================================================================
257 // relative position normalized to the root prim
258 OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation);
259 OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation;
260
261 // relative rotation of the child to the parent
262 OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation;
263 OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation);
264
265 // create a constraint that allows no freedom of movement between the two objects
266 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
267 DetailLog("{0},BSLinkset.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
268 BS6DofConstraint constrain = new BS6DofConstraint(
269 PhysicsScene.World, rootPrim.Body, childPrim.Body,
270 OMV.Vector3.Zero,
271 OMV.Quaternion.Inverse(rootPrim.Orientation),
272 OMV.Vector3.Zero,
273 OMV.Quaternion.Inverse(childPrim.Orientation),
274 // A point half way between the parent and child
275 // childRelativePosition/2,
276 // childRelativeRotation,
277 // childRelativePosition/2,
278 // inverseChildRelativeRotation,
279 true,
280 true
281 );
282 // ==================================================================================
283 */
284
285 PhysicsScene.Constraints.AddConstraint(constrain);
286
287 // zero linear and angular limits makes the objects unable to move in relation to each other
288 constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
289 constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
290
291 // tweek the constraint to increase stability
292 constrain.UseFrameOffset(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintUseFrameOffset));
293 constrain.TranslationalLimitMotor(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintEnableTransMotor),
294 PhysicsScene.Params.linkConstraintTransMotorMaxVel,
295 PhysicsScene.Params.linkConstraintTransMotorMaxForce);
296 constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP);
297 if (PhysicsScene.Params.linkConstraintSolverIterations != 0f)
298 {
299 constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations);
300 }
301 }
302
303 // Remove linkage between myself and a particular child
304 // The root and child bodies are passed in because we need to remove the constraint between
305 // the bodies that were at unlink time.
306 // Called at taint time!
307 private bool PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BSPhysObject childPrim)
308 {
309 bool ret = false;
310 DetailLog("{0},BSLinkset.PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}",
311 rootPrim.LocalID,
312 rootPrim.LocalID, rootPrim.BSBody.ptr.ToString("X"),
313 childPrim.LocalID, childPrim.BSBody.ptr.ToString("X"));
314
315 // Find the constraint for this link and get rid of it from the overall collection and from my list
316 if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody, childPrim.BSBody))
317 {
318 // Make the child refresh its location
319 BulletSimAPI.PushUpdate2(childPrim.BSBody.ptr);
320 ret = true;
321 }
322
323 return ret;
324 }
325
326 // Remove linkage between myself and any possible children I might have.
327 // Called at taint time!
328 private bool PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim)
329 {
330 DetailLog("{0},BSLinkset.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID);
331 bool ret = false;
332
333 if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.BSBody))
334 {
335 ret = true;
336 }
337 return ret;
338 }
339
340 // Call each of the constraints that make up this linkset and recompute the
341 // various transforms and variables. Used when objects are added or removed
342 // from a linkset to make sure the constraints know about the new mass and
343 // geometry.
344 // Must only be called at taint time!!
345 private void RecomputeLinksetConstraintVariables()
346 {
347 float linksetMass = LinksetMass;
348 foreach (BSPhysObject child in m_taintChildren)
349 {
350 BSConstraint constrain;
351 if (PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.BSBody, child.BSBody, out constrain))
352 {
353 // DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}",
354 // LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID);
355 constrain.RecomputeConstraintVariables(linksetMass);
356 }
357 else
358 {
359 // Non-fatal error that happens when children are being added to the linkset but
360 // their constraints have not been created yet.
361 break;
362 }
363 }
364
365 // If the whole linkset is not here, doesn't make sense to recompute linkset wide values
366 if (m_children.Count == m_taintChildren.Count)
367 {
368 // If this is a multiple object linkset, set everybody's center of mass to the set's center of mass
369 OMV.Vector3 centerOfMass = ComputeLinksetCenterOfMass();
370 BulletSimAPI.SetCenterOfMassByPosRot2(LinksetRoot.BSBody.ptr,
371 centerOfMass, OMV.Quaternion.Identity);
372 DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,setCenterOfMass,COM={1},rBody={2}",
373 LinksetRoot.LocalID, centerOfMass, LinksetRoot.BSBody.ptr.ToString("X"));
374 foreach (BSPhysObject child in m_taintChildren)
375 {
376 BulletSimAPI.SetCenterOfMassByPosRot2(child.BSBody.ptr,
377 centerOfMass, OMV.Quaternion.Identity);
378 }
379
380 // BulletSimAPI.DumpAllInfo2(PhysicsScene.World.ptr); // DEBUG DEBUG DEBUG
381 }
382 return;
383 }
384}
385}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
new file mode 100755
index 0000000..538f905
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
@@ -0,0 +1,238 @@
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 MassRaw { get; }
67
68 // Reference to the physical body (btCollisionObject) of this object
69 public BulletBody BSBody;
70 // Reference to the physical shape (btCollisionShape) of this object
71 public BulletShape BSShape;
72
73 // 'true' if the mesh's underlying asset failed to build.
74 // This will keep us from looping after the first time the build failed.
75 public bool LastAssetBuildFailed { get; set; }
76
77 // The objects base shape information. Null if not a prim type shape.
78 public PrimitiveBaseShape BaseShape { get; protected set; }
79
80 // When the physical properties are updated, an EntityProperty holds the update values.
81 // Keep the current and last EntityProperties to enable computation of differences
82 // between the current update and the previous values.
83 public EntityProperties CurrentEntityProperties { get; set; }
84 public EntityProperties LastEntityProperties { get; set; }
85
86 public abstract OMV.Vector3 Scale { get; set; }
87 public abstract bool IsSolid { get; }
88 public abstract bool IsStatic { get; }
89
90 // Stop all physical motion.
91 public abstract void ZeroMotion();
92
93 // Step the vehicle simulation for this object. A NOOP if the vehicle was not configured.
94 public virtual void StepVehicle(float timeStep) { }
95
96 // Update the physical location and motion of the object. Called with data from Bullet.
97 public abstract void UpdateProperties(EntityProperties entprop);
98
99 // Tell the object to clean up.
100 public abstract void Destroy();
101
102 public abstract OMV.Vector3 ForcePosition { get; set; }
103
104 public abstract OMV.Quaternion ForceOrientation { get; set; }
105
106 public abstract OMV.Vector3 ForceVelocity { get; set; }
107
108 public abstract OMV.Vector3 ForceRotationalVelocity { get; set; }
109
110 public abstract float ForceBuoyancy { get; set; }
111
112 public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; }
113
114 #region Collisions
115
116 // Requested number of milliseconds between collision events. Zero means disabled.
117 protected int SubscribedEventsMs { get; set; }
118 // Given subscription, the time that a collision may be passed up
119 protected int NextCollisionOkTime { get; set; }
120 // The simulation step that last had a collision
121 protected long CollidingStep { get; set; }
122 // The simulation step that last had a collision with the ground
123 protected long CollidingGroundStep { get; set; }
124 // The collision flags we think are set in Bullet
125 protected CollisionFlags CurrentCollisionFlags { get; set; }
126
127 // The collisions that have been collected this tick
128 protected CollisionEventUpdate CollisionCollection;
129
130 // The simulation step is telling this object about a collision.
131 // Return 'true' if a collision was processed and should be sent up.
132 // Called at taint time from within the Step() function
133 public virtual bool Collide(uint collidingWith, BSPhysObject collidee,
134 OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
135 {
136 bool ret = false;
137
138 // The following lines make IsColliding() and IsCollidingGround() work
139 CollidingStep = PhysicsScene.SimulationStep;
140 if (collidingWith <= PhysicsScene.TerrainManager.HighestTerrainID)
141 {
142 CollidingGroundStep = PhysicsScene.SimulationStep;
143 }
144
145 // prims in the same linkset cannot collide with each other
146 if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID))
147 {
148 return ret;
149 }
150
151 // if someone has subscribed for collision events....
152 if (SubscribedEvents()) {
153 CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
154 DetailLog("{0},{1}.Collison.AddCollider,call,with={2},point={3},normal={4},depth={5}",
155 LocalID, TypeName, collidingWith, contactPoint, contactNormal, pentrationDepth);
156
157 ret = true;
158 }
159 return ret;
160 }
161
162 // Send the collected collisions into the simulator.
163 // Called at taint time from within the Step() function thus no locking problems
164 // with CollisionCollection and ObjectsWithNoMoreCollisions.
165 // Return 'true' if there were some actual collisions passed up
166 public virtual bool SendCollisions()
167 {
168 bool ret = true;
169 // If the 'no collision' call, force it to happen right now so quick collision_end
170 bool force = CollisionCollection.Count == 0;
171
172 // throttle the collisions to the number of milliseconds specified in the subscription
173 if (force || (PhysicsScene.SimulationNowTime >= NextCollisionOkTime))
174 {
175 NextCollisionOkTime = PhysicsScene.SimulationNowTime + SubscribedEventsMs;
176
177 // We are called if we previously had collisions. If there are no collisions
178 // this time, send up one last empty event so OpenSim can sense collision end.
179 if (CollisionCollection.Count == 0)
180 {
181 // If I have no collisions this time, remove me from the list of objects with collisions.
182 ret = false;
183 }
184
185 // DetailLog("{0},{1}.SendCollisionUpdate,call,numCollisions={2}", LocalID, TypeName, CollisionCollection.Count);
186 base.SendCollisionUpdate(CollisionCollection);
187
188 // The collisionCollection structure is passed around in the simulator.
189 // Make sure we don't have a handle to that one and that a new one is used for next time.
190 CollisionCollection = new CollisionEventUpdate();
191 }
192 return ret;
193 }
194
195 // Subscribe for collision events.
196 // Parameter is the millisecond rate the caller wishes collision events to occur.
197 public override void SubscribeEvents(int ms) {
198 // DetailLog("{0},{1}.SubscribeEvents,subscribing,ms={2}", LocalID, TypeName, ms);
199 SubscribedEventsMs = ms;
200 if (ms > 0)
201 {
202 // make sure first collision happens
203 NextCollisionOkTime = Util.EnvironmentTickCountSubtract(SubscribedEventsMs);
204
205 PhysicsScene.TaintedObject(TypeName+".SubscribeEvents", delegate()
206 {
207 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
208 });
209 }
210 else
211 {
212 // Subscribing for zero or less is the same as unsubscribing
213 UnSubscribeEvents();
214 }
215 }
216 public override void UnSubscribeEvents() {
217 // DetailLog("{0},{1}.UnSubscribeEvents,unsubscribing", LocalID, TypeName);
218 SubscribedEventsMs = 0;
219 PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate()
220 {
221 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
222 });
223 }
224 // Return 'true' if the simulator wants collision events
225 public override bool SubscribedEvents() {
226 return (SubscribedEventsMs > 0);
227 }
228
229 #endregion // Collisions
230
231 // High performance detailed logging routine used by the physical objects.
232 protected void DetailLog(string msg, params Object[] args)
233 {
234 if (PhysicsScene.PhysicsLogging.Enabled)
235 PhysicsScene.DetailLog(msg, args);
236 }
237}
238}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs
index 0f027b8..20f5180 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 9c20004..38ab3de 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -24,6 +24,9 @@
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27
28// Uncomment this it enable code to do all shape an body memory management
29// in the C# code.
27using System; 30using System;
28using System.Reflection; 31using System.Reflection;
29using System.Collections.Generic; 32using System.Collections.Generic;
@@ -36,32 +39,18 @@ using OpenSim.Region.Physics.ConvexDecompositionDotNet;
36 39
37namespace OpenSim.Region.Physics.BulletSPlugin 40namespace OpenSim.Region.Physics.BulletSPlugin
38{ 41{
42
39 [Serializable] 43 [Serializable]
40public sealed class BSPrim : PhysicsActor 44public sealed class BSPrim : BSPhysObject
41{ 45{
42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43 private static readonly string LogHeader = "[BULLETS PRIM]"; 47 private static readonly string LogHeader = "[BULLETS PRIM]";
44 48
45 private void DebugLog(string mm, params Object[] xx) { if (_scene.ShouldDebugLog) m_log.DebugFormat(mm, xx); } 49 // _size is what the user passed. Scale is what we pass to the physics engine with the mesh.
46 50 // Often Scale is unity because the meshmerizer will apply _size when creating the mesh.
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.
61 private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user 51 private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user
62 private OMV.Vector3 _scale; // the multiplier for each mesh dimension for the mesh as created by the meshmerizer 52 // private OMV.Vector3 _scale; // the multiplier for each mesh dimension for the mesh as created by the meshmerizer
63 53
64 private bool _stopped;
65 private bool _grabbed; 54 private bool _grabbed;
66 private bool _isSelected; 55 private bool _isSelected;
67 private bool _isVolumeDetect; 56 private bool _isVolumeDetect;
@@ -89,25 +78,6 @@ public sealed class BSPrim : PhysicsActor
89 private bool _kinematic; 78 private bool _kinematic;
90 private float _buoyancy; 79 private float _buoyancy;
91 80
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
111 private BSDynamics _vehicle; 81 private BSDynamics _vehicle;
112 82
113 private OMV.Vector3 _PIDTarget; 83 private OMV.Vector3 _PIDTarget;
@@ -122,108 +92,112 @@ public sealed class BSPrim : PhysicsActor
122 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) 92 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical)
123 { 93 {
124 // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID); 94 // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID);
125 _localID = localID; 95 base.BaseInitialize(parent_scene, localID, primName, "BSPrim");
126 _avName = primName; 96 _physicsActorType = (int)ActorTypes.Prim;
127 _scene = parent_scene;
128 _position = pos; 97 _position = pos;
129 _size = size; 98 _size = size;
130 _scale = new OMV.Vector3(1f, 1f, 1f); // the scale will be set by CreateGeom depending on object type 99 Scale = new OMV.Vector3(1f, 1f, 1f); // the scale will be set by CreateGeom depending on object type
131 _orientation = rotation; 100 _orientation = rotation;
132 _buoyancy = 1f; 101 _buoyancy = 1f;
133 _velocity = OMV.Vector3.Zero; 102 _velocity = OMV.Vector3.Zero;
134 _rotationalVelocity = OMV.Vector3.Zero; 103 _rotationalVelocity = OMV.Vector3.Zero;
135 _hullKey = 0; 104 BaseShape = pbs;
136 _meshKey = 0;
137 _pbs = pbs;
138 _isPhysical = pisPhysical; 105 _isPhysical = pisPhysical;
139 _isVolumeDetect = false; 106 _isVolumeDetect = false;
140 _subscribedEventsMs = 0; 107 _friction = PhysicsScene.Params.defaultFriction; // TODO: compute based on object material
141 _friction = _scene.Params.defaultFriction; // TODO: compute based on object material 108 _density = PhysicsScene.Params.defaultDensity; // TODO: compute based on object material
142 _density = _scene.Params.defaultDensity; // TODO: compute based on object material 109 _restitution = PhysicsScene.Params.defaultRestitution;
143 _restitution = _scene.Params.defaultRestitution; 110 _vehicle = new BSDynamics(PhysicsScene, this); // add vehicleness
144 _linkset = new BSLinkset(_scene, this); // a linkset of one
145 _vehicle = new BSDynamics(this); // add vehicleness
146 _mass = CalculateMass(); 111 _mass = CalculateMass();
147 // do the actual object creation at taint time 112
113 // No body or shape yet
114 BSBody = new BulletBody(LocalID, IntPtr.Zero);
115 BSShape = new BulletShape(IntPtr.Zero);
116
148 DetailLog("{0},BSPrim.constructor,call", LocalID); 117 DetailLog("{0},BSPrim.constructor,call", LocalID);
149 _scene.TaintedObject("BSPrim.create", delegate() 118 // do the actual object creation at taint time
119 PhysicsScene.TaintedObject("BSPrim.create", delegate()
150 { 120 {
151 RecreateGeomAndObject(); 121 CreateGeomAndObject(true);
152 122
153 // Get the pointer to the physical body for this object. 123 CurrentCollisionFlags = BulletSimAPI.GetCollisionFlags2(BSBody.ptr);
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));
157 }); 124 });
158 } 125 }
159 126
160 // called when this prim is being destroyed and we should free all the resources 127 // called when this prim is being destroyed and we should free all the resources
161 public void Destroy() 128 public override void Destroy()
162 { 129 {
163 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); 130 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID);
164 131
165 // Undo any links between me and any other object 132 // Undo any links between me and any other object
166 BSPrim parentBefore = _linkset.LinksetRoot; 133 BSPhysObject parentBefore = Linkset.LinksetRoot;
167 int childrenBefore = _linkset.NumberOfChildren; 134 int childrenBefore = Linkset.NumberOfChildren;
168 135
169 _linkset = _linkset.RemoveMeFromLinkset(this); 136 Linkset = Linkset.RemoveMeFromLinkset(this);
170 137
171 DetailLog("{0},BSPrim.Destroy,call,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}", 138 DetailLog("{0},BSPrim.Destroy,call,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}",
172 LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren); 139 LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
173 140
174 // Undo any vehicle properties 141 // Undo any vehicle properties
175 this.VehicleType = (int)Vehicle.TYPE_NONE; 142 this.VehicleType = (int)Vehicle.TYPE_NONE;
176 143
177 _scene.TaintedObject("BSPrim.destroy", delegate() 144 PhysicsScene.TaintedObject("BSPrim.destroy", delegate()
178 { 145 {
179 DetailLog("{0},BSPrim.Destroy,taint,", LocalID); 146 DetailLog("{0},BSPrim.Destroy,taint,", LocalID);
180 // everything in the C# world will get garbage collected. Tell the C++ world to free stuff. 147 // If there are physical body and shape, release my use of same.
181 BulletSimAPI.DestroyObject(_scene.WorldID, LocalID); 148 PhysicsScene.Shapes.DereferenceBody(BSBody, true, null);
149 PhysicsScene.Shapes.DereferenceShape(BSShape, true, null);
182 }); 150 });
183 } 151 }
184 152
185 public override bool Stopped { 153 // No one uses this property.
186 get { return _stopped; } 154 public override bool Stopped {
155 get { return false; }
187 } 156 }
188 public override OMV.Vector3 Size { 157 public override OMV.Vector3 Size {
189 get { return _size; } 158 get { return _size; }
190 set { 159 set {
191 _size = value; 160 _size = value;
192 _scene.TaintedObject("BSPrim.setSize", delegate() 161 ForceBodyShapeRebuild(false);
193 { 162 }
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 }
200 } 163 }
201 public override PrimitiveBaseShape Shape { 164 // Scale is what we set in the physics engine. It is different than 'size' in that
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 {
202 set { 169 set {
203 _pbs = value; 170 BaseShape = value;
204 _scene.TaintedObject("BSPrim.setShape", delegate() 171 ForceBodyShapeRebuild(false);
205 { 172 }
206 _mass = CalculateMass(); // changing the shape changes the mass
207 RecreateGeomAndObject();
208 });
209 }
210 } 173 }
211 public override uint LocalID { 174 public override bool ForceBodyShapeRebuild(bool inTaintTime)
212 set { _localID = value; } 175 {
213 get { return _localID; } 176 LastAssetBuildFailed = false;
177 BSScene.TaintCallback rebuildOperation = delegate()
178 {
179 _mass = CalculateMass(); // changing the shape changes the mass
180 CreateGeomAndObject(true);
181 };
182 if (inTaintTime)
183 rebuildOperation();
184 else
185 PhysicsScene.TaintedObject("BSPrim.ForceBodyShapeRebuild", rebuildOperation);
186 return true;
214 } 187 }
215 public override bool Grabbed { 188 public override bool Grabbed {
216 set { _grabbed = value; 189 set { _grabbed = value;
217 } 190 }
218 } 191 }
219 public override bool Selected { 192 public override bool Selected {
220 set { 193 set {
221 _isSelected = value; 194 _isSelected = value;
222 _scene.TaintedObject("BSPrim.setSelected", delegate() 195 PhysicsScene.TaintedObject("BSPrim.setSelected", delegate()
223 { 196 {
224 SetObjectDynamic(); 197 DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected);
198 SetObjectDynamic(false);
225 }); 199 });
226 } 200 }
227 } 201 }
228 public override void CrossingFailure() { return; } 202 public override void CrossingFailure() { return; }
229 203
@@ -232,158 +206,227 @@ public sealed class BSPrim : PhysicsActor
232 BSPrim parent = obj as BSPrim; 206 BSPrim parent = obj as BSPrim;
233 if (parent != null) 207 if (parent != null)
234 { 208 {
235 DebugLog("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, parent.LocalID); 209 BSPhysObject parentBefore = Linkset.LinksetRoot;
236 BSPrim parentBefore = _linkset.LinksetRoot; 210 int childrenBefore = Linkset.NumberOfChildren;
237 int childrenBefore = _linkset.NumberOfChildren;
238 211
239 _linkset = parent.Linkset.AddMeToLinkset(this); 212 Linkset = parent.Linkset.AddMeToLinkset(this);
240 213
241 DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}", 214 DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}",
242 LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren); 215 LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
243 } 216 }
244 return; 217 return;
245 } 218 }
246 219
247 // delink me from my linkset 220 // delink me from my linkset
248 public override void delink() { 221 public override void delink() {
249 // TODO: decide if this parent checking needs to happen at taint time 222 // TODO: decide if this parent checking needs to happen at taint time
250 // Race condition here: if link() and delink() in same simulation tick, the delink will not happen 223 // 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());
253 224
254 BSPrim parentBefore = _linkset.LinksetRoot; 225 BSPhysObject parentBefore = Linkset.LinksetRoot;
255 int childrenBefore = _linkset.NumberOfChildren; 226 int childrenBefore = Linkset.NumberOfChildren;
256 227
257 _linkset = _linkset.RemoveMeFromLinkset(this); 228 Linkset = Linkset.RemoveMeFromLinkset(this);
258 229
259 DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ", 230 DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ",
260 LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren); 231 LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
261 return; 232 return;
262 } 233 }
263 234
264 // Set motion values to zero. 235 // Set motion values to zero.
265 // Do it to the properties so the values get set in the physics engine. 236 // Do it to the properties so the values get set in the physics engine.
266 // Push the setting of the values to the viewer. 237 // Push the setting of the values to the viewer.
267 // Called at taint time! 238 // Called at taint time!
268 public void ZeroMotion() 239 public override void ZeroMotion()
269 { 240 {
270 _velocity = OMV.Vector3.Zero; 241 _velocity = OMV.Vector3.Zero;
271 _acceleration = OMV.Vector3.Zero; 242 _acceleration = OMV.Vector3.Zero;
272 _rotationalVelocity = OMV.Vector3.Zero; 243 _rotationalVelocity = OMV.Vector3.Zero;
273 244
274 // Zero some other properties directly into the physics engine 245 // Zero some other properties directly into the physics engine
275 BulletSimAPI.SetVelocity2(Body.Ptr, OMV.Vector3.Zero); 246 BulletSimAPI.ClearForces2(BSBody.ptr);
276 BulletSimAPI.SetAngularVelocity2(Body.Ptr, OMV.Vector3.Zero);
277 BulletSimAPI.SetInterpolation2(Body.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero);
278 BulletSimAPI.ClearForces2(Body.Ptr);
279 } 247 }
280 248
281 public override void LockAngularMotion(OMV.Vector3 axis) 249 public override void LockAngularMotion(OMV.Vector3 axis)
282 { 250 {
283 // DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis); 251 DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis);
284 return; 252 return;
285 } 253 }
286 254
287 public override OMV.Vector3 Position { 255 public override OMV.Vector3 Position {
288 get { 256 get {
289 if (!_linkset.IsRoot(this)) 257 if (!Linkset.IsRoot(this))
290 // child prims move around based on their parent. Need to get the latest location 258 // child prims move around based on their parent. Need to get the latest location
291 _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 259 _position = BulletSimAPI.GetPosition2(BSBody.ptr);
292 260
293 // don't do the GetObjectPosition for root elements because this function is called a zillion times 261 // don't do the GetObjectPosition for root elements because this function is called a zillion times
294 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 262 // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr);
295 return _position; 263 return _position;
296 } 264 }
297 set { 265 set {
266 // If you must push the position into the physics engine, use ForcePosition.
267 if (_position == value)
268 {
269 return;
270 }
298 _position = value; 271 _position = value;
299 // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? 272 // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint?
300 _scene.TaintedObject("BSPrim.setPosition", delegate() 273 PositionSanityCheck();
274 PhysicsScene.TaintedObject("BSPrim.setPosition", delegate()
301 { 275 {
302 // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 276 // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
303 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 277 BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation);
304 }); 278 });
305 } 279 }
280 }
281 public override OMV.Vector3 ForcePosition {
282 get {
283 _position = BulletSimAPI.GetPosition2(BSBody.ptr);
284 return _position;
285 }
286 set {
287 _position = value;
288 PositionSanityCheck();
289 BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation);
290 }
291 }
292
293 // Check that the current position is sane and, if not, modify the position to make it so.
294 // Check for being below terrain and being out of bounds.
295 // Returns 'true' of the position was made sane by some action.
296 private bool PositionSanityCheck()
297 {
298 bool ret = false;
299
300 // If totally below the ground, move the prim up
301 // TODO: figure out the right solution for this... only for dynamic objects?
302 /*
303 float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position);
304 if (Position.Z < terrainHeight)
305 {
306 DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight);
307 _position.Z = terrainHeight + 2.0f;
308 ret = true;
309 }
310 */
311 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0)
312 {
313 float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position);
314 if (Position.Z < waterHeight)
315 {
316 _position.Z = waterHeight;
317 ret = true;
318 }
319 }
320
321 // TODO: check for out of bounds
322 return ret;
323 }
324
325 // A version of the sanity check that also makes sure a new position value is
326 // pushed to the physics engine. This routine would be used by anyone
327 // who is not already pushing the value.
328 private bool PositionSanityCheck(bool inTaintTime)
329 {
330 bool ret = false;
331 if (PositionSanityCheck())
332 {
333 // The new position value must be pushed into the physics engine but we can't
334 // just assign to "Position" because of potential call loops.
335 BSScene.TaintCallback sanityOperation = delegate()
336 {
337 DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
338 ForcePosition = _position;
339 };
340 if (inTaintTime)
341 sanityOperation();
342 else
343 PhysicsScene.TaintedObject("BSPrim.PositionSanityCheck", sanityOperation);
344
345 ret = true;
346 }
347 return ret;
306 } 348 }
307 349
308 // Return the effective mass of the object. 350 // Return the effective mass of the object.
309 // If there are multiple items in the linkset, add them together for the root 351 // If there are multiple items in the linkset, add them together for the root
310 public override float Mass 352 public override float Mass
311 { 353 {
312 get 354 get
313 { 355 {
314 return _linkset.LinksetMass; 356 // return Linkset.LinksetMass;
357 return _mass;
315 } 358 }
316 } 359 }
317 360
318 // used when we only want this prim's mass and not the linkset thing 361 // used when we only want this prim's mass and not the linkset thing
319 public float MassRaw { get { return _mass; } } 362 public override float MassRaw { get { return _mass; } }
320 363
321 // Is this used? 364 // Is this used?
322 public override OMV.Vector3 CenterOfMass 365 public override OMV.Vector3 CenterOfMass
323 { 366 {
324 get { return _linkset.CenterOfMass; } 367 get { return Linkset.CenterOfMass; }
325 } 368 }
326 369
327 // Is this used? 370 // Is this used?
328 public override OMV.Vector3 GeometricCenter 371 public override OMV.Vector3 GeometricCenter
329 { 372 {
330 get { return _linkset.GeometricCenter; } 373 get { return Linkset.GeometricCenter; }
331 } 374 }
332 375
333 public override OMV.Vector3 Force { 376 public override OMV.Vector3 Force {
334 get { return _force; } 377 get { return _force; }
335 set { 378 set {
336 _force = value; 379 _force = value;
337 _scene.TaintedObject("BSPrim.setForce", delegate() 380 PhysicsScene.TaintedObject("BSPrim.setForce", delegate()
338 { 381 {
339 // DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); 382 // DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force);
340 // BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); 383 BulletSimAPI.SetObjectForce2(BSBody.ptr, _force);
341 BulletSimAPI.SetObjectForce2(Body.Ptr, _force);
342 }); 384 });
343 } 385 }
344 } 386 }
345 387
346 public override int VehicleType { 388 public override int VehicleType {
347 get { 389 get {
348 return (int)_vehicle.Type; // if we are a vehicle, return that type 390 return (int)_vehicle.Type; // if we are a vehicle, return that type
349 } 391 }
350 set { 392 set {
351 Vehicle type = (Vehicle)value; 393 Vehicle type = (Vehicle)value;
352 BSPrim vehiclePrim = this; 394
353 _scene.TaintedObject("setVehicleType", delegate() 395 // Tell the scene about the vehicle so it will get processing each frame.
396 PhysicsScene.VehicleInSceneTypeChanged(this, type);
397
398 PhysicsScene.TaintedObject("setVehicleType", delegate()
354 { 399 {
355 // Done at taint time so we're sure the physics engine is not using the variables 400 // Done at taint time so we're sure the physics engine is not using the variables
356 // Vehicle code changes the parameters for this vehicle type. 401 // Vehicle code changes the parameters for this vehicle type.
357 _vehicle.ProcessTypeChange(type); 402 _vehicle.ProcessTypeChange(type);
358 // Tell the scene about the vehicle so it will get processing each frame.
359 _scene.VehicleInSceneTypeChanged(this, type);
360 }); 403 });
361 } 404 }
362 } 405 }
363 public override void VehicleFloatParam(int param, float value) 406 public override void VehicleFloatParam(int param, float value)
364 { 407 {
365 _scene.TaintedObject("BSPrim.VehicleFloatParam", delegate() 408 PhysicsScene.TaintedObject("BSPrim.VehicleFloatParam", delegate()
366 { 409 {
367 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); 410 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value);
368 }); 411 });
369 } 412 }
370 public override void VehicleVectorParam(int param, OMV.Vector3 value) 413 public override void VehicleVectorParam(int param, OMV.Vector3 value)
371 { 414 {
372 _scene.TaintedObject("BSPrim.VehicleVectorParam", delegate() 415 PhysicsScene.TaintedObject("BSPrim.VehicleVectorParam", delegate()
373 { 416 {
374 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); 417 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value);
375 }); 418 });
376 } 419 }
377 public override void VehicleRotationParam(int param, OMV.Quaternion rotation) 420 public override void VehicleRotationParam(int param, OMV.Quaternion rotation)
378 { 421 {
379 _scene.TaintedObject("BSPrim.VehicleRotationParam", delegate() 422 PhysicsScene.TaintedObject("BSPrim.VehicleRotationParam", delegate()
380 { 423 {
381 _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation); 424 _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation);
382 }); 425 });
383 } 426 }
384 public override void VehicleFlags(int param, bool remove) 427 public override void VehicleFlags(int param, bool remove)
385 { 428 {
386 _scene.TaintedObject("BSPrim.VehicleFlags", delegate() 429 PhysicsScene.TaintedObject("BSPrim.VehicleFlags", delegate()
387 { 430 {
388 _vehicle.ProcessVehicleFlags(param, remove); 431 _vehicle.ProcessVehicleFlags(param, remove);
389 }); 432 });
@@ -391,143 +434,331 @@ public sealed class BSPrim : PhysicsActor
391 434
392 // Called each simulation step to advance vehicle characteristics. 435 // Called each simulation step to advance vehicle characteristics.
393 // Called from Scene when doing simulation step so we're in taint processing time. 436 // Called from Scene when doing simulation step so we're in taint processing time.
394 public void StepVehicle(float timeStep) 437 public override void StepVehicle(float timeStep)
395 { 438 {
396 if (IsPhysical) 439 if (IsPhysical)
440 {
397 _vehicle.Step(timeStep); 441 _vehicle.Step(timeStep);
442 }
398 } 443 }
399 444
400 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more 445 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more
401 public override void SetVolumeDetect(int param) { 446 public override void SetVolumeDetect(int param) {
402 bool newValue = (param != 0); 447 bool newValue = (param != 0);
403 _isVolumeDetect = newValue; 448 if (_isVolumeDetect != newValue)
404 _scene.TaintedObject("BSPrim.SetVolumeDetect", delegate()
405 { 449 {
406 SetObjectDynamic(); 450 _isVolumeDetect = newValue;
407 }); 451 PhysicsScene.TaintedObject("BSPrim.SetVolumeDetect", delegate()
408 return; 452 {
453 // DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect);
454 SetObjectDynamic(true);
455 });
456 }
457 return;
409 } 458 }
410 459 public override OMV.Vector3 Velocity {
411 public override OMV.Vector3 Velocity { 460 get { return _velocity; }
412 get { return _velocity; }
413 set { 461 set {
414 _velocity = value; 462 _velocity = value;
415 _scene.TaintedObject("BSPrim.setVelocity", delegate() 463 PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate()
416 { 464 {
417 // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); 465 // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity);
418 BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity); 466 BulletSimAPI.SetLinearVelocity2(BSBody.ptr, _velocity);
419 }); 467 });
420 } 468 }
469 }
470 public override OMV.Vector3 ForceVelocity {
471 get { return _velocity; }
472 set {
473 _velocity = value;
474 BulletSimAPI.SetLinearVelocity2(BSBody.ptr, _velocity);
475 }
421 } 476 }
422 public override OMV.Vector3 Torque { 477 public override OMV.Vector3 Torque {
423 get { return _torque; } 478 get { return _torque; }
424 set { _torque = value; 479 set { _torque = value;
425 // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque); 480 // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque);
426 } 481 }
427 } 482 }
428 public override float CollisionScore { 483 public override float CollisionScore {
429 get { return _collisionScore; } 484 get { return _collisionScore; }
430 set { _collisionScore = value; 485 set { _collisionScore = value;
431 } 486 }
432 } 487 }
433 public override OMV.Vector3 Acceleration { 488 public override OMV.Vector3 Acceleration {
434 get { return _acceleration; } 489 get { return _acceleration; }
435 set { _acceleration = value; } 490 set { _acceleration = value; }
436 } 491 }
437 public override OMV.Quaternion Orientation { 492 public override OMV.Quaternion Orientation {
438 get { 493 get {
439 if (!_linkset.IsRoot(this)) 494 if (!Linkset.IsRoot(this))
440 { 495 {
441 // Children move around because tied to parent. Get a fresh value. 496 // Children move around because tied to parent. Get a fresh value.
442 _orientation = BulletSimAPI.GetObjectOrientation(_scene.WorldID, LocalID); 497 _orientation = BulletSimAPI.GetOrientation2(BSBody.ptr);
443 } 498 }
444 return _orientation; 499 return _orientation;
445 } 500 }
446 set { 501 set {
502 if (_orientation == value)
503 return;
447 _orientation = value; 504 _orientation = value;
448 // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint? 505 // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint?
449 _scene.TaintedObject("BSPrim.setOrientation", delegate() 506 PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate()
450 { 507 {
451 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 508 // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr);
452 // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); 509 // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation);
453 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 510 BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation);
454 }); 511 });
455 } 512 }
513 }
514 // Go directly to Bullet to get/set the value.
515 public override OMV.Quaternion ForceOrientation
516 {
517 get
518 {
519 _orientation = BulletSimAPI.GetOrientation2(BSBody.ptr);
520 return _orientation;
521 }
522 set
523 {
524 _orientation = value;
525 BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation);
526 }
456 } 527 }
457 public override int PhysicsActorType { 528 public override int PhysicsActorType {
458 get { return _physicsActorType; } 529 get { return _physicsActorType; }
459 set { _physicsActorType = value; 530 set { _physicsActorType = value; }
460 }
461 } 531 }
462 public override bool IsPhysical { 532 public override bool IsPhysical {
463 get { return _isPhysical; } 533 get { return _isPhysical; }
464 set { 534 set {
465 _isPhysical = value; 535 if (_isPhysical != value)
466 _scene.TaintedObject("BSPrim.setIsPhysical", delegate()
467 { 536 {
468 SetObjectDynamic(); 537 _isPhysical = value;
469 }); 538 PhysicsScene.TaintedObject("BSPrim.setIsPhysical", delegate()
470 } 539 {
540 // DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical);
541 SetObjectDynamic(true);
542 });
543 }
544 }
471 } 545 }
472 546
473 // An object is static (does not move) if selected or not physical 547 // An object is static (does not move) if selected or not physical
474 private bool IsStatic 548 public override bool IsStatic
475 { 549 {
476 get { return _isSelected || !IsPhysical; } 550 get { return _isSelected || !IsPhysical; }
477 } 551 }
478 552
479 // An object is solid if it's not phantom and if it's not doing VolumeDetect 553 // An object is solid if it's not phantom and if it's not doing VolumeDetect
480 private bool IsSolid 554 public override bool IsSolid
481 { 555 {
482 get { return !IsPhantom && !_isVolumeDetect; } 556 get { return !IsPhantom && !_isVolumeDetect; }
483 } 557 }
484 558
485 // Make gravity work if the object is physical and not selected 559 // Make gravity work if the object is physical and not selected
486 // No locking here because only called when it is safe 560 // Called at taint-time!!
487 private void SetObjectDynamic() 561 private void SetObjectDynamic(bool forceRebuild)
562 {
563 // Recreate the physical object if necessary
564 CreateGeomAndObject(forceRebuild);
565 }
566
567 // Convert the simulator's physical properties into settings on BulletSim objects.
568 // There are four flags we're interested in:
569 // IsStatic: Object does not move, otherwise the object has mass and moves
570 // isSolid: other objects bounce off of this object
571 // isVolumeDetect: other objects pass through but can generate collisions
572 // collisionEvents: whether this object returns collision events
573 private void UpdatePhysicalParameters()
574 {
575 // DetailLog("{0},BSPrim.UpdatePhysicalParameters,entry,body={1},shape={2}", LocalID, BSBody, BSShape);
576
577 // Mangling all the physical properties requires the object not be in the physical world.
578 // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found).
579 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, BSBody.ptr);
580
581 // Set up the object physicalness (does gravity and collisions move this object)
582 MakeDynamic(IsStatic);
583
584 // Update vehicle specific parameters (after MakeDynamic() so can change physical parameters)
585 _vehicle.Refresh();
586
587 // Arrange for collision events if the simulator wants them
588 EnableCollisions(SubscribedEvents());
589
590 // Make solid or not (do things bounce off or pass through this object).
591 MakeSolid(IsSolid);
592
593 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, BSBody.ptr);
594
595 // Rebuild its shape
596 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, BSBody.ptr);
597
598 // Collision filter can be set only when the object is in the world
599 if (BSBody.collisionFilter != 0 || BSBody.collisionMask != 0)
600 {
601 BulletSimAPI.SetCollisionFilterMask2(BSBody.ptr, (uint)BSBody.collisionFilter, (uint)BSBody.collisionMask);
602 }
603
604 // Recompute any linkset parameters.
605 // When going from non-physical to physical, this re-enables the constraints that
606 // had been automatically disabled when the mass was set to zero.
607 Linkset.Refresh(this, true);
608
609 DetailLog("{0},BSPrim.UpdatePhysicalParameters,exit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}",
610 LocalID, IsStatic, IsSolid, _mass, SubscribedEvents(), CurrentCollisionFlags, BSBody, BSShape);
611 }
612
613 // "Making dynamic" means changing to and from static.
614 // When static, gravity does not effect the object and it is fixed in space.
615 // When dynamic, the object can fall and be pushed by others.
616 // This is independent of its 'solidness' which controls what passes through
617 // this object and what interacts with it.
618 private void MakeDynamic(bool makeStatic)
488 { 619 {
489 // RA: remove this for the moment. 620 if (makeStatic)
490 // The problem is that dynamic objects are hulls so if we are becoming physical 621 {
491 // the shape has to be checked and possibly built. 622 // Become a Bullet 'static' object type
492 // Maybe a VerifyCorrectPhysicalShape() routine? 623 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_STATIC_OBJECT);
493 // RecreateGeomAndObject(); 624 // Stop all movement
625 BulletSimAPI.ClearAllForces2(BSBody.ptr);
626 // Center of mass is at the center of the object
627 BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.BSBody.ptr, _position, _orientation);
628 // Mass is zero which disables a bunch of physics stuff in Bullet
629 BulletSimAPI.SetMassProps2(BSBody.ptr, 0f, OMV.Vector3.Zero);
630 // There is no inertia in a static object
631 BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr);
632 // Set collision detection parameters
633 if (PhysicsScene.Params.ccdMotionThreshold > 0f)
634 {
635 BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold);
636 BulletSimAPI.SetCcdSweepSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius);
637 }
638 // There can be special things needed for implementing linksets
639 Linkset.MakeStatic(this);
640 // The activation state is 'disabled' so Bullet will not try to act on it.
641 BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_SIMULATION);
642 // Start it out sleeping and physical actions could wake it up.
643 // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING);
644
645 BSBody.collisionFilter = CollisionFilterGroups.StaticObjectFilter;
646 BSBody.collisionMask = CollisionFilterGroups.StaticObjectMask;
647 }
648 else
649 {
650 // Not a Bullet static object
651 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.CF_STATIC_OBJECT);
652
653 // Set various physical properties so internal dynamic properties will get computed correctly as they are set
654 BulletSimAPI.SetFriction2(BSBody.ptr, PhysicsScene.Params.defaultFriction);
655 BulletSimAPI.SetRestitution2(BSBody.ptr, PhysicsScene.Params.defaultRestitution);
656
657 // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382
658 BulletSimAPI.ClearAllForces2(BSBody.ptr);
659
660 // For good measure, make sure the transform is set through to the motion state
661 BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation);
662
663 // A dynamic object has mass
664 IntPtr collisionShapePtr = BulletSimAPI.GetCollisionShape2(BSBody.ptr);
665 OMV.Vector3 inertia = BulletSimAPI.CalculateLocalInertia2(collisionShapePtr, Mass);
666 BulletSimAPI.SetMassProps2(BSBody.ptr, _mass, inertia);
667 BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr);
668
669 // Set collision detection parameters
670 if (PhysicsScene.Params.ccdMotionThreshold > 0f)
671 {
672 BulletSimAPI.SetCcdMotionThreshold2(BSBody.ptr, PhysicsScene.Params.ccdMotionThreshold);
673 BulletSimAPI.SetCcdSweepSphereRadius2(BSBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius);
674 }
494 675
495 // Bullet wants static objects to have a mass of zero 676 // Various values for simulation limits
496 float mass = IsStatic ? 0f : _mass; 677 BulletSimAPI.SetDamping2(BSBody.ptr, PhysicsScene.Params.linearDamping, PhysicsScene.Params.angularDamping);
678 BulletSimAPI.SetDeactivationTime2(BSBody.ptr, PhysicsScene.Params.deactivationTime);
679 BulletSimAPI.SetSleepingThresholds2(BSBody.ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold);
680 BulletSimAPI.SetContactProcessingThreshold2(BSBody.ptr, PhysicsScene.Params.contactProcessingThreshold);
497 681
498 BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass); 682 // There might be special things needed for implementing linksets.
683 Linkset.MakeDynamic(this);
499 684
500 // recompute any linkset parameters 685 // Force activation of the object so Bullet will act on it.
501 _linkset.Refresh(this); 686 // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects.
687 BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ACTIVE_TAG);
688 // BulletSimAPI.Activate2(BSBody.ptr, true);
502 689
503 CollisionFlags cf = BulletSimAPI.GetCollisionFlags2(Body.Ptr); 690 BSBody.collisionFilter = CollisionFilterGroups.ObjectFilter;
504 // DetailLog("{0},BSPrim.SetObjectDynamic,taint,static={1},solid={2},mass={3}, cf={4}", LocalID, IsStatic, IsSolid, mass, cf); 691 BSBody.collisionMask = CollisionFilterGroups.ObjectMask;
692 }
693 }
694
695 // "Making solid" means that other object will not pass through this object.
696 // To make transparent, we create a Bullet ghost object.
697 // Note: This expects to be called from the UpdatePhysicalParameters() routine as
698 // the functions after this one set up the state of a possibly newly created collision body.
699 private void MakeSolid(bool makeSolid)
700 {
701 CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(BSBody.ptr);
702 if (makeSolid)
703 {
704 // Verify the previous code created the correct shape for this type of thing.
705 if ((bodyType & CollisionObjectTypes.CO_RIGID_BODY) == 0)
706 {
707 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for solidity. id={1}, type={2}", LogHeader, LocalID, bodyType);
708 }
709 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
710 }
711 else
712 {
713 if ((bodyType & CollisionObjectTypes.CO_GHOST_OBJECT) == 0)
714 {
715 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType);
716 }
717 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
718 BSBody.collisionFilter = CollisionFilterGroups.VolumeDetectFilter;
719 BSBody.collisionMask = CollisionFilterGroups.VolumeDetectMask;
720 }
721 }
722
723 // Turn on or off the flag controlling whether collision events are returned to the simulator.
724 private void EnableCollisions(bool wantsCollisionEvents)
725 {
726 if (wantsCollisionEvents)
727 {
728 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
729 }
730 else
731 {
732 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
733 }
505 } 734 }
506 735
507 // prims don't fly 736 // prims don't fly
508 public override bool Flying { 737 public override bool Flying {
509 get { return _flying; } 738 get { return _flying; }
510 set { _flying = value; } 739 set {
740 _flying = value;
741 }
511 } 742 }
512 public override bool SetAlwaysRun { 743 public override bool SetAlwaysRun {
513 get { return _setAlwaysRun; } 744 get { return _setAlwaysRun; }
514 set { _setAlwaysRun = value; } 745 set { _setAlwaysRun = value; }
515 } 746 }
516 public override bool ThrottleUpdates { 747 public override bool ThrottleUpdates {
517 get { return _throttleUpdates; } 748 get { return _throttleUpdates; }
518 set { _throttleUpdates = value; } 749 set { _throttleUpdates = value; }
519 } 750 }
520 public override bool IsColliding { 751 public override bool IsColliding {
521 get { return (_collidingStep == _scene.SimulationStep); } 752 get { return (CollidingStep == PhysicsScene.SimulationStep); }
522 set { _isColliding = value; } 753 set { _isColliding = value; }
523 } 754 }
524 public override bool CollidingGround { 755 public override bool CollidingGround {
525 get { return (_collidingGroundStep == _scene.SimulationStep); } 756 get { return (CollidingGroundStep == PhysicsScene.SimulationStep); }
526 set { _collidingGround = value; } 757 set { _collidingGround = value; }
527 } 758 }
528 public override bool CollidingObj { 759 public override bool CollidingObj {
529 get { return _collidingObj; } 760 get { return _collidingObj; }
530 set { _collidingObj = value; } 761 set { _collidingObj = value; }
531 } 762 }
532 public bool IsPhantom { 763 public bool IsPhantom {
533 get { 764 get {
@@ -537,10 +768,19 @@ public sealed class BSPrim : PhysicsActor
537 return false; 768 return false;
538 } 769 }
539 } 770 }
540 public override bool FloatOnWater { 771 public override bool FloatOnWater {
541 set { _floatOnWater = value; } 772 set {
773 _floatOnWater = value;
774 PhysicsScene.TaintedObject("BSPrim.setFloatOnWater", delegate()
775 {
776 if (_floatOnWater)
777 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER);
778 else
779 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(BSBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER);
780 });
781 }
542 } 782 }
543 public override OMV.Vector3 RotationalVelocity { 783 public override OMV.Vector3 RotationalVelocity {
544 get { 784 get {
545 /* 785 /*
546 OMV.Vector3 pv = OMV.Vector3.Zero; 786 OMV.Vector3 pv = OMV.Vector3.Zero;
@@ -552,58 +792,76 @@ public sealed class BSPrim : PhysicsActor
552 */ 792 */
553 793
554 return _rotationalVelocity; 794 return _rotationalVelocity;
555 } 795 }
556 set { 796 set {
557 _rotationalVelocity = value; 797 _rotationalVelocity = value;
558 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); 798 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity);
559 _scene.TaintedObject("BSPrim.setRotationalVelocity", delegate() 799 PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate()
560 { 800 {
561 // DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); 801 // DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
562 BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity); 802 BulletSimAPI.SetAngularVelocity2(BSBody.ptr, _rotationalVelocity);
563 }); 803 });
564 } 804 }
805 }
806 public override OMV.Vector3 ForceRotationalVelocity {
807 get {
808 return _rotationalVelocity;
809 }
810 set {
811 _rotationalVelocity = value;
812 BulletSimAPI.SetAngularVelocity2(BSBody.ptr, _rotationalVelocity);
813 }
565 } 814 }
566 public override bool Kinematic { 815 public override bool Kinematic {
567 get { return _kinematic; } 816 get { return _kinematic; }
568 set { _kinematic = value; 817 set { _kinematic = value;
569 // m_log.DebugFormat("{0}: Kinematic={1}", LogHeader, _kinematic); 818 // m_log.DebugFormat("{0}: Kinematic={1}", LogHeader, _kinematic);
570 } 819 }
571 } 820 }
572 public override float Buoyancy { 821 public override float Buoyancy {
573 get { return _buoyancy; } 822 get { return _buoyancy; }
574 set { 823 set {
575 _buoyancy = value; 824 _buoyancy = value;
576 _scene.TaintedObject("BSPrim.setBuoyancy", delegate() 825 PhysicsScene.TaintedObject("BSPrim.setBuoyancy", delegate()
577 { 826 {
578 // DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 827 ForceBuoyancy = _buoyancy;
579 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy);
580 }); 828 });
581 } 829 }
830 }
831 public override float ForceBuoyancy {
832 get { return _buoyancy; }
833 set {
834 _buoyancy = value;
835 // DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
836 // Buoyancy is faked by changing the gravity applied to the object
837 float grav = PhysicsScene.Params.gravity * (1f - _buoyancy);
838 BulletSimAPI.SetGravity2(BSBody.ptr, new OMV.Vector3(0f, 0f, grav));
839 }
582 } 840 }
583 841
584 // Used for MoveTo 842 // Used for MoveTo
585 public override OMV.Vector3 PIDTarget { 843 public override OMV.Vector3 PIDTarget {
586 set { _PIDTarget = value; } 844 set { _PIDTarget = value; }
587 } 845 }
588 public override bool PIDActive { 846 public override bool PIDActive {
589 set { _usePID = value; } 847 set { _usePID = value; }
590 } 848 }
591 public override float PIDTau { 849 public override float PIDTau {
592 set { _PIDTau = value; } 850 set { _PIDTau = value; }
593 } 851 }
594 852
595 // Used for llSetHoverHeight and maybe vehicle height 853 // Used for llSetHoverHeight and maybe vehicle height
596 // Hover Height will override MoveTo target's Z 854 // Hover Height will override MoveTo target's Z
597 public override bool PIDHoverActive { 855 public override bool PIDHoverActive {
598 set { _useHoverPID = value; } 856 set { _useHoverPID = value; }
599 } 857 }
600 public override float PIDHoverHeight { 858 public override float PIDHoverHeight {
601 set { _PIDHoverHeight = value; } 859 set { _PIDHoverHeight = value; }
602 } 860 }
603 public override PIDHoverType PIDHoverType { 861 public override PIDHoverType PIDHoverType {
604 set { _PIDHoverType = value; } 862 set { _PIDHoverType = value; }
605 } 863 }
606 public override float PIDHoverTau { 864 public override float PIDHoverTau {
607 set { _PIDHoverTao = value; } 865 set { _PIDHoverTao = value; }
608 } 866 }
609 867
@@ -615,6 +873,9 @@ public sealed class BSPrim : PhysicsActor
615 873
616 private List<OMV.Vector3> m_accumulatedForces = new List<OMV.Vector3>(); 874 private List<OMV.Vector3> m_accumulatedForces = new List<OMV.Vector3>();
617 public override void AddForce(OMV.Vector3 force, bool pushforce) { 875 public override void AddForce(OMV.Vector3 force, bool pushforce) {
876 AddForce(force, pushforce, false);
877 }
878 public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) {
618 // for an object, doesn't matter if force is a pushforce or not 879 // for an object, doesn't matter if force is a pushforce or not
619 if (force.IsFinite()) 880 if (force.IsFinite())
620 { 881 {
@@ -624,56 +885,38 @@ public sealed class BSPrim : PhysicsActor
624 } 885 }
625 else 886 else
626 { 887 {
627 m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader); 888 m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID);
628 return; 889 return;
629 } 890 }
630 _scene.TaintedObject("BSPrim.AddForce", delegate() 891 BSScene.TaintCallback addForceOperation = delegate()
631 { 892 {
632 OMV.Vector3 fSum = OMV.Vector3.Zero; 893 OMV.Vector3 fSum = OMV.Vector3.Zero;
633 lock (m_accumulatedForces) 894 lock (m_accumulatedForces)
634 { 895 {
896 // Sum the accumulated additional forces for one big force to apply once.
635 foreach (OMV.Vector3 v in m_accumulatedForces) 897 foreach (OMV.Vector3 v in m_accumulatedForces)
636 { 898 {
637 fSum += v; 899 fSum += v;
638 } 900 }
639 m_accumulatedForces.Clear(); 901 m_accumulatedForces.Clear();
640 } 902 }
641 // DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, _force); 903 // DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, fSum);
642 BulletSimAPI.AddObjectForce2(Body.Ptr, fSum); 904 // For unknown reasons, "ApplyCentralForce" adds this force to the total force on the object.
643 }); 905 BulletSimAPI.ApplyCentralForce2(BSBody.ptr, fSum);
906 };
907 if (inTaintTime)
908 addForceOperation();
909 else
910 PhysicsScene.TaintedObject("BSPrim.AddForce", addForceOperation);
644 } 911 }
645 912
646 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { 913 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
647 // DetailLog("{0},BSPrim.AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce); 914 // DetailLog("{0},BSPrim.AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce);
648 // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce); 915 // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce);
649 } 916 }
650 public override void SetMomentum(OMV.Vector3 momentum) { 917 public override void SetMomentum(OMV.Vector3 momentum) {
651 // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum); 918 // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum);
652 } 919 }
653 public override void SubscribeEvents(int ms) {
654 _subscribedEventsMs = ms;
655 if (ms > 0)
656 {
657 // make sure first collision happens
658 _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs;
659
660 Scene.TaintedObject("BSPrim.SubscribeEvents", delegate()
661 {
662 BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
663 });
664 }
665 }
666 public override void UnSubscribeEvents() {
667 _subscribedEventsMs = 0;
668 Scene.TaintedObject("BSPrim.UnSubscribeEvents", delegate()
669 {
670 BulletSimAPI.RemoveFromCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
671 });
672 }
673 public override bool SubscribedEvents() {
674 return (_subscribedEventsMs > 0);
675 }
676
677 #region Mass Calculation 920 #region Mass Calculation
678 921
679 private float CalculateMass() 922 private float CalculateMass()
@@ -682,19 +925,19 @@ public sealed class BSPrim : PhysicsActor
682 float tmp; 925 float tmp;
683 926
684 float returnMass = 0; 927 float returnMass = 0;
685 float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f; 928 float hollowAmount = (float)BaseShape.ProfileHollow * 2.0e-5f;
686 float hollowVolume = hollowAmount * hollowAmount; 929 float hollowVolume = hollowAmount * hollowAmount;
687 930
688 switch (_pbs.ProfileShape) 931 switch (BaseShape.ProfileShape)
689 { 932 {
690 case ProfileShape.Square: 933 case ProfileShape.Square:
691 // default box 934 // default box
692 935
693 if (_pbs.PathCurve == (byte)Extrusion.Straight) 936 if (BaseShape.PathCurve == (byte)Extrusion.Straight)
694 { 937 {
695 if (hollowAmount > 0.0) 938 if (hollowAmount > 0.0)
696 { 939 {
697 switch (_pbs.HollowShape) 940 switch (BaseShape.HollowShape)
698 { 941 {
699 case HollowShape.Square: 942 case HollowShape.Square:
700 case HollowShape.Same: 943 case HollowShape.Same:
@@ -718,19 +961,19 @@ public sealed class BSPrim : PhysicsActor
718 } 961 }
719 } 962 }
720 963
721 else if (_pbs.PathCurve == (byte)Extrusion.Curve1) 964 else if (BaseShape.PathCurve == (byte)Extrusion.Curve1)
722 { 965 {
723 //a tube 966 //a tube
724 967
725 volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX); 968 volume *= 0.78539816339e-2f * (float)(200 - BaseShape.PathScaleX);
726 tmp= 1.0f -2.0e-2f * (float)(200 - _pbs.PathScaleY); 969 tmp= 1.0f -2.0e-2f * (float)(200 - BaseShape.PathScaleY);
727 volume -= volume*tmp*tmp; 970 volume -= volume*tmp*tmp;
728 971
729 if (hollowAmount > 0.0) 972 if (hollowAmount > 0.0)
730 { 973 {
731 hollowVolume *= hollowAmount; 974 hollowVolume *= hollowAmount;
732 975
733 switch (_pbs.HollowShape) 976 switch (BaseShape.HollowShape)
734 { 977 {
735 case HollowShape.Square: 978 case HollowShape.Square:
736 case HollowShape.Same: 979 case HollowShape.Same:
@@ -755,13 +998,13 @@ public sealed class BSPrim : PhysicsActor
755 998
756 case ProfileShape.Circle: 999 case ProfileShape.Circle:
757 1000
758 if (_pbs.PathCurve == (byte)Extrusion.Straight) 1001 if (BaseShape.PathCurve == (byte)Extrusion.Straight)
759 { 1002 {
760 volume *= 0.78539816339f; // elipse base 1003 volume *= 0.78539816339f; // elipse base
761 1004
762 if (hollowAmount > 0.0) 1005 if (hollowAmount > 0.0)
763 { 1006 {
764 switch (_pbs.HollowShape) 1007 switch (BaseShape.HollowShape)
765 { 1008 {
766 case HollowShape.Same: 1009 case HollowShape.Same:
767 case HollowShape.Circle: 1010 case HollowShape.Circle:
@@ -783,19 +1026,19 @@ public sealed class BSPrim : PhysicsActor
783 } 1026 }
784 } 1027 }
785 1028
786 else if (_pbs.PathCurve == (byte)Extrusion.Curve1) 1029 else if (BaseShape.PathCurve == (byte)Extrusion.Curve1)
787 { 1030 {
788 volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX); 1031 volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - BaseShape.PathScaleX);
789 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY); 1032 tmp = 1.0f - .02f * (float)(200 - BaseShape.PathScaleY);
790 volume *= (1.0f - tmp * tmp); 1033 volume *= (1.0f - tmp * tmp);
791 1034
792 if (hollowAmount > 0.0) 1035 if (hollowAmount > 0.0)
793 { 1036 {
794 1037
795 // calculate the hollow volume by it's shape compared to the prim shape 1038 // calculate the hollow volume by it's shape compared to the prim shape
796 hollowVolume *= hollowAmount; 1039 hollowVolume *= hollowAmount;
797 1040
798 switch (_pbs.HollowShape) 1041 switch (BaseShape.HollowShape)
799 { 1042 {
800 case HollowShape.Same: 1043 case HollowShape.Same:
801 case HollowShape.Circle: 1044 case HollowShape.Circle:
@@ -819,7 +1062,7 @@ public sealed class BSPrim : PhysicsActor
819 break; 1062 break;
820 1063
821 case ProfileShape.HalfCircle: 1064 case ProfileShape.HalfCircle:
822 if (_pbs.PathCurve == (byte)Extrusion.Curve1) 1065 if (BaseShape.PathCurve == (byte)Extrusion.Curve1)
823 { 1066 {
824 volume *= 0.52359877559829887307710723054658f; 1067 volume *= 0.52359877559829887307710723054658f;
825 } 1068 }
@@ -827,7 +1070,7 @@ public sealed class BSPrim : PhysicsActor
827 1070
828 case ProfileShape.EquilateralTriangle: 1071 case ProfileShape.EquilateralTriangle:
829 1072
830 if (_pbs.PathCurve == (byte)Extrusion.Straight) 1073 if (BaseShape.PathCurve == (byte)Extrusion.Straight)
831 { 1074 {
832 volume *= 0.32475953f; 1075 volume *= 0.32475953f;
833 1076
@@ -835,7 +1078,7 @@ public sealed class BSPrim : PhysicsActor
835 { 1078 {
836 1079
837 // calculate the hollow volume by it's shape compared to the prim shape 1080 // calculate the hollow volume by it's shape compared to the prim shape
838 switch (_pbs.HollowShape) 1081 switch (BaseShape.HollowShape)
839 { 1082 {
840 case HollowShape.Same: 1083 case HollowShape.Same:
841 case HollowShape.Triangle: 1084 case HollowShape.Triangle:
@@ -860,11 +1103,11 @@ public sealed class BSPrim : PhysicsActor
860 volume *= (1.0f - hollowVolume); 1103 volume *= (1.0f - hollowVolume);
861 } 1104 }
862 } 1105 }
863 else if (_pbs.PathCurve == (byte)Extrusion.Curve1) 1106 else if (BaseShape.PathCurve == (byte)Extrusion.Curve1)
864 { 1107 {
865 volume *= 0.32475953f; 1108 volume *= 0.32475953f;
866 volume *= 0.01f * (float)(200 - _pbs.PathScaleX); 1109 volume *= 0.01f * (float)(200 - BaseShape.PathScaleX);
867 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY); 1110 tmp = 1.0f - .02f * (float)(200 - BaseShape.PathScaleY);
868 volume *= (1.0f - tmp * tmp); 1111 volume *= (1.0f - tmp * tmp);
869 1112
870 if (hollowAmount > 0.0) 1113 if (hollowAmount > 0.0)
@@ -872,7 +1115,7 @@ public sealed class BSPrim : PhysicsActor
872 1115
873 hollowVolume *= hollowAmount; 1116 hollowVolume *= hollowAmount;
874 1117
875 switch (_pbs.HollowShape) 1118 switch (BaseShape.HollowShape)
876 { 1119 {
877 case HollowShape.Same: 1120 case HollowShape.Same:
878 case HollowShape.Triangle: 1121 case HollowShape.Triangle:
@@ -912,26 +1155,26 @@ public sealed class BSPrim : PhysicsActor
912 float profileBegin; 1155 float profileBegin;
913 float profileEnd; 1156 float profileEnd;
914 1157
915 if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible) 1158 if (BaseShape.PathCurve == (byte)Extrusion.Straight || BaseShape.PathCurve == (byte)Extrusion.Flexible)
916 { 1159 {
917 taperX1 = _pbs.PathScaleX * 0.01f; 1160 taperX1 = BaseShape.PathScaleX * 0.01f;
918 if (taperX1 > 1.0f) 1161 if (taperX1 > 1.0f)
919 taperX1 = 2.0f - taperX1; 1162 taperX1 = 2.0f - taperX1;
920 taperX = 1.0f - taperX1; 1163 taperX = 1.0f - taperX1;
921 1164
922 taperY1 = _pbs.PathScaleY * 0.01f; 1165 taperY1 = BaseShape.PathScaleY * 0.01f;
923 if (taperY1 > 1.0f) 1166 if (taperY1 > 1.0f)
924 taperY1 = 2.0f - taperY1; 1167 taperY1 = 2.0f - taperY1;
925 taperY = 1.0f - taperY1; 1168 taperY = 1.0f - taperY1;
926 } 1169 }
927 else 1170 else
928 { 1171 {
929 taperX = _pbs.PathTaperX * 0.01f; 1172 taperX = BaseShape.PathTaperX * 0.01f;
930 if (taperX < 0.0f) 1173 if (taperX < 0.0f)
931 taperX = -taperX; 1174 taperX = -taperX;
932 taperX1 = 1.0f - taperX; 1175 taperX1 = 1.0f - taperX;
933 1176
934 taperY = _pbs.PathTaperY * 0.01f; 1177 taperY = BaseShape.PathTaperY * 0.01f;
935 if (taperY < 0.0f) 1178 if (taperY < 0.0f)
936 taperY = -taperY; 1179 taperY = -taperY;
937 taperY1 = 1.0f - taperY; 1180 taperY1 = 1.0f - taperY;
@@ -941,13 +1184,13 @@ public sealed class BSPrim : PhysicsActor
941 1184
942 volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY); 1185 volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY);
943 1186
944 pathBegin = (float)_pbs.PathBegin * 2.0e-5f; 1187 pathBegin = (float)BaseShape.PathBegin * 2.0e-5f;
945 pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f; 1188 pathEnd = 1.0f - (float)BaseShape.PathEnd * 2.0e-5f;
946 volume *= (pathEnd - pathBegin); 1189 volume *= (pathEnd - pathBegin);
947 1190
948 // this is crude aproximation 1191 // this is crude aproximation
949 profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f; 1192 profileBegin = (float)BaseShape.ProfileBegin * 2.0e-5f;
950 profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f; 1193 profileEnd = 1.0f - (float)BaseShape.ProfileEnd * 2.0e-5f;
951 volume *= (profileEnd - profileBegin); 1194 volume *= (profileEnd - profileBegin);
952 1195
953 returnMass = _density * volume; 1196 returnMass = _density * volume;
@@ -967,296 +1210,66 @@ public sealed class BSPrim : PhysicsActor
967 if (returnMass <= 0) 1210 if (returnMass <= 0)
968 returnMass = 0.0001f; 1211 returnMass = 0.0001f;
969 1212
970 if (returnMass > _scene.MaximumObjectMass) 1213 if (returnMass > PhysicsScene.MaximumObjectMass)
971 returnMass = _scene.MaximumObjectMass; 1214 returnMass = PhysicsScene.MaximumObjectMass;
972 1215
973 return returnMass; 1216 return returnMass;
974 }// end CalculateMass 1217 }// end CalculateMass
975 #endregion Mass Calculation 1218 #endregion Mass Calculation
976 1219
977 // Create the geometry information in Bullet for later use
978 // The objects needs a hull if it's physical otherwise a mesh is enough
979 // No locking here because this is done when we know physics is not simulating
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)
983 {
984 // the mesher thought this was too simple to mesh. Use a native Bullet collision shape.
985 bool ret = false;
986 if (!_scene.NeedsMeshing(_pbs))
987 {
988 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
989 {
990 // if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
991 // {
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;
1100
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)
1105 {
1106 // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey);
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 }
1193 }
1194
1195 // create the hull definition in Bullet
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 1220 // Copy prim's info into the BulletSim shape description structure
1233 public void FillShapeInfo(out ShapeData shape) 1221 public void FillShapeInfo(out ShapeData shape)
1234 { 1222 {
1235 shape.ID = _localID; 1223 shape.ID = LocalID;
1236 shape.Type = _shapeType; 1224 shape.Type = ShapeData.PhysicsShapeType.SHAPE_UNKNOWN;
1237 shape.Position = _position; 1225 shape.Position = _position;
1238 shape.Rotation = _orientation; 1226 shape.Rotation = _orientation;
1239 shape.Velocity = _velocity; 1227 shape.Velocity = _velocity;
1240 shape.Scale = _scale; 1228 shape.Size = _size;
1229 shape.Scale = Scale;
1241 shape.Mass = _isPhysical ? _mass : 0f; 1230 shape.Mass = _isPhysical ? _mass : 0f;
1242 shape.Buoyancy = _buoyancy; 1231 shape.Buoyancy = _buoyancy;
1243 shape.HullKey = _hullKey; 1232 shape.HullKey = 0;
1244 shape.MeshKey = _meshKey; 1233 shape.MeshKey = 0;
1245 shape.Friction = _friction; 1234 shape.Friction = _friction;
1246 shape.Restitution = _restitution; 1235 shape.Restitution = _restitution;
1247 shape.Collidable = (!IsPhantom) ? ShapeData.numericTrue : ShapeData.numericFalse; 1236 shape.Collidable = (!IsPhantom) ? ShapeData.numericTrue : ShapeData.numericFalse;
1248 shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue; 1237 shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue;
1238 shape.Solid = IsSolid ? ShapeData.numericFalse : ShapeData.numericTrue;
1249 } 1239 }
1250
1251
1252 // Rebuild the geometry and object. 1240 // Rebuild the geometry and object.
1253 // This is called when the shape changes so we need to recreate the mesh/hull. 1241 // 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 1242 // Called at taint-time!!!
1255 private void RecreateGeomAndObject() 1243 private void CreateGeomAndObject(bool forceRebuild)
1256 { 1244 {
1257 // m_log.DebugFormat("{0}: RecreateGeomAndObject. lID={1}", LogHeader, _localID); 1245 ShapeData shapeData;
1258 if (CreateGeom(true)) 1246 FillShapeInfo(out shapeData);
1259 CreateObject(); 1247
1248 // If this prim is part of a linkset, we must remove and restore the physical
1249 // links if the body is rebuilt.
1250 bool needToRestoreLinkset = false;
1251
1252 // Create the correct physical representation for this type of object.
1253 // Updates BSBody and BSShape with the new information.
1254 // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary.
1255 // Returns 'true' if either the body or the shape was changed.
1256 PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, shapeData, BaseShape,
1257 null, delegate(BulletBody dBody)
1258 {
1259 // Called if the current prim body is about to be destroyed.
1260 // Remove all the physical dependencies on the old body.
1261 // (Maybe someday make the changing of BSShape an event handled by BSLinkset.)
1262 needToRestoreLinkset = Linkset.RemoveBodyDependencies(this);
1263 });
1264
1265 if (needToRestoreLinkset)
1266 {
1267 // If physical body dependencies were removed, restore them
1268 Linkset.RestoreBodyDependencies(this);
1269 }
1270
1271 // Make sure the properties are set on the new object
1272 UpdatePhysicalParameters();
1260 return; 1273 return;
1261 } 1274 }
1262 1275
@@ -1277,7 +1290,7 @@ public sealed class BSPrim : PhysicsActor
1277 const float ACCELERATION_TOLERANCE = 0.01f; 1290 const float ACCELERATION_TOLERANCE = 0.01f;
1278 const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f; 1291 const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f;
1279 1292
1280 public void UpdateProperties(EntityProperties entprop) 1293 public override void UpdateProperties(EntityProperties entprop)
1281 { 1294 {
1282 /* 1295 /*
1283 UpdatedProperties changed = 0; 1296 UpdatedProperties changed = 0;
@@ -1325,7 +1338,7 @@ public sealed class BSPrim : PhysicsActor
1325 // Don't check for damping here -- it's done in BulletSim and SceneObjectPart. 1338 // Don't check for damping here -- it's done in BulletSim and SceneObjectPart.
1326 1339
1327 // Updates only for individual prims and for the root object of a linkset. 1340 // Updates only for individual prims and for the root object of a linkset.
1328 if (_linkset.IsRoot(this)) 1341 if (Linkset.IsRoot(this))
1329 { 1342 {
1330 // Assign to the local variables so the normal set action does not happen 1343 // Assign to the local variables so the normal set action does not happen
1331 _position = entprop.Position; 1344 _position = entprop.Position;
@@ -1334,69 +1347,31 @@ public sealed class BSPrim : PhysicsActor
1334 _acceleration = entprop.Acceleration; 1347 _acceleration = entprop.Acceleration;
1335 _rotationalVelocity = entprop.RotationalVelocity; 1348 _rotationalVelocity = entprop.RotationalVelocity;
1336 1349
1337 // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}", 1350 // remember the current and last set values
1338 // LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); 1351 LastEntityProperties = CurrentEntityProperties;
1339 // DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", 1352 CurrentEntityProperties = entprop;
1340 // LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); 1353
1354 PositionSanityCheck(true);
1355
1356 DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
1357 LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
1358
1359 // BulletSimAPI.DumpRigidBody2(PhysicsScene.World.ptr, BSBody.ptr); // DEBUG DEBUG DEBUG
1341 1360
1342 base.RequestPhysicsterseUpdate(); 1361 base.RequestPhysicsterseUpdate();
1343 } 1362 }
1344 /* 1363 /*
1345 else 1364 else
1346 { 1365 {
1347 // For debugging, we also report the movement of children 1366 // For debugging, report the movement of children
1348 DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", 1367 DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
1349 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, 1368 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
1350 entprop.Acceleration, entprop.RotationalVelocity); 1369 entprop.Acceleration, entprop.RotationalVelocity);
1351 } 1370 }
1352 */ 1371 */
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 1372
1370 // if someone is subscribed to collision events.... 1373 // The linkset implimentation might want to know about this.
1371 if (_subscribedEventsMs != 0) { 1374 Linkset.UpdateProperties(this);
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;
1376
1377 if (collisionCollection == null)
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);
1400 } 1375 }
1401} 1376}
1402} 1377}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index a31c578..db0c99e 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -39,33 +39,27 @@ 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// Debug linkset 42// Test sculpties (verified that they don't work)
43// Test with multiple regions in one simulator
44// Adjust character capsule size when height is adjusted (ScenePresence.SetHeight)
45// Test sculpties
46// Compute physics FPS reasonably 43// Compute physics FPS reasonably
47// Based on material, set density and friction 44// Based on material, set density and friction
48// More efficient memory usage when passing hull information from BSPrim to BulletSim 45// Don't use constraints in linksets of non-physical objects. Means having to move children manually.
49// Move all logic out of the C++ code and into the C# code for easier future modifications.
50// Four states of prim: Physical, regular, phantom and selected. Are we modeling these correctly? 46// Four states of prim: Physical, regular, phantom and selected. Are we modeling these correctly?
51// In SL one can set both physical and phantom (gravity, does not effect others, makes collisions with ground) 47// In SL one can set both physical and phantom (gravity, does not effect others, makes collisions with ground)
52// At the moment, physical and phantom causes object to drop through the terrain 48// At the moment, physical and phantom causes object to drop through the terrain
53// Physical phantom objects and related typing (collision options ) 49// Physical phantom objects and related typing (collision options )
54// Use collision masks for collision with terrain and phantom objects
55// Check out llVolumeDetect. Must do something for that. 50// 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
56// Should prim.link() and prim.delink() membership checking happen at taint time? 53// Should prim.link() and prim.delink() membership checking happen at taint time?
57// changing the position and orientation of a linked prim must rebuild the constraint with the root. 54// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once.
58// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once
59// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect 55// 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)
61// Implement LockAngularMotion 56// Implement LockAngularMotion
62// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation) 57// 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?
64// Remove mesh and Hull stuff. Use mesh passed to bullet and use convexdecom from bullet. 58// Remove mesh and Hull stuff. Use mesh passed to bullet and use convexdecom from bullet.
65// Add PID movement operations. What does ScenePresence.MoveToTarget do? 59// Add PID movement operations. What does ScenePresence.MoveToTarget do?
66// Check terrain size. 128 or 127? 60// Check terrain size. 128 or 127?
67// Raycast 61// Raycast
68// 62//
69namespace OpenSim.Region.Physics.BulletSPlugin 63namespace OpenSim.Region.Physics.BulletSPlugin
70{ 64{
71public class BSScene : PhysicsScene, IPhysicsParameters 65public class BSScene : PhysicsScene, IPhysicsParameters
@@ -73,62 +67,56 @@ public class BSScene : PhysicsScene, IPhysicsParameters
73 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 67 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
74 private static readonly string LogHeader = "[BULLETS SCENE]"; 68 private static readonly string LogHeader = "[BULLETS SCENE]";
75 69
76 public void DebugLog(string mm, params Object[] xx) { if (ShouldDebugLog) m_log.DebugFormat(mm, xx); } 70 // The name of the region we're working for.
71 public string RegionName { get; private set; }
77 72
78 public string BulletSimVersion = "?"; 73 public string BulletSimVersion = "?";
79 74
80 private Dictionary<uint, BSCharacter> m_avatars = new Dictionary<uint, BSCharacter>(); 75 public Dictionary<uint, BSPhysObject> PhysObjects;
81 private Dictionary<uint, BSPrim> m_prims = new Dictionary<uint, BSPrim>(); 76 public BSShapeCollection Shapes;
82 private HashSet<BSCharacter> m_avatarsWithCollisions = new HashSet<BSCharacter>();
83 private HashSet<BSPrim> m_primsWithCollisions = new HashSet<BSPrim>();
84 private List<BSPrim> m_vehicles = new List<BSPrim>();
85 private float[] m_heightMap;
86 private float m_waterLevel;
87 private uint m_worldID;
88 public uint WorldID { get { return m_worldID; } }
89 77
90 // let my minuions use my logger 78 // Keeping track of the objects with collisions so we can report begin and end of a collision
91 public ILog Logger { get { return m_log; } } 79 public HashSet<BSPhysObject> ObjectsWithCollisions = new HashSet<BSPhysObject>();
80 public HashSet<BSPhysObject> ObjectsWithNoMoreCollisions = new HashSet<BSPhysObject>();
81 // Keep track of all the avatars so we can send them a collision event
82 // every tick so OpenSim will update its animation.
83 private HashSet<BSPhysObject> m_avatars = new HashSet<BSPhysObject>();
92 84
93 private bool m_initialized = false; 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>();
94 88
95 private int m_detailedStatsStep = 0; 89 // let my minuions use my logger
90 public ILog Logger { get { return m_log; } }
96 91
97 public IMesher mesher; 92 public IMesher mesher;
98 private float m_meshLOD; 93 // Level of Detail values kept as float because that's what the Meshmerizer wants
99 public float MeshLOD 94 public float MeshLOD { get; private set; }
100 { 95 public float MeshMegaPrimLOD { get; private set; }
101 get { return m_meshLOD; } 96 public float MeshMegaPrimThreshold { get; private set; }
102 } 97 public float SculptLOD { get; private set; }
103 private float m_sculptLOD;
104 public float SculptLOD
105 {
106 get { return m_sculptLOD; }
107 }
108 98
109 private BulletSim m_worldSim; 99 public uint WorldID { get; private set; }
110 public BulletSim World 100 public BulletSim World { get; private set; }
111 {
112 get { return m_worldSim; }
113 }
114 private BSConstraintCollection m_constraintCollection;
115 public BSConstraintCollection Constraints
116 {
117 get { return m_constraintCollection; }
118 }
119 101
102 // All the constraints that have been allocated in this instance.
103 public BSConstraintCollection Constraints { get; private set; }
104
105 // Simulation parameters
120 private int m_maxSubSteps; 106 private int m_maxSubSteps;
121 private float m_fixedTimeStep; 107 private float m_fixedTimeStep;
122 private long m_simulationStep = 0; 108 private long m_simulationStep = 0;
123 public long SimulationStep { get { return m_simulationStep; } } 109 public long SimulationStep { get { return m_simulationStep; } }
124 110 private int m_taintsToProcessPerStep;
125 public float LastSimulatedTimestep { get; private set; }
126 111
127 // A value of the time now so all the collision and update routines do not have to get their own 112 // A value of the time now so all the collision and update routines do not have to get their own
128 // Set to 'now' just before all the prims and actors are called for collisions and updates 113 // Set to 'now' just before all the prims and actors are called for collisions and updates
129 private int m_simulationNowTime; 114 public int SimulationNowTime { get; private set; }
130 public int SimulationNowTime { get { return m_simulationNowTime; } } 115
116 // True if initialized and ready to do simulation steps
117 private bool m_initialized = false;
131 118
119 // Pinned memory used to pass step information between managed and unmanaged
132 private int m_maxCollisionsPerFrame; 120 private int m_maxCollisionsPerFrame;
133 private CollisionDesc[] m_collisionArray; 121 private CollisionDesc[] m_collisionArray;
134 private GCHandle m_collisionArrayPinnedHandle; 122 private GCHandle m_collisionArrayPinnedHandle;
@@ -137,14 +125,19 @@ public class BSScene : PhysicsScene, IPhysicsParameters
137 private EntityProperties[] m_updateArray; 125 private EntityProperties[] m_updateArray;
138 private GCHandle m_updateArrayPinnedHandle; 126 private GCHandle m_updateArrayPinnedHandle;
139 127
140 private bool _meshSculptedPrim = true; // cause scuplted prims to get meshed 128 public bool ShouldMeshSculptedPrim { get; private set; } // cause scuplted prims to get meshed
141 private bool _forceSimplePrimMeshing = false; // if a cube or sphere, let Bullet do internal shapes 129 public bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes
130 public bool ShouldUseHullsForPhysicalObjects { get; private set; } // 'true' if should create hulls for physical objects
142 131
143 public float PID_D { get; private set; } // derivative 132 public float PID_D { get; private set; } // derivative
144 public float PID_P { get; private set; } // proportional 133 public float PID_P { get; private set; } // proportional
145 134
146 public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero 135 public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero
147 public const uint GROUNDPLANE_ID = 1; 136 public const uint GROUNDPLANE_ID = 1;
137 public const uint CHILDTERRAIN_ID = 2; // Terrain allocated based on our mega-prim childre start here
138
139 private float m_waterLevel;
140 public BSTerrainManager TerrainManager { get; private set; }
148 141
149 public ConfigurationParameters Params 142 public ConfigurationParameters Params
150 { 143 {
@@ -154,13 +147,18 @@ public class BSScene : PhysicsScene, IPhysicsParameters
154 { 147 {
155 get { return new Vector3(0f, 0f, Params.gravity); } 148 get { return new Vector3(0f, 0f, Params.gravity); }
156 } 149 }
157 150 // Just the Z value of the gravity
158 private float m_maximumObjectMass; 151 public float DefaultGravityZ
159 public float MaximumObjectMass
160 { 152 {
161 get { return m_maximumObjectMass; } 153 get { return Params.gravity; }
162 } 154 }
163 155
156 public float MaximumObjectMass { get; private set; }
157
158 // When functions in the unmanaged code must be called, it is only
159 // done at a known time just before the simulation step. The taint
160 // system saves all these function calls and executes them in
161 // order before the simulation.
164 public delegate void TaintCallback(); 162 public delegate void TaintCallback();
165 private struct TaintCallbackEntry 163 private struct TaintCallbackEntry
166 { 164 {
@@ -172,15 +170,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters
172 callback = c; 170 callback = c;
173 } 171 }
174 } 172 }
173 private Object _taintLock = new Object(); // lock for using the next object
175 private List<TaintCallbackEntry> _taintedObjects; 174 private List<TaintCallbackEntry> _taintedObjects;
176 private Object _taintLock = new Object();
177 175
178 // A pointer to an instance if this structure is passed to the C++ code 176 // A pointer to an instance if this structure is passed to the C++ code
177 // Used to pass basic configuration values to the unmanaged code.
179 ConfigurationParameters[] m_params; 178 ConfigurationParameters[] m_params;
180 GCHandle m_paramsHandle; 179 GCHandle m_paramsHandle;
181 180
182 public bool ShouldDebugLog { get; private set; } 181 // Handle to the callback used by the unmanaged code to call into the managed code.
183 182 // Used for debug logging.
183 // Need to store the handle in a persistant variable so it won't be freed.
184 private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle; 184 private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle;
185 185
186 // Sometimes you just have to log everything. 186 // Sometimes you just have to log everything.
@@ -189,17 +189,24 @@ public class BSScene : PhysicsScene, IPhysicsParameters
189 private string m_physicsLoggingDir; 189 private string m_physicsLoggingDir;
190 private string m_physicsLoggingPrefix; 190 private string m_physicsLoggingPrefix;
191 private int m_physicsLoggingFileMinutes; 191 private int m_physicsLoggingFileMinutes;
192 // 'true' of the vehicle code is to log lots of details
193 public bool VehicleLoggingEnabled { get; private set; }
192 194
193 private bool m_vehicleLoggingEnabled; 195 #region Construction and Initialization
194 public bool VehicleLoggingEnabled { get { return m_vehicleLoggingEnabled; } }
195
196 public BSScene(string identifier) 196 public BSScene(string identifier)
197 { 197 {
198 m_initialized = false; 198 m_initialized = false;
199 // we are passed the name of the region we're working for.
200 RegionName = identifier;
199 } 201 }
200 202
201 public override void Initialise(IMesher meshmerizer, IConfigSource config) 203 public override void Initialise(IMesher meshmerizer, IConfigSource config)
202 { 204 {
205 mesher = meshmerizer;
206 _taintedObjects = new List<TaintCallbackEntry>();
207 PhysObjects = new Dictionary<uint, BSPhysObject>();
208 Shapes = new BSShapeCollection(this);
209
203 // Allocate pinned memory to pass parameters. 210 // Allocate pinned memory to pass parameters.
204 m_params = new ConfigurationParameters[1]; 211 m_params = new ConfigurationParameters[1];
205 m_paramsHandle = GCHandle.Alloc(m_params, GCHandleType.Pinned); 212 m_paramsHandle = GCHandle.Alloc(m_params, GCHandleType.Pinned);
@@ -215,7 +222,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
215 222
216 // Enable very detailed logging. 223 // Enable very detailed logging.
217 // By creating an empty logger when not logging, the log message invocation code 224 // By creating an empty logger when not logging, the log message invocation code
218 // can be left in and every call doesn't have to check for null. 225 // can be left in and every call doesn't have to check for null.
219 if (m_physicsLoggingEnabled) 226 if (m_physicsLoggingEnabled)
220 { 227 {
221 PhysicsLogging = new Logging.LogWriter(m_physicsLoggingDir, m_physicsLoggingPrefix, m_physicsLoggingFileMinutes); 228 PhysicsLogging = new Logging.LogWriter(m_physicsLoggingDir, m_physicsLoggingPrefix, m_physicsLoggingFileMinutes);
@@ -225,38 +232,39 @@ public class BSScene : PhysicsScene, IPhysicsParameters
225 PhysicsLogging = new Logging.LogWriter(); 232 PhysicsLogging = new Logging.LogWriter();
226 } 233 }
227 234
228 // Get the version of the DLL 235 // If Debug logging level, enable logging from the unmanaged code
229 // TODO: this doesn't work yet. Something wrong with marshaling the returned string. 236 m_DebugLogCallbackHandle = null;
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
234 if (m_log.IsDebugEnabled || PhysicsLogging.Enabled) 237 if (m_log.IsDebugEnabled || PhysicsLogging.Enabled)
235 { 238 {
236 m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader); 239 m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader);
237 if (PhysicsLogging.Enabled) 240 if (PhysicsLogging.Enabled)
241 // The handle is saved in a variable to make sure it doesn't get freed after this call
238 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLoggerPhysLog); 242 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLoggerPhysLog);
239 else 243 else
240 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger); 244 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);
243 } 245 }
244 246
245 _taintedObjects = new List<TaintCallbackEntry>(); 247 // Get the version of the DLL
248 // TODO: this doesn't work yet. Something wrong with marshaling the returned string.
249 // BulletSimVersion = BulletSimAPI.GetVersion();
250 // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion);
246 251
247 mesher = meshmerizer; 252 // The bounding box for the simulated world. The origin is 0,0,0 unless we're
248 // The bounding box for the simulated world 253 // a child in a mega-region.
249 Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, 8192f); 254 // Bullet actually doesn't care about the extents of the simulated
255 // area. It tracks active objects no matter where they are.
256 Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
250 257
251 // m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader); 258 // m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader);
252 m_worldID = BulletSimAPI.Initialize(worldExtent, m_paramsHandle.AddrOfPinnedObject(), 259 World = new BulletSim(0, this, BulletSimAPI.Initialize2(worldExtent, m_paramsHandle.AddrOfPinnedObject(),
253 m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(), 260 m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(),
254 m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject()); 261 m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject(),
262 m_DebugLogCallbackHandle));
263
264 Constraints = new BSConstraintCollection(World);
255 265
256 // Initialization to support the transition to a new API which puts most of the logic 266 TerrainManager = new BSTerrainManager(this);
257 // into the C# code so it is easier to modify and add to. 267 TerrainManager.CreateInitialGroundPlaneAndTerrain();
258 m_worldSim = new BulletSim(m_worldID, this, BulletSimAPI.GetSimHandle2(m_worldID));
259 m_constraintCollection = new BSConstraintCollection(World);
260 268
261 m_initialized = true; 269 m_initialized = true;
262 } 270 }
@@ -281,10 +289,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters
281 // Very detailed logging for physics debugging 289 // Very detailed logging for physics debugging
282 m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false); 290 m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false);
283 m_physicsLoggingDir = pConfig.GetString("PhysicsLoggingDir", "."); 291 m_physicsLoggingDir = pConfig.GetString("PhysicsLoggingDir", ".");
284 m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-"); 292 m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-%REGIONNAME%-");
285 m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5); 293 m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5);
286 // Very detailed logging for vehicle debugging 294 // Very detailed logging for vehicle debugging
287 m_vehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false); 295 VehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false);
296
297 // Do any replacements in the parameters
298 m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName);
288 } 299 }
289 } 300 }
290 } 301 }
@@ -309,13 +320,51 @@ public class BSScene : PhysicsScene, IPhysicsParameters
309 { 320 {
310 m_log.Debug("[BULLETS UNMANAGED]:" + msg); 321 m_log.Debug("[BULLETS UNMANAGED]:" + msg);
311 } 322 }
312 323
313 // Called directly from unmanaged code so don't do much 324 // Called directly from unmanaged code so don't do much
314 private void BulletLoggerPhysLog(string msg) 325 private void BulletLoggerPhysLog(string msg)
315 { 326 {
316 PhysicsLogging.Write("[BULLETS UNMANAGED]:" + msg); 327 DetailLog("[BULLETS UNMANAGED]:" + msg);
317 } 328 }
318 329
330 public override void Dispose()
331 {
332 // m_log.DebugFormat("{0}: Dispose()", LogHeader);
333
334 // make sure no stepping happens while we're deleting stuff
335 m_initialized = false;
336
337 TerrainManager.ReleaseGroundPlaneAndTerrain();
338
339 foreach (KeyValuePair<uint, BSPhysObject> kvp in PhysObjects)
340 {
341 kvp.Value.Destroy();
342 }
343 PhysObjects.Clear();
344
345 // Now that the prims are all cleaned up, there should be no constraints left
346 if (Constraints != null)
347 {
348 Constraints.Dispose();
349 Constraints = null;
350 }
351
352 if (Shapes != null)
353 {
354 Shapes.Dispose();
355 Shapes = null;
356 }
357
358 // Anything left in the unmanaged code should be cleaned out
359 BulletSimAPI.Shutdown2(World.ptr);
360
361 // Not logging any more
362 PhysicsLogging.Close();
363 }
364 #endregion // Construction and Initialization
365
366 #region Prim and Avatar addition and removal
367
319 public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying) 368 public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying)
320 { 369 {
321 m_log.ErrorFormat("{0}: CALL TO AddAvatar in BSScene. NOT IMPLEMENTED", LogHeader); 370 m_log.ErrorFormat("{0}: CALL TO AddAvatar in BSScene. NOT IMPLEMENTED", LogHeader);
@@ -329,7 +378,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters
329 if (!m_initialized) return null; 378 if (!m_initialized) return null;
330 379
331 BSCharacter actor = new BSCharacter(localID, avName, this, position, size, isFlying); 380 BSCharacter actor = new BSCharacter(localID, avName, this, position, size, isFlying);
332 lock (m_avatars) m_avatars.Add(localID, actor); 381 lock (PhysObjects) PhysObjects.Add(localID, actor);
382
383 // TODO: Remove kludge someday.
384 // We must generate a collision for avatars whether they collide or not.
385 // This is required by OpenSim to update avatar animations, etc.
386 lock (m_avatars) m_avatars.Add(actor);
387
333 return actor; 388 return actor;
334 } 389 }
335 390
@@ -344,7 +399,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
344 { 399 {
345 try 400 try
346 { 401 {
347 lock (m_avatars) m_avatars.Remove(actor.LocalID); 402 lock (PhysObjects) PhysObjects.Remove(actor.LocalID);
403 // Remove kludge someday
404 lock (m_avatars) m_avatars.Remove(bsactor);
348 } 405 }
349 catch (Exception e) 406 catch (Exception e)
350 { 407 {
@@ -362,11 +419,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
362 BSPrim bsprim = prim as BSPrim; 419 BSPrim bsprim = prim as BSPrim;
363 if (bsprim != null) 420 if (bsprim != null)
364 { 421 {
365 // DetailLog("{0},RemovePrim,call", bsprim.LocalID); 422 DetailLog("{0},RemovePrim,call", bsprim.LocalID);
366 // m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID); 423 // m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID);
367 try 424 try
368 { 425 {
369 lock (m_prims) m_prims.Remove(bsprim.LocalID); 426 lock (PhysObjects) PhysObjects.Remove(bsprim.LocalID);
370 } 427 }
371 catch (Exception e) 428 catch (Exception e)
372 { 429 {
@@ -388,18 +445,21 @@ public class BSScene : PhysicsScene, IPhysicsParameters
388 445
389 if (!m_initialized) return null; 446 if (!m_initialized) return null;
390 447
391 // DetailLog("{0},AddPrimShape,call", localID); 448 DetailLog("{0},AddPrimShape,call", localID);
392 449
393 BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical); 450 BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical);
394 lock (m_prims) m_prims.Add(localID, prim); 451 lock (PhysObjects) PhysObjects.Add(localID, prim);
395 return prim; 452 return prim;
396 } 453 }
397 454
398 // This is a call from the simulator saying that some physical property has been updated. 455 // This is a call from the simulator saying that some physical property has been updated.
399 // The BulletSim driver senses the changing of relevant properties so this taint 456 // The BulletSim driver senses the changing of relevant properties so this taint
400 // information call is not needed. 457 // information call is not needed.
401 public override void AddPhysicsActorTaint(PhysicsActor prim) { } 458 public override void AddPhysicsActorTaint(PhysicsActor prim) { }
402 459
460 #endregion // Prim and Avatar addition and removal
461
462 #region Simulation
403 // Simulate one timestep 463 // Simulate one timestep
404 public override float Simulate(float timeStep) 464 public override float Simulate(float timeStep)
405 { 465 {
@@ -408,34 +468,46 @@ public class BSScene : PhysicsScene, IPhysicsParameters
408 int collidersCount = 0; 468 int collidersCount = 0;
409 IntPtr collidersPtr; 469 IntPtr collidersPtr;
410 470
411 LastSimulatedTimestep = timeStep; 471 int beforeTime = 0;
472 int simTime = 0;
412 473
413 // prevent simulation until we've been initialized 474 // prevent simulation until we've been initialized
414 if (!m_initialized) return 10.0f; 475 if (!m_initialized) return 5.0f;
415
416 int simulateStartTime = Util.EnvironmentTickCount();
417 476
418 // update the prim states while we know the physics engine is not busy 477 // update the prim states while we know the physics engine is not busy
478 int numTaints = _taintedObjects.Count;
419 ProcessTaints(); 479 ProcessTaints();
420 480
421 // Some of the prims operate with special vehicle properties 481 // Some of the prims operate with special vehicle properties
422 ProcessVehicles(timeStep); 482 ProcessVehicles(timeStep);
483 numTaints += _taintedObjects.Count;
423 ProcessTaints(); // the vehicles might have added taints 484 ProcessTaints(); // the vehicles might have added taints
424 485
425 // step the physical world one interval 486 // step the physical world one interval
426 m_simulationStep++; 487 m_simulationStep++;
427 int numSubSteps = 0; 488 int numSubSteps = 0;
489
490 // DEBUG
491 // DetailLog("{0},BSScene.Simulate,beforeStep,ntaimts={1},step={2}", DetailLogZero, numTaints, m_simulationStep);
492
428 try 493 try
429 { 494 {
430 numSubSteps = BulletSimAPI.PhysicsStep(m_worldID, timeStep, m_maxSubSteps, m_fixedTimeStep, 495 if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount();
496
497 numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep,
431 out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr); 498 out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr);
432 // DetailLog("{0},Simulate,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount); 499
500 if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime);
501 DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}",
502 DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount);
433 } 503 }
434 catch (Exception e) 504 catch (Exception e)
435 { 505 {
436 m_log.WarnFormat("{0},PhysicsStep Exception: substeps={1}, updates={2}, colliders={3}, e={4}", LogHeader, numSubSteps, updatedEntityCount, collidersCount, e); 506 m_log.WarnFormat("{0},PhysicsStep Exception: nTaints={1}, substeps={2}, updates={3}, colliders={4}, e={5}",
437 // DetailLog("{0},PhysicsStepException,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount); 507 LogHeader, numTaints, numSubSteps, updatedEntityCount, collidersCount, e);
438 // updatedEntityCount = 0; 508 DetailLog("{0},PhysicsStepException,call, nTaints={1}, substeps={2}, updates={3}, colliders={4}",
509 DetailLogZero, numTaints, numSubSteps, updatedEntityCount, collidersCount);
510 updatedEntityCount = 0;
439 collidersCount = 0; 511 collidersCount = 0;
440 } 512 }
441 513
@@ -443,7 +515,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
443 // Don't have to use the pointers passed back since we know it is the same pinned memory we passed in 515 // Don't have to use the pointers passed back since we know it is the same pinned memory we passed in
444 516
445 // Get a value for 'now' so all the collision and update routines don't have to get their own 517 // Get a value for 'now' so all the collision and update routines don't have to get their own
446 m_simulationNowTime = Util.EnvironmentTickCount(); 518 SimulationNowTime = Util.EnvironmentTickCount();
447 519
448 // If there were collisions, process them by sending the event to the prim. 520 // If there were collisions, process them by sending the event to the prim.
449 // Collisions must be processed before updates. 521 // Collisions must be processed before updates.
@@ -462,19 +534,32 @@ public class BSScene : PhysicsScene, IPhysicsParameters
462 534
463 // The above SendCollision's batch up the collisions on the objects. 535 // The above SendCollision's batch up the collisions on the objects.
464 // Now push the collisions into the simulator. 536 // Now push the collisions into the simulator.
465 foreach (BSPrim bsp in m_primsWithCollisions) 537 if (ObjectsWithCollisions.Count > 0)
466 bsp.SendCollisions(); 538 {
467 m_primsWithCollisions.Clear(); 539 foreach (BSPhysObject bsp in ObjectsWithCollisions)
468 540 if (!bsp.SendCollisions())
469 // This is a kludge to get avatar movement updated. 541 {
470 // Don't send collisions only if there were collisions -- send everytime. 542 // If the object is done colliding, see that it's removed from the colliding list
471 // ODE sends collisions even if there are none and this is used to update 543 ObjectsWithNoMoreCollisions.Add(bsp);
472 // avatar animations and stuff. 544 }
473 // foreach (BSCharacter bsc in m_avatarsWithCollisions) 545 }
474 // bsc.SendCollisions(); 546
475 foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars) 547 // This is a kludge to get avatar movement updates.
476 kvp.Value.SendCollisions(); 548 // The simulator expects collisions for avatars even if there are have been no collisions.
477 m_avatarsWithCollisions.Clear(); 549 // The event updates avatar animations and stuff.
550 // If you fix avatar animation updates, remove this overhead and let normal collision processing happen.
551 foreach (BSPhysObject bsp in m_avatars)
552 if (!ObjectsWithCollisions.Contains(bsp)) // don't call avatars twice
553 bsp.SendCollisions();
554
555 // Objects that are done colliding are removed from the ObjectsWithCollisions list.
556 // Not done above because it is inside an iteration of ObjectWithCollisions.
557 if (ObjectsWithNoMoreCollisions.Count > 0)
558 {
559 foreach (BSPhysObject po in ObjectsWithNoMoreCollisions)
560 ObjectsWithCollisions.Remove(po);
561 ObjectsWithNoMoreCollisions.Clear();
562 }
478 563
479 // If any of the objects had updated properties, tell the object it has been changed by the physics engine 564 // If any of the objects had updated properties, tell the object it has been changed by the physics engine
480 if (updatedEntityCount > 0) 565 if (updatedEntityCount > 0)
@@ -482,145 +567,102 @@ public class BSScene : PhysicsScene, IPhysicsParameters
482 for (int ii = 0; ii < updatedEntityCount; ii++) 567 for (int ii = 0; ii < updatedEntityCount; ii++)
483 { 568 {
484 EntityProperties entprop = m_updateArray[ii]; 569 EntityProperties entprop = m_updateArray[ii];
485 BSPrim prim; 570 BSPhysObject pobj;
486 if (m_prims.TryGetValue(entprop.ID, out prim)) 571 if (PhysObjects.TryGetValue(entprop.ID, out pobj))
487 { 572 {
488 prim.UpdateProperties(entprop); 573 pobj.UpdateProperties(entprop);
489 continue;
490 }
491 BSCharacter actor;
492 if (m_avatars.TryGetValue(entprop.ID, out actor))
493 {
494 actor.UpdateProperties(entprop);
495 continue;
496 } 574 }
497 } 575 }
498 } 576 }
499 577
500 // If enabled, call into the physics engine to dump statistics 578 // This causes the unmanaged code to output ALL the values found in ALL the objects in the world.
501 if (m_detailedStatsStep > 0) 579 // Only enable this in a limited test world with few objects.
502 { 580 // BulletSimAPI.DumpAllInfo2(World.ptr); // DEBUG DEBUG DEBUG
503 if ((m_simulationStep % m_detailedStatsStep) == 0)
504 {
505 BulletSimAPI.DumpBulletStatistics();
506 }
507 }
508 581
509 // this is a waste since the outside routine also calcuates the physics simulation 582 // The physics engine returns the number of milliseconds it simulated this call.
510 // period. TODO: There should be a way of computing physics frames from simulator computation. 583 // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS.
511 // long simulateTotalTime = Util.EnvironmentTickCountSubtract(simulateStartTime); 584 // We multiply by 55 to give a recognizable running rate (55 or less).
512 // return (timeStep * (float)simulateTotalTime); 585 return numSubSteps * m_fixedTimeStep * 1000 * 55;
513 586 // return timeStep * 1000 * 55;
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);
521 } 587 }
522 588
523 // Something has collided 589 // Something has collided
524 private void SendCollision(uint localID, uint collidingWith, Vector3 collidePoint, Vector3 collideNormal, float penitration) 590 private void SendCollision(uint localID, uint collidingWith, Vector3 collidePoint, Vector3 collideNormal, float penetration)
525 { 591 {
526 if (localID == TERRAIN_ID || localID == GROUNDPLANE_ID) 592 if (localID <= TerrainManager.HighestTerrainID)
527 { 593 {
528 return; // don't send collisions to the terrain 594 return; // don't send collisions to the terrain
529 } 595 }
530 596
531 ActorTypes type = ActorTypes.Prim; 597 BSPhysObject collider;
532 if (collidingWith == TERRAIN_ID || collidingWith == GROUNDPLANE_ID) 598 if (!PhysObjects.TryGetValue(localID, out collider))
533 type = ActorTypes.Ground; 599 {
534 else if (m_avatars.ContainsKey(collidingWith)) 600 // If the object that is colliding cannot be found, just ignore the collision.
535 type = ActorTypes.Agent; 601 DetailLog("{0},BSScene.SendCollision,colliderNotInObjectList,id={1},with={2}", DetailLogZero, localID, collidingWith);
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);
541 return; 602 return;
542 } 603 }
543 BSCharacter actor; 604
544 if (m_avatars.TryGetValue(localID, out actor)) { 605 // The terrain is not in the physical object list so 'collidee' can be null when Collide() is called.
545 actor.Collide(collidingWith, type, collidePoint, collideNormal, penitration); 606 BSPhysObject collidee = null;
546 m_avatarsWithCollisions.Add(actor); 607 PhysObjects.TryGetValue(collidingWith, out collidee);
547 return; 608
609 // DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith);
610
611 if (collider.Collide(collidingWith, collidee, collidePoint, collideNormal, penetration))
612 {
613 // If a collision was posted, remember to send it to the simulator
614 ObjectsWithCollisions.Add(collider);
548 } 615 }
616
549 return; 617 return;
550 } 618 }
551 619
552 public override void GetResults() { } 620 #endregion // Simulation
553 621
554 public override void SetTerrain(float[] heightMap) { 622 public override void GetResults() { }
555 m_heightMap = heightMap;
556 this.TaintedObject("BSScene.SetTerrain", delegate()
557 {
558 BulletSimAPI.SetHeightmap(m_worldID, m_heightMap);
559 });
560 }
561 623
562 // Someday we will have complex terrain with caves and tunnels 624 #region Terrain
563 // For the moment, it's flat and convex
564 public float GetTerrainHeightAtXYZ(Vector3 loc)
565 {
566 return GetTerrainHeightAtXY(loc.X, loc.Y);
567 }
568 625
569 public float GetTerrainHeightAtXY(float tX, float tY) 626 public override void SetTerrain(float[] heightMap) {
570 { 627 TerrainManager.SetTerrain(heightMap);
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)];
574 } 628 }
575 629
576 public override void SetWaterLevel(float baseheight) 630 public override void SetWaterLevel(float baseheight)
577 { 631 {
578 m_waterLevel = baseheight; 632 m_waterLevel = baseheight;
579 // TODO: pass to physics engine so things will float?
580 } 633 }
581 public float GetWaterLevel() 634 // Someday....
635 public float GetWaterLevelAtXYZ(Vector3 loc)
582 { 636 {
583 return m_waterLevel; 637 return m_waterLevel;
584 } 638 }
585 639
586 public override void DeleteTerrain() 640 public override void DeleteTerrain()
587 { 641 {
588 // m_log.DebugFormat("{0}: DeleteTerrain()", LogHeader); 642 // m_log.DebugFormat("{0}: DeleteTerrain()", LogHeader);
589 } 643 }
590 644
591 public override void Dispose() 645 // Although no one seems to check this, I do support combining.
646 public override bool SupportsCombining()
592 { 647 {
593 // m_log.DebugFormat("{0}: Dispose()", LogHeader); 648 return TerrainManager.SupportsCombining();
594 649 }
595 // make sure no stepping happens while we're deleting stuff 650 // This call says I am a child to region zero in a mega-region. 'pScene' is that
596 m_initialized = false; 651 // of region zero, 'offset' is my offset from regions zero's origin, and
597 652 // 'extents' is the largest XY that is handled in my region.
598 foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars) 653 public override void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents)
599 { 654 {
600 kvp.Value.Destroy(); 655 TerrainManager.Combine(pScene, offset, extents);
601 } 656 }
602 m_avatars.Clear();
603
604 foreach (KeyValuePair<uint, BSPrim> kvp in m_prims)
605 {
606 kvp.Value.Destroy();
607 }
608 m_prims.Clear();
609
610 // Now that the prims are all cleaned up, there should be no constraints left
611 if (m_constraintCollection != null)
612 {
613 m_constraintCollection.Dispose();
614 m_constraintCollection = null;
615 }
616
617 // Anything left in the unmanaged code should be cleaned out
618 BulletSimAPI.Shutdown(WorldID);
619 657
620 // Not logging any more 658 // Unhook all the combining that I know about.
621 PhysicsLogging.Close(); 659 public override void UnCombine(PhysicsScene pScene)
660 {
661 TerrainManager.UnCombine(pScene);
622 } 662 }
623 663
664 #endregion // Terrain
665
624 public override Dictionary<uint, float> GetTopColliders() 666 public override Dictionary<uint, float> GetTopColliders()
625 { 667 {
626 return new Dictionary<uint, float>(); 668 return new Dictionary<uint, float>();
@@ -628,121 +670,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters
628 670
629 public override bool IsThreaded { get { return false; } } 671 public override bool IsThreaded { get { return false; } }
630 672
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)
637 {
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)
645 {
646 // Render sculpties as boxes
647 return false;
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))
657 {
658
659 if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
660 && pbs.ProfileHollow == 0
661 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
662 && pbs.PathBegin == 0 && pbs.PathEnd == 0
663 && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
664 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
665 && pbs.PathShearX == 0 && pbs.PathShearY == 0)
666 {
667 return false;
668 }
669 }
670 }
671
672 /* TODO: verify that the mesher will now do all these shapes
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)
704 {
705 iPropertiesNotSupportedDefault++;
706 }
707 }
708 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
709 {
710 if (pbs.PathCurve == (byte)Extrusion.Straight)
711 {
712 iPropertiesNotSupportedDefault++;
713 }
714 // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
715 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
716 {
717 iPropertiesNotSupportedDefault++;
718 }
719 }
720 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
721 {
722 if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2)
723 {
724 iPropertiesNotSupportedDefault++;
725 }
726 }
727 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
728 {
729 if (pbs.PathCurve == (byte)Extrusion.Straight)
730 {
731 iPropertiesNotSupportedDefault++;
732 }
733 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
734 {
735 iPropertiesNotSupportedDefault++;
736 }
737 }
738 if (iPropertiesNotSupportedDefault == 0)
739 {
740 return false;
741 }
742 */
743 return true;
744 }
745
746 // Calls to the PhysicsActors can't directly call into the physics engine 673 // 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. 674 // 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. 675 // We rely on C#'s closure to save and restore the context for the delegate.
@@ -751,7 +678,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
751 if (!m_initialized) return; 678 if (!m_initialized) return;
752 679
753 lock (_taintLock) 680 lock (_taintLock)
681 {
754 _taintedObjects.Add(new TaintCallbackEntry(ident, callback)); 682 _taintedObjects.Add(new TaintCallbackEntry(ident, callback));
683 }
684
755 return; 685 return;
756 } 686 }
757 687
@@ -762,6 +692,35 @@ public class BSScene : PhysicsScene, IPhysicsParameters
762 { 692 {
763 if (_taintedObjects.Count > 0) // save allocating new list if there is nothing to process 693 if (_taintedObjects.Count > 0) // save allocating new list if there is nothing to process
764 { 694 {
695 int taintCount = m_taintsToProcessPerStep;
696 TaintCallbackEntry oneCallback = new TaintCallbackEntry();
697 while (_taintedObjects.Count > 0 && taintCount-- > 0)
698 {
699 bool gotOne = false;
700 lock (_taintLock)
701 {
702 if (_taintedObjects.Count > 0)
703 {
704 oneCallback = _taintedObjects[0];
705 _taintedObjects.RemoveAt(0);
706 gotOne = true;
707 }
708 }
709 if (gotOne)
710 {
711 try
712 {
713 DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, oneCallback.ident);
714 oneCallback.callback();
715 }
716 catch (Exception e)
717 {
718 DetailLog("{0},BSScene.ProcessTaints,doTaintException,id={1}", DetailLogZero, oneCallback.ident); // DEBUG DEBUG DEBUG
719 m_log.ErrorFormat("{0}: ProcessTaints: {1}: Exception: {2}", LogHeader, oneCallback.ident, e);
720 }
721 }
722 }
723 /*
765 // swizzle a new list into the list location so we can process what's there 724 // swizzle a new list into the list location so we can process what's there
766 List<TaintCallbackEntry> oldList; 725 List<TaintCallbackEntry> oldList;
767 lock (_taintLock) 726 lock (_taintLock)
@@ -774,6 +733,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
774 { 733 {
775 try 734 try
776 { 735 {
736 DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, tcbe.ident); // DEBUG DEBUG DEBUG
777 tcbe.callback(); 737 tcbe.callback();
778 } 738 }
779 catch (Exception e) 739 catch (Exception e)
@@ -782,6 +742,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
782 } 742 }
783 } 743 }
784 oldList.Clear(); 744 oldList.Clear();
745 */
785 } 746 }
786 } 747 }
787 748
@@ -789,13 +750,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
789 750
790 public void VehicleInSceneTypeChanged(BSPrim vehic, Vehicle newType) 751 public void VehicleInSceneTypeChanged(BSPrim vehic, Vehicle newType)
791 { 752 {
792 if (newType == Vehicle.TYPE_NONE) 753 RemoveVehiclePrim(vehic);
793 { 754 if (newType != Vehicle.TYPE_NONE)
794 RemoveVehiclePrim(vehic);
795 }
796 else
797 { 755 {
798 // make it so the scene will call us each tick to do vehicle things 756 // make it so the scene will call us each tick to do vehicle things
799 AddVehiclePrim(vehic); 757 AddVehiclePrim(vehic);
800 } 758 }
801 } 759 }
@@ -827,21 +785,22 @@ public class BSScene : PhysicsScene, IPhysicsParameters
827 } 785 }
828 786
829 // Some prims have extra vehicle actions 787 // Some prims have extra vehicle actions
830 // no locking because only called when physics engine is not busy 788 // Called at taint time!
831 private void ProcessVehicles(float timeStep) 789 private void ProcessVehicles(float timeStep)
832 { 790 {
833 foreach (BSPrim prim in m_vehicles) 791 foreach (BSPhysObject pobj in m_vehicles)
834 { 792 {
835 prim.StepVehicle(timeStep); 793 pobj.StepVehicle(timeStep);
836 } 794 }
837 } 795 }
838 #endregion Vehicles 796 #endregion Vehicles
839 797
840 #region Parameters 798 #region INI and command line parameter processing
841 799
842 delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val); 800 delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val);
843 delegate float ParamGet(BSScene scene); 801 delegate float ParamGet(BSScene scene);
844 delegate void ParamSet(BSScene scene, string paramName, uint localID, float val); 802 delegate void ParamSet(BSScene scene, string paramName, uint localID, float val);
803 delegate void SetOnObject(BSScene scene, BSPhysObject obj, float val);
845 804
846 private struct ParameterDefn 805 private struct ParameterDefn
847 { 806 {
@@ -851,6 +810,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
851 public ParamUser userParam; // get the value from the configuration file 810 public ParamUser userParam; // get the value from the configuration file
852 public ParamGet getter; // return the current value stored for this parameter 811 public ParamGet getter; // return the current value stored for this parameter
853 public ParamSet setter; // set the current value for this parameter 812 public ParamSet setter; // set the current value for this parameter
813 public SetOnObject onObject; // set the value on an object in the physical domain
854 public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s) 814 public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s)
855 { 815 {
856 name = n; 816 name = n;
@@ -859,6 +819,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters
859 userParam = u; 819 userParam = u;
860 getter = g; 820 getter = g;
861 setter = s; 821 setter = s;
822 onObject = null;
823 }
824 public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s, SetOnObject o)
825 {
826 name = n;
827 desc = d;
828 defaultValue = v;
829 userParam = u;
830 getter = g;
831 setter = s;
832 onObject = o;
862 } 833 }
863 } 834 }
864 835
@@ -869,7 +840,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
869 // getters and setters. 840 // getters and setters.
870 // It is easiest to find an existing definition and copy it. 841 // It is easiest to find an existing definition and copy it.
871 // Parameter values are floats. Booleans are converted to a floating value. 842 // Parameter values are floats. Booleans are converted to a floating value.
872 // 843 //
873 // A ParameterDefn() takes the following parameters: 844 // A ParameterDefn() takes the following parameters:
874 // -- the text name of the parameter. This is used for console input and ini file. 845 // -- the text name of the parameter. This is used for console input and ini file.
875 // -- a short text description of the parameter. This shows up in the console listing. 846 // -- a short text description of the parameter. This shows up in the console listing.
@@ -880,6 +851,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
880 // 851 //
881 // The single letter parameters for the delegates are: 852 // The single letter parameters for the delegates are:
882 // s = BSScene 853 // s = BSScene
854 // o = BSPhysObject
883 // p = string parameter name 855 // p = string parameter name
884 // l = localID of referenced object 856 // l = localID of referenced object
885 // v = float value 857 // v = float value
@@ -888,25 +860,40 @@ public class BSScene : PhysicsScene, IPhysicsParameters
888 { 860 {
889 new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties", 861 new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties",
890 ConfigurationParameters.numericTrue, 862 ConfigurationParameters.numericTrue,
891 (s,cf,p,v) => { s._meshSculptedPrim = cf.GetBoolean(p, s.BoolNumeric(v)); }, 863 (s,cf,p,v) => { s.ShouldMeshSculptedPrim = cf.GetBoolean(p, s.BoolNumeric(v)); },
892 (s) => { return s.NumericBool(s._meshSculptedPrim); }, 864 (s) => { return s.NumericBool(s.ShouldMeshSculptedPrim); },
893 (s,p,l,v) => { s._meshSculptedPrim = s.BoolNumeric(v); } ), 865 (s,p,l,v) => { s.ShouldMeshSculptedPrim = s.BoolNumeric(v); } ),
894 new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects", 866 new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects",
895 ConfigurationParameters.numericFalse, 867 ConfigurationParameters.numericFalse,
896 (s,cf,p,v) => { s._forceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); }, 868 (s,cf,p,v) => { s.ShouldForceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); },
897 (s) => { return s.NumericBool(s._forceSimplePrimMeshing); }, 869 (s) => { return s.NumericBool(s.ShouldForceSimplePrimMeshing); },
898 (s,p,l,v) => { s._forceSimplePrimMeshing = s.BoolNumeric(v); } ), 870 (s,p,l,v) => { s.ShouldForceSimplePrimMeshing = s.BoolNumeric(v); } ),
871 new ParameterDefn("UseHullsForPhysicalObjects", "If true, create hulls for physical objects",
872 ConfigurationParameters.numericTrue,
873 (s,cf,p,v) => { s.ShouldUseHullsForPhysicalObjects = cf.GetBoolean(p, s.BoolNumeric(v)); },
874 (s) => { return s.NumericBool(s.ShouldUseHullsForPhysicalObjects); },
875 (s,p,l,v) => { s.ShouldUseHullsForPhysicalObjects = s.BoolNumeric(v); } ),
899 876
900 new ParameterDefn("MeshLOD", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)", 877 new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)",
901 8f, 878 8f,
902 (s,cf,p,v) => { s.m_meshLOD = cf.GetInt(p, (int)v); }, 879 (s,cf,p,v) => { s.MeshLOD = (float)cf.GetInt(p, (int)v); },
903 (s) => { return (float)s.m_meshLOD; }, 880 (s) => { return s.MeshLOD; },
904 (s,p,l,v) => { s.m_meshLOD = (int)v; } ), 881 (s,p,l,v) => { s.MeshLOD = v; } ),
905 new ParameterDefn("SculptLOD", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)", 882 new ParameterDefn("MeshLevelOfDetailMegaPrim", "Level of detail to render meshes larger than threshold meters",
883 16f,
884 (s,cf,p,v) => { s.MeshMegaPrimLOD = (float)cf.GetInt(p, (int)v); },
885 (s) => { return s.MeshMegaPrimLOD; },
886 (s,p,l,v) => { s.MeshMegaPrimLOD = v; } ),
887 new ParameterDefn("MeshLevelOfDetailMegaPrimThreshold", "Size (in meters) of a mesh before using MeshMegaPrimLOD",
888 10f,
889 (s,cf,p,v) => { s.MeshMegaPrimThreshold = (float)cf.GetInt(p, (int)v); },
890 (s) => { return s.MeshMegaPrimThreshold; },
891 (s,p,l,v) => { s.MeshMegaPrimThreshold = v; } ),
892 new ParameterDefn("SculptLevelOfDetail", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)",
906 32f, 893 32f,
907 (s,cf,p,v) => { s.m_sculptLOD = cf.GetInt(p, (int)v); }, 894 (s,cf,p,v) => { s.SculptLOD = (float)cf.GetInt(p, (int)v); },
908 (s) => { return (float)s.m_sculptLOD; }, 895 (s) => { return s.SculptLOD; },
909 (s,p,l,v) => { s.m_sculptLOD = (int)v; } ), 896 (s,p,l,v) => { s.SculptLOD = v; } ),
910 897
911 new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps", 898 new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps",
912 10f, 899 10f,
@@ -928,11 +915,16 @@ public class BSScene : PhysicsScene, IPhysicsParameters
928 (s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); }, 915 (s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); },
929 (s) => { return (float)s.m_maxUpdatesPerFrame; }, 916 (s) => { return (float)s.m_maxUpdatesPerFrame; },
930 (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ), 917 (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ),
918 new ParameterDefn("MaxTaintsToProcessPerStep", "Number of update taints to process before each simulation step",
919 100f,
920 (s,cf,p,v) => { s.m_taintsToProcessPerStep = cf.GetInt(p, (int)v); },
921 (s) => { return (float)s.m_taintsToProcessPerStep; },
922 (s,p,l,v) => { s.m_taintsToProcessPerStep = (int)v; } ),
931 new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)", 923 new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)",
932 10000.01f, 924 10000.01f,
933 (s,cf,p,v) => { s.m_maximumObjectMass = cf.GetFloat(p, v); }, 925 (s,cf,p,v) => { s.MaximumObjectMass = cf.GetFloat(p, v); },
934 (s) => { return (float)s.m_maximumObjectMass; }, 926 (s) => { return (float)s.MaximumObjectMass; },
935 (s,p,l,v) => { s.m_maximumObjectMass = v; } ), 927 (s,p,l,v) => { s.MaximumObjectMass = v; } ),
936 928
937 new ParameterDefn("PID_D", "Derivitive factor for motion smoothing", 929 new ParameterDefn("PID_D", "Derivitive factor for motion smoothing",
938 2200f, 930 2200f,
@@ -969,104 +961,118 @@ public class BSScene : PhysicsScene, IPhysicsParameters
969 -9.80665f, 961 -9.80665f,
970 (s,cf,p,v) => { s.m_params[0].gravity = cf.GetFloat(p, v); }, 962 (s,cf,p,v) => { s.m_params[0].gravity = cf.GetFloat(p, v); },
971 (s) => { return s.m_params[0].gravity; }, 963 (s) => { return s.m_params[0].gravity; },
972 (s,p,l,v) => { s.m_params[0].gravity = v; s.TaintedUpdateParameter(p,l,v); } ), 964 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].gravity, p, PhysParameterEntry.APPLY_TO_NONE, v); },
965 (s,o,v) => { BulletSimAPI.SetGravity2(s.World.ptr, new Vector3(0f,0f,v)); } ),
973 966
974 967
975 new ParameterDefn("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)", 968 new ParameterDefn("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)",
976 0f, 969 0f,
977 (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); }, 970 (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); },
978 (s) => { return s.m_params[0].linearDamping; }, 971 (s) => { return s.m_params[0].linearDamping; },
979 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearDamping, p, l, v); } ), 972 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearDamping, p, l, v); },
973 (s,o,v) => { BulletSimAPI.SetDamping2(o.BSBody.ptr, v, v); } ),
980 new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)", 974 new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)",
981 0f, 975 0f,
982 (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); }, 976 (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); },
983 (s) => { return s.m_params[0].angularDamping; }, 977 (s) => { return s.m_params[0].angularDamping; },
984 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularDamping, p, l, v); } ), 978 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularDamping, p, l, v); },
979 (s,o,v) => { BulletSimAPI.SetDamping2(o.BSBody.ptr, v, v); } ),
985 new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static", 980 new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static",
986 0.2f, 981 0.2f,
987 (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); }, 982 (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); },
988 (s) => { return s.m_params[0].deactivationTime; }, 983 (s) => { return s.m_params[0].deactivationTime; },
989 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].deactivationTime, p, l, v); } ), 984 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].deactivationTime, p, l, v); },
985 (s,o,v) => { BulletSimAPI.SetDeactivationTime2(o.BSBody.ptr, v); } ),
990 new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static", 986 new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static",
991 0.8f, 987 0.8f,
992 (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); }, 988 (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); },
993 (s) => { return s.m_params[0].linearSleepingThreshold; }, 989 (s) => { return s.m_params[0].linearSleepingThreshold; },
994 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearSleepingThreshold, p, l, v); } ), 990 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearSleepingThreshold, p, l, v); },
991 (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.BSBody.ptr, v, v); } ),
995 new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static", 992 new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static",
996 1.0f, 993 1.0f,
997 (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); }, 994 (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); },
998 (s) => { return s.m_params[0].angularSleepingThreshold; }, 995 (s) => { return s.m_params[0].angularSleepingThreshold; },
999 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularSleepingThreshold, p, l, v); } ), 996 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularSleepingThreshold, p, l, v); },
997 (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.BSBody.ptr, v, v); } ),
1000 new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" , 998 new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ,
1001 0f, // set to zero to disable 999 0f, // set to zero to disable
1002 (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); }, 1000 (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); },
1003 (s) => { return s.m_params[0].ccdMotionThreshold; }, 1001 (s) => { return s.m_params[0].ccdMotionThreshold; },
1004 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdMotionThreshold, p, l, v); } ), 1002 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdMotionThreshold, p, l, v); },
1003 (s,o,v) => { BulletSimAPI.SetCcdMotionThreshold2(o.BSBody.ptr, v); } ),
1005 new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" , 1004 new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" ,
1006 0f, 1005 0f,
1007 (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); }, 1006 (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); },
1008 (s) => { return s.m_params[0].ccdSweptSphereRadius; }, 1007 (s) => { return s.m_params[0].ccdSweptSphereRadius; },
1009 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); } ), 1008 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); },
1009 (s,o,v) => { BulletSimAPI.SetCcdSweepSphereRadius2(o.BSBody.ptr, v); } ),
1010 new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" , 1010 new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" ,
1011 0.1f, 1011 0.1f,
1012 (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); },
1013 (s) => { return s.m_params[0].contactProcessingThreshold; }, 1013 (s) => { return s.m_params[0].contactProcessingThreshold; },
1014 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].contactProcessingThreshold, p, l, v); } ), 1014 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].contactProcessingThreshold, p, l, v); },
1015 (s,o,v) => { BulletSimAPI.SetContactProcessingThreshold2(o.BSBody.ptr, v); } ),
1015 1016
1016 new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" , 1017 new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" ,
1017 0.5f, 1018 0.5f,
1018 (s,cf,p,v) => { s.m_params[0].terrainFriction = cf.GetFloat(p, v); }, 1019 (s,cf,p,v) => { s.m_params[0].terrainFriction = cf.GetFloat(p, v); },
1019 (s) => { return s.m_params[0].terrainFriction; }, 1020 (s) => { return s.m_params[0].terrainFriction; },
1020 (s,p,l,v) => { s.m_params[0].terrainFriction = v; s.TaintedUpdateParameter(p,l,v); } ), 1021 (s,p,l,v) => { s.m_params[0].terrainFriction = v; /* TODO: set on real terrain */} ),
1021 new ParameterDefn("TerrainHitFraction", "Distance to measure hit collisions" , 1022 new ParameterDefn("TerrainHitFraction", "Distance to measure hit collisions" ,
1022 0.8f, 1023 0.8f,
1023 (s,cf,p,v) => { s.m_params[0].terrainHitFraction = cf.GetFloat(p, v); }, 1024 (s,cf,p,v) => { s.m_params[0].terrainHitFraction = cf.GetFloat(p, v); },
1024 (s) => { return s.m_params[0].terrainHitFraction; }, 1025 (s) => { return s.m_params[0].terrainHitFraction; },
1025 (s,p,l,v) => { s.m_params[0].terrainHitFraction = v; s.TaintedUpdateParameter(p,l,v); } ), 1026 (s,p,l,v) => { s.m_params[0].terrainHitFraction = v; /* TODO: set on real terrain */ } ),
1026 new ParameterDefn("TerrainRestitution", "Bouncyness" , 1027 new ParameterDefn("TerrainRestitution", "Bouncyness" ,
1027 0f, 1028 0f,
1028 (s,cf,p,v) => { s.m_params[0].terrainRestitution = cf.GetFloat(p, v); }, 1029 (s,cf,p,v) => { s.m_params[0].terrainRestitution = cf.GetFloat(p, v); },
1029 (s) => { return s.m_params[0].terrainRestitution; }, 1030 (s) => { return s.m_params[0].terrainRestitution; },
1030 (s,p,l,v) => { s.m_params[0].terrainRestitution = v; s.TaintedUpdateParameter(p,l,v); } ), 1031 (s,p,l,v) => { s.m_params[0].terrainRestitution = v; /* TODO: set on real terrain */ } ),
1031 new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.", 1032 new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.",
1032 0.5f, 1033 0.2f,
1033 (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); }, 1034 (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); },
1034 (s) => { return s.m_params[0].avatarFriction; }, 1035 (s) => { return s.m_params[0].avatarFriction; },
1035 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarFriction, p, l, v); } ), 1036 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarFriction, p, l, v); } ),
1037 new ParameterDefn("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.",
1038 10f,
1039 (s,cf,p,v) => { s.m_params[0].avatarStandingFriction = cf.GetFloat(p, v); },
1040 (s) => { return s.m_params[0].avatarStandingFriction; },
1041 (s,p,l,v) => { s.m_params[0].avatarStandingFriction = v; } ),
1036 new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.", 1042 new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.",
1037 60f, 1043 60f,
1038 (s,cf,p,v) => { s.m_params[0].avatarDensity = cf.GetFloat(p, v); }, 1044 (s,cf,p,v) => { s.m_params[0].avatarDensity = cf.GetFloat(p, v); },
1039 (s) => { return s.m_params[0].avatarDensity; }, 1045 (s) => { return s.m_params[0].avatarDensity; },
1040 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarDensity, p, l, v); } ), 1046 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarDensity, p, l, v); } ),
1041 new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.", 1047 new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.",
1042 0f, 1048 0f,
1043 (s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); }, 1049 (s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); },
1044 (s) => { return s.m_params[0].avatarRestitution; }, 1050 (s) => { return s.m_params[0].avatarRestitution; },
1045 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarRestitution, p, l, v); } ), 1051 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarRestitution, p, l, v); } ),
1046 new ParameterDefn("AvatarCapsuleRadius", "Radius of space around an avatar", 1052 new ParameterDefn("AvatarCapsuleRadius", "Radius of space around an avatar",
1047 0.37f, 1053 0.37f,
1048 (s,cf,p,v) => { s.m_params[0].avatarCapsuleRadius = cf.GetFloat(p, v); }, 1054 (s,cf,p,v) => { s.m_params[0].avatarCapsuleRadius = cf.GetFloat(p, v); },
1049 (s) => { return s.m_params[0].avatarCapsuleRadius; }, 1055 (s) => { return s.m_params[0].avatarCapsuleRadius; },
1050 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ), 1056 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ),
1051 new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar", 1057 new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar",
1052 1.5f, 1058 1.5f,
1053 (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); }, 1059 (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); },
1054 (s) => { return s.m_params[0].avatarCapsuleHeight; }, 1060 (s) => { return s.m_params[0].avatarCapsuleHeight; },
1055 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ), 1061 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ),
1056 new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions", 1062 new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions",
1057 0.1f, 1063 0.1f,
1058 (s,cf,p,v) => { s.m_params[0].avatarContactProcessingThreshold = cf.GetFloat(p, v); }, 1064 (s,cf,p,v) => { s.m_params[0].avatarContactProcessingThreshold = cf.GetFloat(p, v); },
1059 (s) => { return s.m_params[0].avatarContactProcessingThreshold; }, 1065 (s) => { return s.m_params[0].avatarContactProcessingThreshold; },
1060 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ), 1066 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ),
1061 1067
1062 1068
1063 new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)", 1069 new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
1064 0f, // zero to disable 1070 0f,
1065 (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); }, 1071 (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); },
1066 (s) => { return s.m_params[0].maxPersistantManifoldPoolSize; }, 1072 (s) => { return s.m_params[0].maxPersistantManifoldPoolSize; },
1067 (s,p,l,v) => { s.m_params[0].maxPersistantManifoldPoolSize = v; } ), 1073 (s,p,l,v) => { s.m_params[0].maxPersistantManifoldPoolSize = v; } ),
1068 new ParameterDefn("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)", 1074 new ParameterDefn("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)",
1069 0f, // zero to disable 1075 0f,
1070 (s,cf,p,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = cf.GetFloat(p, v); }, 1076 (s,cf,p,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = cf.GetFloat(p, v); },
1071 (s) => { return s.m_params[0].maxCollisionAlgorithmPoolSize; }, 1077 (s) => { return s.m_params[0].maxCollisionAlgorithmPoolSize; },
1072 (s,p,l,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = v; } ), 1078 (s,p,l,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = v; } ),
@@ -1081,12 +1087,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1081 (s) => { return s.m_params[0].shouldForceUpdateAllAabbs; }, 1087 (s) => { return s.m_params[0].shouldForceUpdateAllAabbs; },
1082 (s,p,l,v) => { s.m_params[0].shouldForceUpdateAllAabbs = v; } ), 1088 (s,p,l,v) => { s.m_params[0].shouldForceUpdateAllAabbs = v; } ),
1083 new ParameterDefn("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction", 1089 new ParameterDefn("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction",
1084 ConfigurationParameters.numericFalse, 1090 ConfigurationParameters.numericTrue,
1085 (s,cf,p,v) => { s.m_params[0].shouldRandomizeSolverOrder = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, 1091 (s,cf,p,v) => { s.m_params[0].shouldRandomizeSolverOrder = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1086 (s) => { return s.m_params[0].shouldRandomizeSolverOrder; }, 1092 (s) => { return s.m_params[0].shouldRandomizeSolverOrder; },
1087 (s,p,l,v) => { s.m_params[0].shouldRandomizeSolverOrder = v; } ), 1093 (s,p,l,v) => { s.m_params[0].shouldRandomizeSolverOrder = v; } ),
1088 new ParameterDefn("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands", 1094 new ParameterDefn("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands",
1089 ConfigurationParameters.numericFalse, 1095 ConfigurationParameters.numericTrue,
1090 (s,cf,p,v) => { s.m_params[0].shouldSplitSimulationIslands = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, 1096 (s,cf,p,v) => { s.m_params[0].shouldSplitSimulationIslands = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1091 (s) => { return s.m_params[0].shouldSplitSimulationIslands; }, 1097 (s) => { return s.m_params[0].shouldSplitSimulationIslands; },
1092 (s,p,l,v) => { s.m_params[0].shouldSplitSimulationIslands = v; } ), 1098 (s,p,l,v) => { s.m_params[0].shouldSplitSimulationIslands = v; } ),
@@ -1121,28 +1127,27 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1121 (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = cf.GetFloat(p, v); }, 1127 (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = cf.GetFloat(p, v); },
1122 (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; }, 1128 (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; },
1123 (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ), 1129 (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ),
1124 new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=none, 1=all. Default=0", 1130 new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1",
1125 0.0f, 1131 0.001f,
1126 (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); }, 1132 (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); },
1127 (s) => { return s.m_params[0].linkConstraintCFM; }, 1133 (s) => { return s.m_params[0].linkConstraintCFM; },
1128 (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ), 1134 (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ),
1129 new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2", 1135 new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2",
1130 0.2f, 1136 0.8f,
1131 (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); }, 1137 (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); },
1132 (s) => { return s.m_params[0].linkConstraintERP; }, 1138 (s) => { return s.m_params[0].linkConstraintERP; },
1133 (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ), 1139 (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ),
1140 new ParameterDefn("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)",
1141 40,
1142 (s,cf,p,v) => { s.m_params[0].linkConstraintSolverIterations = cf.GetFloat(p, v); },
1143 (s) => { return s.m_params[0].linkConstraintSolverIterations; },
1144 (s,p,l,v) => { s.m_params[0].linkConstraintSolverIterations = v; } ),
1134 1145
1135 new ParameterDefn("DetailedStats", "Frames between outputting detailed phys stats. (0 is off)", 1146 new ParameterDefn("LogPhysicsStatisticsFrames", "Frames between outputting detailed phys stats. (0 is off)",
1136 0f, 1147 0f,
1137 (s,cf,p,v) => { s.m_detailedStatsStep = cf.GetInt(p, (int)v); }, 1148 (s,cf,p,v) => { s.m_params[0].physicsLoggingFrames = cf.GetInt(p, (int)v); },
1138 (s) => { return (float)s.m_detailedStatsStep; }, 1149 (s) => { return (float)s.m_params[0].physicsLoggingFrames; },
1139 (s,p,l,v) => { s.m_detailedStatsStep = (int)v; } ), 1150 (s,p,l,v) => { s.m_params[0].physicsLoggingFrames = (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
1146 }; 1151 };
1147 1152
1148 // Convert a boolean to our numeric true and false values 1153 // Convert a boolean to our numeric true and false values
@@ -1200,11 +1205,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1200 1205
1201 private PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1]; 1206 private PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1];
1202 1207
1208 // This creates an array in the correct format for returning the list of
1209 // parameters. This is used by the 'list' option of the 'physics' command.
1203 private void BuildParameterTable() 1210 private void BuildParameterTable()
1204 { 1211 {
1205 if (SettableParameters.Length < ParameterDefinitions.Length) 1212 if (SettableParameters.Length < ParameterDefinitions.Length)
1206 { 1213 {
1207
1208 List<PhysParameterEntry> entries = new List<PhysParameterEntry>(); 1214 List<PhysParameterEntry> entries = new List<PhysParameterEntry>();
1209 for (int ii = 0; ii < ParameterDefinitions.Length; ii++) 1215 for (int ii = 0; ii < ParameterDefinitions.Length; ii++)
1210 { 1216 {
@@ -1249,60 +1255,54 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1249 return ret; 1255 return ret;
1250 } 1256 }
1251 1257
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
1268 // update all the localIDs specified 1258 // update all the localIDs specified
1269 // If the local ID is APPLY_TO_NONE, just change the default value 1259 // If the local ID is APPLY_TO_NONE, just change the default value
1270 // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs 1260 // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs
1271 // If the localID is a specific object, apply the parameter change to only that object 1261 // If the localID is a specific object, apply the parameter change to only that object
1272 protected void UpdateParameterSet(List<uint> lIDs, ref float defaultLoc, string parm, uint localID, float val) 1262 protected void UpdateParameterObject(ref float defaultLoc, string parm, uint localID, float val)
1273 { 1263 {
1264 List<uint> objectIDs = new List<uint>();
1274 switch (localID) 1265 switch (localID)
1275 { 1266 {
1276 case PhysParameterEntry.APPLY_TO_NONE: 1267 case PhysParameterEntry.APPLY_TO_NONE:
1277 defaultLoc = val; // setting only the default value 1268 defaultLoc = val; // setting only the default value
1269 // This will cause a call into the physical world if some operation is specified (SetOnObject).
1270 objectIDs.Add(TERRAIN_ID);
1271 TaintedUpdateParameter(parm, objectIDs, val);
1278 break; 1272 break;
1279 case PhysParameterEntry.APPLY_TO_ALL: 1273 case PhysParameterEntry.APPLY_TO_ALL:
1280 defaultLoc = val; // setting ALL also sets the default value 1274 defaultLoc = val; // setting ALL also sets the default value
1281 List<uint> objectIDs = lIDs; 1275 lock (PhysObjects) objectIDs = new List<uint>(PhysObjects.Keys);
1282 string xparm = parm.ToLower(); 1276 TaintedUpdateParameter(parm, objectIDs, val);
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 });
1290 break; 1277 break;
1291 default: 1278 default:
1292 // setting only one localID 1279 // setting only one localID
1293 TaintedUpdateParameter(parm, localID, val); 1280 objectIDs.Add(localID);
1281 TaintedUpdateParameter(parm, objectIDs, val);
1294 break; 1282 break;
1295 } 1283 }
1296 } 1284 }
1297 1285
1298 // schedule the actual updating of the paramter to when the phys engine is not busy 1286 // schedule the actual updating of the paramter to when the phys engine is not busy
1299 protected void TaintedUpdateParameter(string parm, uint localID, float val) 1287 protected void TaintedUpdateParameter(string parm, List<uint> lIDs, float val)
1300 { 1288 {
1301 uint xlocalID = localID;
1302 string xparm = parm.ToLower();
1303 float xval = val; 1289 float xval = val;
1304 TaintedObject("BSScene.TaintedUpdateParameter", delegate() { 1290 List<uint> xlIDs = lIDs;
1305 BulletSimAPI.UpdateParameter(m_worldID, xlocalID, xparm, xval); 1291 string xparm = parm;
1292 TaintedObject("BSScene.UpdateParameterSet", delegate() {
1293 ParameterDefn thisParam;
1294 if (TryGetParameter(xparm, out thisParam))
1295 {
1296 if (thisParam.onObject != null)
1297 {
1298 foreach (uint lID in xlIDs)
1299 {
1300 BSPhysObject theObject = null;
1301 PhysObjects.TryGetValue(lID, out theObject);
1302 thisParam.onObject(this, theObject, xval);
1303 }
1304 }
1305 }
1306 }); 1306 });
1307 } 1307 }
1308 1308
@@ -1330,8 +1330,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1330 public void DetailLog(string msg, params Object[] args) 1330 public void DetailLog(string msg, params Object[] args)
1331 { 1331 {
1332 PhysicsLogging.Write(msg, args); 1332 PhysicsLogging.Write(msg, args);
1333 // Add the Flush() if debugging crashes to get all the messages written out.
1334 // PhysicsLogging.Flush();
1333 } 1335 }
1334 // used to fill in the LocalID when there isn't one 1336 // Used to fill in the LocalID when there isn't one. It's the correct number of characters.
1335 public const string DetailLogZero = "0000000000"; 1337 public const string DetailLogZero = "0000000000";
1336 1338
1337} 1339}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
new file mode 100755
index 0000000..30fa50a
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -0,0 +1,833 @@
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 class BSShapeCollection : IDisposable
38{
39 private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]";
40
41 protected 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 }
52
53 // Description of a hull.
54 // Meshes and hulls have the same shape hash key but we only need hulls for efficient collision calculations.
55 private struct HullDesc
56 {
57 public IntPtr ptr;
58 public int referenceCount;
59 public DateTime lastReferenced;
60 }
61
62 // The sharable set of meshes and hulls. Indexed by their shape hash.
63 private Dictionary<System.UInt64, MeshDesc> Meshes = new Dictionary<System.UInt64, MeshDesc>();
64 private Dictionary<System.UInt64, HullDesc> Hulls = new Dictionary<System.UInt64, HullDesc>();
65
66 public BSShapeCollection(BSScene physScene)
67 {
68 PhysicsScene = physScene;
69 }
70
71 public void Dispose()
72 {
73 // TODO!!!!!!!!!
74 }
75
76 // Callbacks called just before either the body or shape is destroyed.
77 // Mostly used for changing bodies out from under Linksets.
78 // Useful for other cases where parameters need saving.
79 // Passing 'null' says no callback.
80 public delegate void ShapeDestructionCallback(BulletShape shape);
81 public delegate void BodyDestructionCallback(BulletBody body);
82
83 // Called to update/change the body and shape for an object.
84 // First checks the shape and updates that if necessary then makes
85 // sure the body is of the right type.
86 // Return 'true' if either the body or the shape changed.
87 // 'shapeCallback' and 'bodyCallback' are, if non-null, functions called just before
88 // the current shape or body is destroyed. This allows the caller to remove any
89 // higher level dependencies on the shape or body. Mostly used for LinkSets to
90 // remove the physical constraints before the body is destroyed.
91 // Called at taint-time!!
92 public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPhysObject prim,
93 ShapeData shapeData, PrimitiveBaseShape pbs,
94 ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback)
95 {
96 bool ret = false;
97
98 // This lock could probably be pushed down lower but building shouldn't take long
99 lock (m_collectionActivityLock)
100 {
101 // Do we have the correct geometry for this type of object?
102 // Updates prim.BSShape with information/pointers to shape.
103 // CreateGeom returns 'true' of BSShape as changed to a new shape.
104 bool newGeom = CreateGeom(forceRebuild, prim, shapeData, pbs, shapeCallback);
105 // If we had to select a new shape geometry for the object,
106 // rebuild the body around it.
107 // Updates prim.BSBody with information/pointers to requested body
108 bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World,
109 prim.BSShape, shapeData, bodyCallback);
110 ret = newGeom || newBody;
111 }
112 DetailLog("{0},BSShapeCollection.GetBodyAndShape,force={1},ret={2},body={3},shape={4}",
113 prim.LocalID, forceRebuild, ret, prim.BSBody, prim.BSShape);
114
115 return ret;
116 }
117
118 // Track another user of a body
119 // We presume the caller has allocated the body.
120 // Bodies only have one user so the body is just put into the world if not already there.
121 public void ReferenceBody(BulletBody body, bool inTaintTime)
122 {
123 lock (m_collectionActivityLock)
124 {
125 DetailLog("{0},BSShapeCollection.ReferenceBody,newBody", body.ID, body);
126 BSScene.TaintCallback createOperation = delegate()
127 {
128 if (!BulletSimAPI.IsInWorld2(body.ptr))
129 {
130 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr);
131 DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body);
132 }
133 };
134 if (inTaintTime)
135 createOperation();
136 else
137 PhysicsScene.TaintedObject("BSShapeCollection.ReferenceBody", createOperation);
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 BSScene.TaintCallback removeOperation = delegate()
151 {
152 DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}, inTaintTime={2}",
153 body.ID, body.ptr.ToString("X"), 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 // It may have already been removed from the world in which case the next is a NOOP.
158 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr);
159
160 // Zero any reference to the shape so it is not freed when the body is deleted.
161 BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero);
162 BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr);
163 };
164 // If already in taint-time, do the operations now. Otherwise queue for later.
165 if (inTaintTime)
166 removeOperation();
167 else
168 PhysicsScene.TaintedObject("BSShapeCollection.DereferenceBody", removeOperation);
169 }
170 }
171
172 // Track the datastructures and use count for a shape.
173 // When creating a hull, this is called first to reference the mesh
174 // and then again to reference the hull.
175 // Meshes and hulls for the same shape have the same hash key.
176 // NOTE that native shapes are not added to the mesh list or removed.
177 // Returns 'true' if this is the initial reference to the shape. Otherwise reused.
178 private bool ReferenceShape(BulletShape shape)
179 {
180 bool ret = false;
181 switch (shape.type)
182 {
183 case ShapeData.PhysicsShapeType.SHAPE_MESH:
184 MeshDesc meshDesc;
185 if (Meshes.TryGetValue(shape.shapeKey, out meshDesc))
186 {
187 // There is an existing instance of this mesh.
188 meshDesc.referenceCount++;
189 DetailLog("{0},BSShapeCollection.ReferenceShape,existingMesh,key={1},cnt={2}",
190 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
191 }
192 else
193 {
194 // This is a new reference to a mesh
195 meshDesc.ptr = shape.ptr;
196 // We keep a reference to the underlying IMesh data so a hull can be built
197 meshDesc.referenceCount = 1;
198 DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}",
199 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
200 ret = true;
201 }
202 meshDesc.lastReferenced = System.DateTime.Now;
203 Meshes[shape.shapeKey] = meshDesc;
204 break;
205 case ShapeData.PhysicsShapeType.SHAPE_HULL:
206 HullDesc hullDesc;
207 if (Hulls.TryGetValue(shape.shapeKey, out hullDesc))
208 {
209 // There is an existing instance of this hull.
210 hullDesc.referenceCount++;
211 DetailLog("{0},BSShapeCollection.ReferenceShape,existingHull,key={1},cnt={2}",
212 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
213 }
214 else
215 {
216 // This is a new reference to a hull
217 hullDesc.ptr = shape.ptr;
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 BSScene.TaintCallback dereferenceOperation = 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_UNKNOWN:
265 break;
266 default:
267 break;
268 }
269 }
270 }
271 };
272 if (inTaintTime)
273 {
274 lock (m_collectionActivityLock)
275 {
276 dereferenceOperation();
277 }
278 }
279 else
280 {
281 PhysicsScene.TaintedObject("BSShapeCollection.DereferenceShape", dereferenceOperation);
282 }
283 }
284
285 // Count down the reference count for a mesh shape
286 // Called at taint-time.
287 private void DereferenceMesh(BulletShape shape, ShapeDestructionCallback shapeCallback)
288 {
289 MeshDesc meshDesc;
290 if (Meshes.TryGetValue(shape.shapeKey, out meshDesc))
291 {
292 meshDesc.referenceCount--;
293 // TODO: release the Bullet storage
294 if (shapeCallback != null) shapeCallback(shape);
295 meshDesc.lastReferenced = System.DateTime.Now;
296 Meshes[shape.shapeKey] = meshDesc;
297 DetailLog("{0},BSShapeCollection.DereferenceMesh,key={1},refCnt={2}",
298 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
299
300 }
301 }
302
303 // Count down the reference count for a hull shape
304 // Called at taint-time.
305 private void DereferenceHull(BulletShape shape, ShapeDestructionCallback shapeCallback)
306 {
307 HullDesc hullDesc;
308 if (Hulls.TryGetValue(shape.shapeKey, out hullDesc))
309 {
310 hullDesc.referenceCount--;
311 // TODO: release the Bullet storage (aging old entries?)
312 if (shapeCallback != null) shapeCallback(shape);
313 hullDesc.lastReferenced = System.DateTime.Now;
314 Hulls[shape.shapeKey] = hullDesc;
315 DetailLog("{0},BSShapeCollection.DereferenceHull,key={1},refCnt={2}",
316 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
317 }
318 }
319
320 // Create the geometry information in Bullet for later use.
321 // The objects needs a hull if it's physical otherwise a mesh is enough.
322 // if 'forceRebuild' is true, the geometry is unconditionally rebuilt. For meshes and hulls,
323 // shared geometries will be used. If the parameters of the existing shape are the same
324 // as this request, the shape is not rebuilt.
325 // Info in prim.BSShape is updated to the new shape.
326 // Returns 'true' if the geometry was rebuilt.
327 // Called at taint-time!
328 private bool CreateGeom(bool forceRebuild, BSPhysObject prim, ShapeData shapeData,
329 PrimitiveBaseShape pbs, ShapeDestructionCallback shapeCallback)
330 {
331 bool ret = false;
332 bool haveShape = false;
333 bool nativeShapePossible = true;
334
335 if (shapeData.Type == ShapeData.PhysicsShapeType.SHAPE_AVATAR)
336 {
337 // an avatar capsule is close to a native shape (it is not shared)
338 ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_AVATAR,
339 ShapeData.FixedShapeKey.KEY_CAPSULE, shapeCallback);
340 DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.BSShape);
341 ret = true;
342 haveShape = true;
343 }
344 // If the prim attributes are simple, this could be a simple Bullet native shape
345 if (!haveShape
346 && pbs != null
347 && nativeShapePossible
348 && ((pbs.SculptEntry && !PhysicsScene.ShouldMeshSculptedPrim)
349 || (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
350 && pbs.ProfileHollow == 0
351 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
352 && pbs.PathBegin == 0 && pbs.PathEnd == 0
353 && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
354 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
355 && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) )
356 {
357 if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
358 && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z)
359 {
360 haveShape = true;
361 if (forceRebuild
362 || prim.Scale != shapeData.Size
363 || prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_SPHERE
364 )
365 {
366 ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_SPHERE,
367 ShapeData.FixedShapeKey.KEY_SPHERE, shapeCallback);
368 DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}",
369 prim.LocalID, forceRebuild, prim.BSShape);
370 }
371 }
372 if (pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
373 {
374 haveShape = true;
375 if (forceRebuild
376 || prim.Scale != shapeData.Size
377 || prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_BOX
378 )
379 {
380 ret = GetReferenceToNativeShape( prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_BOX,
381 ShapeData.FixedShapeKey.KEY_BOX, shapeCallback);
382 DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}",
383 prim.LocalID, forceRebuild, prim.BSShape);
384 }
385 }
386 }
387 // If a simple shape is not happening, create a mesh and possibly a hull.
388 // Note that if it's a native shape, the check for physical/non-physical is not
389 // made. Native shapes are best used in either case.
390 if (!haveShape && pbs != null)
391 {
392 if (prim.IsPhysical && PhysicsScene.ShouldUseHullsForPhysicalObjects)
393 {
394 // Update prim.BSShape to reference a hull of this shape.
395 ret = GetReferenceToHull(prim, shapeData, pbs, shapeCallback);
396 DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}",
397 shapeData.ID, prim.BSShape, prim.BSShape.shapeKey.ToString("X"));
398 }
399 else
400 {
401 ret = GetReferenceToMesh(prim, shapeData, pbs, shapeCallback);
402 DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}",
403 shapeData.ID, prim.BSShape, prim.BSShape.shapeKey.ToString("X"));
404 }
405 }
406 return ret;
407 }
408
409 // Creates a native shape and assignes it to prim.BSShape.
410 // "Native" shapes are never shared. they are created here and destroyed in DereferenceShape().
411 private bool GetReferenceToNativeShape(BSPhysObject prim, ShapeData shapeData,
412 ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey,
413 ShapeDestructionCallback shapeCallback)
414 {
415 // release any previous shape
416 DereferenceShape(prim.BSShape, true, shapeCallback);
417
418 shapeData.Type = shapeType;
419 // Bullet native objects are scaled by the Bullet engine so pass the size in
420 prim.Scale = shapeData.Size;
421 shapeData.Scale = shapeData.Size;
422
423 BulletShape newShape = BuildPhysicalNativeShape(shapeType, shapeData, shapeKey);
424
425 // Don't need to do a 'ReferenceShape()' here because native shapes are not shared.
426 DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}",
427 shapeData.ID, newShape, shapeData.Scale);
428
429 prim.BSShape = newShape;
430 return true;
431 }
432
433 private BulletShape BuildPhysicalNativeShape(ShapeData.PhysicsShapeType shapeType,
434 ShapeData shapeData, ShapeData.FixedShapeKey shapeKey)
435 {
436 BulletShape newShape;
437 // Need to make sure the passed shape information is for the native type.
438 ShapeData nativeShapeData = shapeData;
439 nativeShapeData.Type = shapeType;
440 nativeShapeData.MeshKey = (ulong)shapeKey;
441 nativeShapeData.HullKey = (ulong)shapeKey;
442
443 if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR)
444 {
445 newShape = new BulletShape(
446 BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1f, 1f, nativeShapeData.Scale)
447 , shapeType);
448 DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", nativeShapeData.ID, nativeShapeData.Scale);
449 }
450 else
451 {
452 newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, nativeShapeData), shapeType);
453 }
454 if (newShape.ptr == IntPtr.Zero)
455 {
456 PhysicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}",
457 LogHeader, nativeShapeData.ID, nativeShapeData.Type);
458 }
459 newShape.shapeKey = (System.UInt64)shapeKey;
460 newShape.isNativeShape = true;
461
462 return newShape;
463 }
464
465 // Builds a mesh shape in the physical world and updates prim.BSShape.
466 // Dereferences previous shape in BSShape and adds a reference for this new shape.
467 // Returns 'true' of a mesh was actually built. Otherwise .
468 // Called at taint-time!
469 private bool GetReferenceToMesh(BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs,
470 ShapeDestructionCallback shapeCallback)
471 {
472 BulletShape newShape = new BulletShape(IntPtr.Zero);
473
474 float lod;
475 System.UInt64 newMeshKey = ComputeShapeKey(shapeData, pbs, out lod);
476
477 // if this new shape is the same as last time, don't recreate the mesh
478 if (newMeshKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH)
479 return false;
480
481 DetailLog("{0},BSShapeCollection.CreateGeomMesh,create,oldKey={1},newKey={2}",
482 prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newMeshKey.ToString("X"));
483
484 // Since we're recreating new, get rid of the reference to the previous shape
485 DereferenceShape(prim.BSShape, true, shapeCallback);
486
487 newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, pbs, shapeData.Size, lod);
488 // Take evasive action if the mesh was not constructed.
489 newShape = VerifyMeshCreated(newShape, prim, shapeData, pbs);
490
491 ReferenceShape(newShape);
492
493 // meshes are already scaled by the meshmerizer
494 prim.Scale = new OMV.Vector3(1f, 1f, 1f);
495 prim.BSShape = newShape;
496
497 return true; // 'true' means a new shape has been added to this prim
498 }
499
500 private BulletShape CreatePhysicalMesh(string objName, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
501 {
502 IMesh meshData = null;
503 IntPtr meshPtr = IntPtr.Zero;
504 MeshDesc meshDesc;
505 if (Meshes.TryGetValue(newMeshKey, out meshDesc))
506 {
507 // If the mesh has already been built just use it.
508 meshPtr = meshDesc.ptr;
509 }
510 else
511 {
512 // Pass false for physicalness as this creates some sort of bounding box which we don't need
513 meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false);
514
515 if (meshData != null)
516 {
517 int[] indices = meshData.getIndexListAsInt();
518 List<OMV.Vector3> vertices = meshData.getVertexList();
519
520 float[] verticesAsFloats = new float[vertices.Count * 3];
521 int vi = 0;
522 foreach (OMV.Vector3 vv in vertices)
523 {
524 verticesAsFloats[vi++] = vv.X;
525 verticesAsFloats[vi++] = vv.Y;
526 verticesAsFloats[vi++] = vv.Z;
527 }
528
529 // m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}",
530 // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count);
531
532 meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr,
533 indices.GetLength(0), indices, vertices.Count, verticesAsFloats);
534 }
535 }
536 BulletShape newShape = new BulletShape(meshPtr, ShapeData.PhysicsShapeType.SHAPE_MESH);
537 newShape.shapeKey = newMeshKey;
538
539 return newShape;
540 }
541
542 // See that hull shape exists in the physical world and update prim.BSShape.
543 // We could be creating the hull because scale changed or whatever.
544 private bool GetReferenceToHull(BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs,
545 ShapeDestructionCallback shapeCallback)
546 {
547 BulletShape newShape;
548
549 float lod;
550 System.UInt64 newHullKey = ComputeShapeKey(shapeData, pbs, out lod);
551
552 // if the hull hasn't changed, don't rebuild it
553 if (newHullKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL)
554 return false;
555
556 DetailLog("{0},BSShapeCollection.CreateGeomHull,create,oldKey={1},newKey={2}",
557 prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newHullKey.ToString("X"));
558
559 // Remove usage of the previous shape.
560 DereferenceShape(prim.BSShape, true, shapeCallback);
561
562 newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, pbs, shapeData.Size, lod);
563 newShape = VerifyMeshCreated(newShape, prim, shapeData, pbs);
564
565 ReferenceShape(newShape);
566
567 // hulls are already scaled by the meshmerizer
568 prim.Scale = new OMV.Vector3(1f, 1f, 1f);
569 prim.BSShape = newShape;
570 return true; // 'true' means a new shape has been added to this prim
571 }
572
573 List<ConvexResult> m_hulls;
574 private BulletShape CreatePhysicalHull(string objName, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
575 {
576
577 IntPtr hullPtr = IntPtr.Zero;
578 HullDesc hullDesc;
579 if (Hulls.TryGetValue(newHullKey, out hullDesc))
580 {
581 // If the hull shape already is created, just use it.
582 hullPtr = hullDesc.ptr;
583 }
584 else
585 {
586 // Build a new hull in the physical world
587 // Pass false for physicalness as this creates some sort of bounding box which we don't need
588 IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false);
589 if (meshData != null)
590 {
591
592 int[] indices = meshData.getIndexListAsInt();
593 List<OMV.Vector3> vertices = meshData.getVertexList();
594
595 //format conversion from IMesh format to DecompDesc format
596 List<int> convIndices = new List<int>();
597 List<float3> convVertices = new List<float3>();
598 for (int ii = 0; ii < indices.GetLength(0); ii++)
599 {
600 convIndices.Add(indices[ii]);
601 }
602 foreach (OMV.Vector3 vv in vertices)
603 {
604 convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
605 }
606
607 // setup and do convex hull conversion
608 m_hulls = new List<ConvexResult>();
609 DecompDesc dcomp = new DecompDesc();
610 dcomp.mIndices = convIndices;
611 dcomp.mVertices = convVertices;
612 ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
613 // create the hull into the _hulls variable
614 convexBuilder.process(dcomp);
615
616 // Convert the vertices and indices for passing to unmanaged.
617 // The hull information is passed as a large floating point array.
618 // The format is:
619 // convHulls[0] = number of hulls
620 // convHulls[1] = number of vertices in first hull
621 // convHulls[2] = hull centroid X coordinate
622 // convHulls[3] = hull centroid Y coordinate
623 // convHulls[4] = hull centroid Z coordinate
624 // convHulls[5] = first hull vertex X
625 // convHulls[6] = first hull vertex Y
626 // convHulls[7] = first hull vertex Z
627 // convHulls[8] = second hull vertex X
628 // ...
629 // convHulls[n] = number of vertices in second hull
630 // convHulls[n+1] = second hull centroid X coordinate
631 // ...
632 //
633 // TODO: is is very inefficient. Someday change the convex hull generator to return
634 // data structures that do not need to be converted in order to pass to Bullet.
635 // And maybe put the values directly into pinned memory rather than marshaling.
636 int hullCount = m_hulls.Count;
637 int totalVertices = 1; // include one for the count of the hulls
638 foreach (ConvexResult cr in m_hulls)
639 {
640 totalVertices += 4; // add four for the vertex count and centroid
641 totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
642 }
643 float[] convHulls = new float[totalVertices];
644
645 convHulls[0] = (float)hullCount;
646 int jj = 1;
647 foreach (ConvexResult cr in m_hulls)
648 {
649 // copy vertices for index access
650 float3[] verts = new float3[cr.HullVertices.Count];
651 int kk = 0;
652 foreach (float3 ff in cr.HullVertices)
653 {
654 verts[kk++] = ff;
655 }
656
657 // add to the array one hull's worth of data
658 convHulls[jj++] = cr.HullIndices.Count;
659 convHulls[jj++] = 0f; // centroid x,y,z
660 convHulls[jj++] = 0f;
661 convHulls[jj++] = 0f;
662 foreach (int ind in cr.HullIndices)
663 {
664 convHulls[jj++] = verts[ind].x;
665 convHulls[jj++] = verts[ind].y;
666 convHulls[jj++] = verts[ind].z;
667 }
668 }
669 // create the hull data structure in Bullet
670 hullPtr = BulletSimAPI.CreateHullShape2(PhysicsScene.World.ptr, hullCount, convHulls);
671 }
672 }
673
674 BulletShape newShape = new BulletShape(hullPtr, ShapeData.PhysicsShapeType.SHAPE_HULL);
675 newShape.shapeKey = newHullKey;
676
677 return newShape; // 'true' means a new shape has been added to this prim
678 }
679
680 // Callback from convex hull creater with a newly created hull.
681 // Just add it to our collection of hulls for this shape.
682 private void HullReturn(ConvexResult result)
683 {
684 m_hulls.Add(result);
685 return;
686 }
687
688 // Create a hash of all the shape parameters to be used as a key
689 // for this particular shape.
690 private System.UInt64 ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs, out float retLod)
691 {
692 // level of detail based on size and type of the object
693 float lod = PhysicsScene.MeshLOD;
694 if (pbs.SculptEntry)
695 lod = PhysicsScene.SculptLOD;
696
697 // Mega prims usually get more detail because one can interact with shape approximations at this size.
698 float maxAxis = Math.Max(shapeData.Size.X, Math.Max(shapeData.Size.Y, shapeData.Size.Z));
699 if (maxAxis > PhysicsScene.MeshMegaPrimThreshold)
700 lod = PhysicsScene.MeshMegaPrimLOD;
701
702 retLod = lod;
703 return pbs.GetMeshKey(shapeData.Size, lod);
704 }
705 // For those who don't want the LOD
706 private System.UInt64 ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs)
707 {
708 float lod;
709 return ComputeShapeKey(shapeData, pbs, out lod);
710 }
711
712 // The creation of a mesh or hull can fail if an underlying asset is not available.
713 // There are two cases: 1) the asset is not in the cache and it needs to be fetched;
714 // and 2) the asset cannot be converted (like decompressing JPEG2000s).
715 // The first case causes the asset to be fetched. The second case just requires
716 // us to not loop forever.
717 // Called after creating a physical mesh or hull. If the physical shape was created,
718 // just return.
719 private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs)
720 {
721 // If the shape was successfully created, nothing more to do
722 if (newShape.ptr != IntPtr.Zero)
723 return newShape;
724
725 // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset
726 if (pbs.SculptEntry && !prim.LastAssetBuildFailed && pbs.SculptTexture != OMV.UUID.Zero)
727 {
728 prim.LastAssetBuildFailed = true;
729 BSPhysObject xprim = prim;
730 DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset,lID={1},lastFailed={2}",
731 LogHeader, shapeData.ID.ToString("X"), prim.LastAssetBuildFailed);
732 Util.FireAndForget(delegate
733 {
734 RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod;
735 if (assetProvider != null)
736 {
737 BSPhysObject yprim = xprim; // probably not necessary, but, just in case.
738 assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset)
739 {
740 if (!yprim.BaseShape.SculptEntry)
741 return;
742 if (yprim.BaseShape.SculptTexture.ToString() != asset.ID)
743 return;
744
745 yprim.BaseShape.SculptData = asset.Data;
746 // This will cause the prim to see that the filler shape is not the right
747 // one and try again to build the object.
748 // No race condition with the native sphere setting since the rebuild is at taint time.
749 yprim.ForceBodyShapeRebuild(false);
750
751 });
752 }
753 });
754 }
755 else
756 {
757 if (prim.LastAssetBuildFailed)
758 {
759 PhysicsScene.Logger.ErrorFormat("{0} Mesh failed to fetch asset. lID={1}, texture={2}",
760 LogHeader, shapeData.ID, pbs.SculptTexture);
761 }
762 }
763
764 // While we figure out the real problem, stick a simple native shape on the object.
765 BulletShape fillinShape =
766 BuildPhysicalNativeShape(ShapeData.PhysicsShapeType.SHAPE_BOX, shapeData, ShapeData.FixedShapeKey.KEY_BOX);
767
768 return fillinShape;
769 }
770
771 // Create a body object in Bullet.
772 // Updates prim.BSBody with the information about the new body if one is created.
773 // Returns 'true' if an object was actually created.
774 // Called at taint-time.
775 private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletSim sim, BulletShape shape,
776 ShapeData shapeData, BodyDestructionCallback bodyCallback)
777 {
778 bool ret = false;
779
780 // the mesh, hull or native shape must have already been created in Bullet
781 bool mustRebuild = (prim.BSBody.ptr == IntPtr.Zero);
782
783 // If there is an existing body, verify it's of an acceptable type.
784 // If not a solid object, body is a GhostObject. Otherwise a RigidBody.
785 if (!mustRebuild)
786 {
787 CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(prim.BSBody.ptr);
788 if (prim.IsSolid && bodyType != CollisionObjectTypes.CO_RIGID_BODY
789 || !prim.IsSolid && bodyType != CollisionObjectTypes.CO_GHOST_OBJECT)
790 {
791 // If the collisionObject is not the correct type for solidness, rebuild what's there
792 mustRebuild = true;
793 }
794 }
795
796 if (mustRebuild || forceRebuild)
797 {
798 // Free any old body
799 DereferenceBody(prim.BSBody, true, bodyCallback);
800
801 BulletBody aBody;
802 IntPtr bodyPtr = IntPtr.Zero;
803 if (prim.IsSolid)
804 {
805 bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr,
806 shapeData.ID, shapeData.Position, shapeData.Rotation);
807 DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X"));
808 }
809 else
810 {
811 bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr,
812 shapeData.ID, shapeData.Position, shapeData.Rotation);
813 DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X"));
814 }
815 aBody = new BulletBody(shapeData.ID, bodyPtr);
816
817 ReferenceBody(aBody, true);
818
819 prim.BSBody = aBody;
820
821 ret = true;
822 }
823
824 return ret;
825 }
826
827 private void DetailLog(string msg, params Object[] args)
828 {
829 if (PhysicsScene.PhysicsLogging.Enabled)
830 PhysicsScene.DetailLog(msg, args);
831 }
832}
833}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
new file mode 100755
index 0000000..880859a
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
@@ -0,0 +1,492 @@
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 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 BSScene.TaintCallback rebuildOperation = 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 // There is the option to do the changes now (we're already in 'taint time'), or
343 // to do the Bullet operations later.
344 if (inTaintTime)
345 rebuildOperation();
346 else
347 PhysicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:UpdateExisting", rebuildOperation);
348 }
349 else
350 {
351 // We don't know about this terrain so either we are creating a new terrain or
352 // our mega-prim child is giving us a new terrain to add to the phys world
353
354 // if this is a child terrain, calculate a unique terrain id
355 uint newTerrainID = id;
356 if (newTerrainID >= BSScene.CHILDTERRAIN_ID)
357 newTerrainID = ++m_terrainCount;
358
359 float[] heightMapX = heightMap;
360 Vector3 minCoordsX = minCoords;
361 Vector3 maxCoordsX = maxCoords;
362
363 DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,call,id={1}, minC={2}, maxC={3}",
364 BSScene.DetailLogZero, newTerrainID, minCoords, minCoords);
365
366 // Code that must happen at taint-time
367 BSScene.TaintCallback createOperation = delegate()
368 {
369 DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,taint,baseX={1},baseY={2}", BSScene.DetailLogZero, minCoords.X, minCoords.Y);
370 // Create a new mapInfo that will be filled with the new info
371 mapInfo = new BulletHeightMapInfo(id, heightMapX,
372 BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, newTerrainID,
373 minCoordsX, maxCoordsX, heightMapX, TERRAIN_COLLISION_MARGIN));
374 // Put the unfilled heightmap info into the collection of same
375 m_heightMaps.Add(terrainRegionBase, mapInfo);
376 // Build the terrain
377 UpdateOrCreateTerrain(newTerrainID, heightMap, minCoords, maxCoords, true);
378
379 m_terrainModified = true;
380 };
381
382 // If already in taint-time, just call Bullet. Otherwise queue the operations for the safe time.
383 if (inTaintTime)
384 createOperation();
385 else
386 PhysicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:NewTerrain", createOperation);
387 }
388 }
389
390 // Someday we will have complex terrain with caves and tunnels
391 public float GetTerrainHeightAtXYZ(Vector3 loc)
392 {
393 // For the moment, it's flat and convex
394 return GetTerrainHeightAtXY(loc.X, loc.Y);
395 }
396
397 // Given an X and Y, find the height of the terrain.
398 // Since we could be handling multiple terrains for a mega-region,
399 // the base of the region is calcuated assuming all regions are
400 // the same size and that is the default.
401 // Once the heightMapInfo is found, we have all the information to
402 // compute the offset into the array.
403 private float lastHeightTX = 999999f;
404 private float lastHeightTY = 999999f;
405 private float lastHeight = HEIGHT_INITIAL_LASTHEIGHT;
406 private float GetTerrainHeightAtXY(float tX, float tY)
407 {
408 // You'd be surprized at the number of times this routine is called
409 // with the same parameters as last time.
410 if (!m_terrainModified && lastHeightTX == tX && lastHeightTY == tY)
411 return lastHeight;
412
413 lastHeightTX = tX;
414 lastHeightTY = tY;
415 float ret = HEIGHT_GETHEIGHT_RET;
416
417 int offsetX = ((int)(tX / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X;
418 int offsetY = ((int)(tY / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y;
419 Vector2 terrainBaseXY = new Vector2(offsetX, offsetY);
420
421 BulletHeightMapInfo mapInfo;
422 if (m_heightMaps.TryGetValue(terrainBaseXY, out mapInfo))
423 {
424 float regionX = tX - offsetX;
425 float regionY = tY - offsetY;
426 int mapIndex = (int)regionY * (int)mapInfo.sizeY + (int)regionX;
427 try
428 {
429 ret = mapInfo.heightMap[mapIndex];
430 }
431 catch
432 {
433 // Sometimes they give us wonky values of X and Y. Give a warning and return something.
434 PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, x={2}, y={3}",
435 LogHeader, terrainBaseXY, regionX, regionY);
436 ret = HEIGHT_GETHEIGHT_RET;
437 }
438 // DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXY,bX={1},baseY={2},szX={3},szY={4},regX={5},regY={6},index={7},ht={8}",
439 // BSScene.DetailLogZero, offsetX, offsetY, mapInfo.sizeX, mapInfo.sizeY, regionX, regionY, mapIndex, ret);
440 }
441 else
442 {
443 PhysicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}",
444 LogHeader, PhysicsScene.RegionName, tX, tY);
445 }
446 m_terrainModified = false;
447 lastHeight = ret;
448 return ret;
449 }
450
451 // Although no one seems to check this, I do support combining.
452 public bool SupportsCombining()
453 {
454 return true;
455 }
456
457 // This routine is called two ways:
458 // One with 'offset' and 'pScene' zero and null but 'extents' giving the maximum
459 // extent of the combined regions. This is to inform the parent of the size
460 // of the combined regions.
461 // and one with 'offset' as the offset of the child region to the base region,
462 // 'pScene' pointing to the parent and 'extents' of zero. This informs the
463 // child of its relative base and new parent.
464 public void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents)
465 {
466 m_worldOffset = offset;
467 m_worldMax = extents;
468 MegaRegionParentPhysicsScene = pScene;
469 if (pScene != null)
470 {
471 // We are a child.
472 // We want m_worldMax to be the highest coordinate of our piece of terrain.
473 m_worldMax = offset + DefaultRegionSize;
474 }
475 DetailLog("{0},BSTerrainManager.Combine,offset={1},extents={2},wOffset={3},wMax={4}",
476 BSScene.DetailLogZero, offset, extents, m_worldOffset, m_worldMax);
477 }
478
479 // Unhook all the combining that I know about.
480 public void UnCombine(PhysicsScene pScene)
481 {
482 // Just like ODE, for the moment a NOP
483 DetailLog("{0},BSTerrainManager.UnCombine", BSScene.DetailLogZero);
484 }
485
486
487 private void DetailLog(string msg, params Object[] args)
488 {
489 PhysicsScene.PhysicsLogging.Write(msg, args);
490 }
491}
492}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
index 504bd3c..5ffd591 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
@@ -33,38 +33,153 @@ 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
36public struct BulletSim 39public struct BulletSim
37{ 40{
38 public BulletSim(uint id, BSScene bss, IntPtr xx) { ID = id; scene = bss; Ptr = xx; } 41 public BulletSim(uint worldId, BSScene bss, IntPtr xx)
39 public uint ID; 42 {
43 ptr = xx;
44 worldID = worldId;
45 physicsScene = bss;
46 }
47 public IntPtr ptr;
48 public uint worldID;
40 // The scene is only in here so very low level routines have a handle to print debug/error messages 49 // The scene is only in here so very low level routines have a handle to print debug/error messages
41 public BSScene scene; 50 public BSScene physicsScene;
42 public IntPtr Ptr;
43} 51}
44 52
53// An allocated Bullet btRigidBody
45public struct BulletBody 54public struct BulletBody
46{ 55{
47 public BulletBody(uint id, IntPtr xx) { ID = id; Ptr = xx; } 56 public BulletBody(uint id, IntPtr xx)
48 public IntPtr Ptr; 57 {
58 ID = id;
59 ptr = xx;
60 collisionFilter = 0;
61 collisionMask = 0;
62 }
63 public IntPtr ptr;
49 public uint ID; 64 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 }
50} 120}
51 121
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
52public struct BulletConstraint 136public struct BulletConstraint
53{ 137{
54 public BulletConstraint(IntPtr xx) { Ptr = xx; } 138 public BulletConstraint(IntPtr 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;
55 public IntPtr Ptr; 162 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;
56} 171}
57 172
58// =============================================================================== 173// ===============================================================================
59[StructLayout(LayoutKind.Sequential)] 174[StructLayout(LayoutKind.Sequential)]
60public struct ConvexHull 175public struct ConvexHull
61{ 176{
62 Vector3 Offset; 177 Vector3 Offset;
63 int VertexCount; 178 int VertexCount;
64 Vector3[] Vertices; 179 Vector3[] Vertices;
65} 180}
66[StructLayout(LayoutKind.Sequential)] 181[StructLayout(LayoutKind.Sequential)]
67public struct ShapeData 182public struct ShapeData
68{ 183{
69 public enum PhysicsShapeType 184 public enum PhysicsShapeType
70 { 185 {
@@ -75,7 +190,10 @@ public struct ShapeData
75 SHAPE_CYLINDER = 4, 190 SHAPE_CYLINDER = 4,
76 SHAPE_SPHERE = 5, 191 SHAPE_SPHERE = 5,
77 SHAPE_MESH = 6, 192 SHAPE_MESH = 6,
78 SHAPE_HULL = 7 193 SHAPE_HULL = 7,
194 // following defined by BulletSim
195 SHAPE_GROUNDPLANE = 20,
196 SHAPE_TERRAIN = 21,
79 }; 197 };
80 public uint ID; 198 public uint ID;
81 public PhysicsShapeType Type; 199 public PhysicsShapeType Type;
@@ -91,13 +209,25 @@ public struct ShapeData
91 public float Restitution; 209 public float Restitution;
92 public float Collidable; // true of things bump into this 210 public float Collidable; // true of things bump into this
93 public float Static; // true if a static object. Otherwise gravity, etc. 211 public float Static; // true if a static object. Otherwise gravity, etc.
212 public float Solid; // true if object cannot be passed through
213 public Vector3 Size;
94 214
95 // note that bools are passed as floats since bool size changes by language and architecture 215 // note that bools are passed as floats since bool size changes by language and architecture
96 public const float numericTrue = 1f; 216 public const float numericTrue = 1f;
97 public const float numericFalse = 0f; 217 public const float numericFalse = 0f;
218
219 // The native shapes have predefined shape hash keys
220 public enum FixedShapeKey : ulong
221 {
222 KEY_BOX = 1,
223 KEY_SPHERE = 2,
224 KEY_CONE = 3,
225 KEY_CYLINDER = 4,
226 KEY_CAPSULE = 5,
227 }
98} 228}
99[StructLayout(LayoutKind.Sequential)] 229[StructLayout(LayoutKind.Sequential)]
100public struct SweepHit 230public struct SweepHit
101{ 231{
102 public uint ID; 232 public uint ID;
103 public float Fraction; 233 public float Fraction;
@@ -153,6 +283,7 @@ public struct ConfigurationParameters
153 public float terrainHitFraction; 283 public float terrainHitFraction;
154 public float terrainRestitution; 284 public float terrainRestitution;
155 public float avatarFriction; 285 public float avatarFriction;
286 public float avatarStandingFriction;
156 public float avatarDensity; 287 public float avatarDensity;
157 public float avatarRestitution; 288 public float avatarRestitution;
158 public float avatarCapsuleRadius; 289 public float avatarCapsuleRadius;
@@ -174,12 +305,38 @@ public struct ConfigurationParameters
174 public float linkConstraintTransMotorMaxForce; 305 public float linkConstraintTransMotorMaxForce;
175 public float linkConstraintERP; 306 public float linkConstraintERP;
176 public float linkConstraintCFM; 307 public float linkConstraintCFM;
308 public float linkConstraintSolverIterations;
309
310 public float physicsLoggingFrames;
177 311
178 public const float numericTrue = 1f; 312 public const float numericTrue = 1f;
179 public const float numericFalse = 0f; 313 public const float numericFalse = 0f;
180} 314}
181 315
182// Values used by Bullet and BulletSim to control collisions 316
317// The states a bullet collision object can have
318public enum ActivationState : uint
319{
320 ACTIVE_TAG = 1,
321 ISLAND_SLEEPING,
322 WANTS_DEACTIVATION,
323 DISABLE_DEACTIVATION,
324 DISABLE_SIMULATION,
325}
326
327public enum CollisionObjectTypes : int
328{
329 CO_COLLISION_OBJECT = 1 << 0,
330 CO_RIGID_BODY = 1 << 1,
331 CO_GHOST_OBJECT = 1 << 2,
332 CO_SOFT_BODY = 1 << 3,
333 CO_HF_FLUID = 1 << 4,
334 CO_USER_TYPE = 1 << 5,
335}
336
337// Values used by Bullet and BulletSim to control object properties.
338// Bullet's "CollisionFlags" has more to do with operations on the
339// object (if collisions happen, if gravity effects it, ...).
183public enum CollisionFlags : uint 340public enum CollisionFlags : uint
184{ 341{
185 CF_STATIC_OBJECT = 1 << 0, 342 CF_STATIC_OBJECT = 1 << 0,
@@ -191,11 +348,55 @@ public enum CollisionFlags : uint
191 CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6, 348 CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6,
192 // Following used by BulletSim to control collisions 349 // Following used by BulletSim to control collisions
193 BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10, 350 BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10,
194 BS_VOLUME_DETECT_OBJECT = 1 << 11, 351 BS_FLOATS_ON_WATER = 1 << 11,
195 BS_PHANTOM_OBJECT = 1 << 12, 352 BS_NONE = 0,
196 BS_PHYSICAL_OBJECT = 1 << 13, 353 BS_ALL = 0xFFFFFFFF,
354
355 // These are the collision flags switched depending on physical state.
356 // The other flags are used for other things and should not be fooled with.
357 BS_ACTIVE = CF_STATIC_OBJECT
358 | CF_KINEMATIC_OBJECT
359 | CF_NO_CONTACT_RESPONSE
197}; 360};
198 361
362// Values for collisions groups and masks
363public enum CollisionFilterGroups : uint
364{
365 // Don't use the bit definitions!! Define the use in a
366 // filter/mask definition below. This way collision interactions
367 // are more easily debugged.
368 BNoneFilter = 0,
369 BDefaultFilter = 1 << 0,
370 BStaticFilter = 1 << 1,
371 BKinematicFilter = 1 << 2,
372 BDebrisFilter = 1 << 3,
373 BSensorTrigger = 1 << 4,
374 BCharacterFilter = 1 << 5,
375 BAllFilter = 0xFFFFFFFF,
376 // Filter groups defined by BulletSim
377 BGroundPlaneFilter = 1 << 10,
378 BTerrainFilter = 1 << 11,
379 BRaycastFilter = 1 << 12,
380 BSolidFilter = 1 << 13,
381
382 // The collsion filters and masked are defined in one place -- don't want them scattered
383 AvatarFilter = BCharacterFilter,
384 AvatarMask = BAllFilter,
385 ObjectFilter = BSolidFilter,
386 ObjectMask = BAllFilter,
387 StaticObjectFilter = BStaticFilter,
388 StaticObjectMask = BAllFilter,
389 VolumeDetectFilter = BSensorTrigger,
390 VolumeDetectMask = ~BSensorTrigger,
391 TerrainFilter = BTerrainFilter,
392 TerrainMask = BAllFilter & ~BStaticFilter,
393 GroundPlaneFilter = BGroundPlaneFilter,
394 GroundPlaneMask = BAllFilter
395
396};
397
398
399
199// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0 400// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0
200// ERP controls amount of correction per tick. Usable range=0.1..0.8. Default=0.2. 401// ERP controls amount of correction per tick. Usable range=0.1..0.8. Default=0.2.
201public enum ConstraintParams : int 402public enum ConstraintParams : int
@@ -221,14 +422,23 @@ public enum ConstraintParamAxis : int
221// =============================================================================== 422// ===============================================================================
222static class BulletSimAPI { 423static class BulletSimAPI {
223 424
425// Link back to the managed code for outputting log messages
426[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
427public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg);
428
224[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 429[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
225[return: MarshalAs(UnmanagedType.LPStr)] 430[return: MarshalAs(UnmanagedType.LPStr)]
226public static extern string GetVersion(); 431public static extern string GetVersion();
227 432
433/* Remove the linkage to the old api methods
228[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 434[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
229public static extern uint Initialize(Vector3 maxPosition, IntPtr parms, 435public static extern uint Initialize(Vector3 maxPosition, IntPtr parms,
230 int maxCollisions, IntPtr collisionArray, 436 int maxCollisions, IntPtr collisionArray,
231 int maxUpdates, IntPtr updateArray); 437 int maxUpdates, IntPtr updateArray,
438 DebugLogCallback logRoutine);
439
440[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
441public static extern void CreateInitialGroundPlaneAndTerrain(uint worldID);
232 442
233[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 443[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
234public static extern void SetHeightmap(uint worldID, [MarshalAs(UnmanagedType.LPArray)] float[] heightMap); 444public static extern void SetHeightmap(uint worldID, [MarshalAs(UnmanagedType.LPArray)] float[] heightMap);
@@ -242,19 +452,19 @@ public static extern bool UpdateParameter(uint worldID, uint localID,
242 452
243// =============================================================================== 453// ===============================================================================
244[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 454[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
245public static extern int PhysicsStep(uint worldID, float timeStep, int maxSubSteps, float fixedTimeStep, 455public static extern int PhysicsStep(uint worldID, float timeStep, int maxSubSteps, float fixedTimeStep,
246 out int updatedEntityCount, 456 out int updatedEntityCount,
247 out IntPtr updatedEntitiesPtr, 457 out IntPtr updatedEntitiesPtr,
248 out int collidersCount, 458 out int collidersCount,
249 out IntPtr collidersPtr); 459 out IntPtr collidersPtr);
250 460
251[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 461[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
252public static extern bool CreateHull(uint worldID, System.UInt64 meshKey, 462public static extern bool CreateHull(uint worldID, System.UInt64 meshKey,
253 int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls 463 int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls
254 ); 464 );
255 465
256[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 466[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
257public static extern bool CreateMesh(uint worldID, System.UInt64 meshKey, 467public static extern bool CreateMesh(uint worldID, System.UInt64 meshKey,
258 int indexCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices, 468 int indexCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices,
259 int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices 469 int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices
260 ); 470 );
@@ -268,23 +478,6 @@ public static extern bool DestroyMesh(uint worldID, System.UInt64 meshKey);
268[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 478[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
269public static extern bool CreateObject(uint worldID, ShapeData shapeData); 479public static extern bool CreateObject(uint worldID, ShapeData shapeData);
270 480
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
288[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 481[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
289public static extern Vector3 GetObjectPosition(uint WorldID, uint id); 482public static extern Vector3 GetObjectPosition(uint WorldID, uint id);
290 483
@@ -300,6 +493,7 @@ public static extern bool SetObjectVelocity(uint worldID, uint id, Vector3 veloc
300[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 493[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
301public static extern bool SetObjectAngularVelocity(uint worldID, uint id, Vector3 angularVelocity); 494public static extern bool SetObjectAngularVelocity(uint worldID, uint id, Vector3 angularVelocity);
302 495
496// Set the current force acting on the object
303[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 497[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
304public static extern bool SetObjectForce(uint worldID, uint id, Vector3 force); 498public static extern bool SetObjectForce(uint worldID, uint id, Vector3 force);
305 499
@@ -340,10 +534,8 @@ public static extern Vector3 RecoverFromPenetration(uint worldID, uint id);
340// =============================================================================== 534// ===============================================================================
341[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 535[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
342public static extern void DumpBulletStatistics(); 536public static extern void DumpBulletStatistics();
343 537*/
344// Log a debug message 538// Log a debug message
345[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
346public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg);
347[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 539[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
348public static extern void SetDebugLogCallback(DebugLogCallback callback); 540public static extern void SetDebugLogCallback(DebugLogCallback callback);
349 541
@@ -358,6 +550,7 @@ public static extern void SetDebugLogCallback(DebugLogCallback callback);
358// The names have a "2" tacked on. This will be removed as the C# code gets rebuilt 550// The names have a "2" tacked on. This will be removed as the C# code gets rebuilt
359// and the old code is removed. 551// and the old code is removed.
360 552
553// Functions use while converting from API1 to API2. Can be removed when totally converted.
361[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 554[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
362public static extern IntPtr GetSimHandle2(uint worldID); 555public static extern IntPtr GetSimHandle2(uint worldID);
363 556
@@ -368,23 +561,25 @@ public static extern IntPtr GetBodyHandleWorldID2(uint worldID, uint id);
368public static extern IntPtr GetBodyHandle2(IntPtr world, uint id); 561public static extern IntPtr GetBodyHandle2(IntPtr world, uint id);
369 562
370// =============================================================================== 563// ===============================================================================
564// Initialization and simulation
371[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 565[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
372public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms, 566public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms,
373 int maxCollisions, IntPtr collisionArray, 567 int maxCollisions, IntPtr collisionArray,
374 int maxUpdates, IntPtr updateArray); 568 int maxUpdates, IntPtr updateArray,
569 DebugLogCallback logRoutine);
375 570
376[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 571[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
377public static extern bool UpdateParameter2(IntPtr world, uint localID, String parm, float value); 572public static extern bool UpdateParameter2(IntPtr world, uint localID, String parm, float value);
378 573
379[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 574[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
380public static extern void SetHeightmap2(IntPtr world, float[] heightmap); 575public static extern void SetHeightMap2(IntPtr world, float[] heightmap);
381 576
382[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 577[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
383public static extern void Shutdown2(IntPtr sim); 578public static extern void Shutdown2(IntPtr sim);
384 579
385[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 580[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
386public static extern int PhysicsStep2(IntPtr world, float timeStep, int maxSubSteps, float fixedTimeStep, 581public static extern int PhysicsStep2(IntPtr world, float timeStep, int maxSubSteps, float fixedTimeStep,
387 out int updatedEntityCount, 582 out int updatedEntityCount,
388 out IntPtr updatedEntitiesPtr, 583 out IntPtr updatedEntitiesPtr,
389 out int collidersCount, 584 out int collidersCount,
390 out IntPtr collidersPtr); 585 out IntPtr collidersPtr);
@@ -392,24 +587,90 @@ public static extern int PhysicsStep2(IntPtr world, float timeStep, int maxSubSt
392[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 587[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
393public static extern bool PushUpdate2(IntPtr obj); 588public static extern bool PushUpdate2(IntPtr obj);
394 589
395/* 590// =====================================================================================
591// Mesh, hull, shape and body creation helper routines
396[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 592[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
397public static extern IntPtr CreateMesh2(IntPtr world, int indicesCount, int* indices, int verticesCount, float* vertices ); 593public static extern IntPtr CreateMeshShape2(IntPtr world,
594 int indicesCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices,
595 int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices );
398 596
399[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 597[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
400public static extern bool BuildHull2(IntPtr world, IntPtr mesh); 598public static extern IntPtr CreateHullShape2(IntPtr world,
599 int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls);
401 600
402[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 601[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
403public static extern bool ReleaseHull2(IntPtr world, IntPtr mesh); 602public static extern IntPtr BuildHullShapeFromMesh2(IntPtr world, IntPtr meshShape);
404 603
405[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 604[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
406public static extern bool DestroyMesh2(IntPtr world, IntPtr mesh); 605public static extern IntPtr BuildNativeShape2(IntPtr world, ShapeData shapeData);
407 606
408[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 607[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
409public static extern IntPtr CreateObject2(IntPtr world, ShapeData shapeData); 608public static extern bool IsNativeShape2(IntPtr shape);
410*/ 609
610[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
611public static extern IntPtr BuildCapsuleShape2(IntPtr world, float radius, float height, Vector3 scale);
612
613[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
614public static extern IntPtr CreateCompoundShape2(IntPtr sim);
615
616[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
617public static extern void AddChildToCompoundShape2(IntPtr cShape, IntPtr addShape, Vector3 pos, Quaternion rot);
618
619[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
620public static extern void RemoveChildFromCompoundShape2(IntPtr cShape, IntPtr removeShape);
621
622[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
623public static extern IntPtr DuplicateCollisionShape2(IntPtr sim, IntPtr srcShape, uint id);
624
625[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
626public static extern IntPtr CreateBodyFromShapeAndInfo2(IntPtr sim, IntPtr shape, uint id, IntPtr constructionInfo);
627
628[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
629public static extern bool DeleteCollisionShape2(IntPtr world, IntPtr shape);
411 630
412[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 631[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
632public static extern int GetBodyType2(IntPtr obj);
633
634[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
635public static extern IntPtr CreateBodyFromShape2(IntPtr sim, IntPtr shape, uint id, Vector3 pos, Quaternion rot);
636
637[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
638public static extern IntPtr CreateBodyWithDefaultMotionState2(IntPtr shape, uint id, Vector3 pos, Quaternion rot);
639
640[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
641public static extern IntPtr CreateGhostFromShape2(IntPtr sim, IntPtr shape, uint id, Vector3 pos, Quaternion rot);
642
643[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
644public static extern IntPtr AllocateBodyInfo2(IntPtr obj);
645
646[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
647public static extern void ReleaseBodyInfo2(IntPtr obj);
648
649[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
650public static extern void DestroyObject2(IntPtr sim, IntPtr obj);
651
652// =====================================================================================
653// Terrain creation and helper routines
654[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
655public static extern IntPtr CreateHeightMapInfo2(IntPtr sim, uint id, Vector3 minCoords, Vector3 maxCoords,
656 [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin);
657
658[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
659public static extern IntPtr FillHeightMapInfo2(IntPtr sim, IntPtr mapInfo, uint id, Vector3 minCoords, Vector3 maxCoords,
660 [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin);
661
662[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
663public static extern bool ReleaseHeightMapInfo2(IntPtr heightMapInfo);
664
665[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
666public static extern IntPtr CreateGroundPlaneShape2(uint id, float height, float collisionMargin);
667
668[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
669public static extern IntPtr CreateTerrainShape2(IntPtr mapInfo);
670
671// =====================================================================================
672// Constraint creation and helper routines
673[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
413public static extern IntPtr Create6DofConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2, 674public static extern IntPtr Create6DofConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
414 Vector3 frame1loc, Quaternion frame1rot, 675 Vector3 frame1loc, Quaternion frame1rot,
415 Vector3 frame2loc, Quaternion frame2rot, 676 Vector3 frame2loc, Quaternion frame2rot,
@@ -433,7 +694,7 @@ public static extern void SetConstraintEnable2(IntPtr constrain, float numericTr
433public static extern void SetConstraintNumSolverIterations2(IntPtr constrain, float iterations); 694public static extern void SetConstraintNumSolverIterations2(IntPtr constrain, float iterations);
434 695
435[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 696[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
436public static extern bool SetFrames2(IntPtr constrain, 697public static extern bool SetFrames2(IntPtr constrain,
437 Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot); 698 Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot);
438 699
439[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 700[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
@@ -460,11 +721,108 @@ public static extern bool SetConstraintParam2(IntPtr constrain, ConstraintParams
460[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 721[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
461public static extern bool DestroyConstraint2(IntPtr world, IntPtr constrain); 722public static extern bool DestroyConstraint2(IntPtr world, IntPtr constrain);
462 723
724// =====================================================================================
725// btCollisionWorld entries
726[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
727public static extern void UpdateSingleAabb2(IntPtr world, IntPtr obj);
728
729[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
730public static extern void UpdateAabbs2(IntPtr world);
731
732[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
733public static extern bool GetForceUpdateAllAabbs2(IntPtr world);
734
735[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
736public static extern void SetForceUpdateAllAabbs2(IntPtr world, bool force);
737
738// =====================================================================================
739// btDynamicsWorld entries
740[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
741public static extern bool AddObjectToWorld2(IntPtr world, IntPtr obj);
742
743[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
744public static extern bool RemoveObjectFromWorld2(IntPtr world, IntPtr obj);
745
746[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
747public static extern bool AddConstraintToWorld2(IntPtr world, IntPtr constrain, bool disableCollisionsBetweenLinkedObjects);
748
749[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
750public static extern bool RemoveConstraintFromWorld2(IntPtr world, IntPtr constrain);
751// =====================================================================================
752// btCollisionObject entries
753[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
754public static extern Vector3 GetAnisotripicFriction2(IntPtr constrain);
755
756[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
757public static extern Vector3 SetAnisotripicFriction2(IntPtr constrain, Vector3 frict);
758
759[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
760public static extern bool HasAnisotripicFriction2(IntPtr constrain);
761
762[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
763public static extern void SetContactProcessingThreshold2(IntPtr obj, float val);
764
765[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
766public static extern float GetContactProcessingThreshold2(IntPtr obj);
767
768[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
769public static extern bool IsStaticObject2(IntPtr obj);
770
771[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
772public static extern bool IsKinematicObject2(IntPtr obj);
773
463[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 774[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
464public static extern Vector3 AddObjectToWorld2(IntPtr world, IntPtr obj); 775public static extern bool IsStaticOrKinematicObject2(IntPtr obj);
465 776
466[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 777[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
467public static extern Vector3 RemoveObjectFromWorld2(IntPtr world, IntPtr obj); 778public static extern bool HasContactResponse2(IntPtr obj);
779
780[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
781public static extern void SetCollisionShape2(IntPtr sim, IntPtr obj, IntPtr shape);
782
783[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
784public static extern IntPtr GetCollisionShape2(IntPtr obj);
785
786[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
787public static extern int GetActivationState2(IntPtr obj);
788
789[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
790public static extern void SetActivationState2(IntPtr obj, int state);
791
792[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
793public static extern void SetDeactivationTime2(IntPtr obj, float dtime);
794
795[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
796public static extern float GetDeactivationTime2(IntPtr obj);
797
798[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
799public static extern void ForceActivationState2(IntPtr obj, ActivationState state);
800
801[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
802public static extern void Activate2(IntPtr obj, bool forceActivation);
803
804[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
805public static extern bool IsActive2(IntPtr obj);
806
807[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
808public static extern void SetRestitution2(IntPtr obj, float val);
809
810[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
811public static extern float GetRestitution2(IntPtr obj);
812
813[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
814public static extern void SetFriction2(IntPtr obj, float val);
815
816[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
817public static extern float GetFriction2(IntPtr obj);
818
819 /* Haven't defined the type 'Transform'
820[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
821public static extern Transform GetWorldTransform2(IntPtr obj);
822
823[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
824public static extern void setWorldTransform2(IntPtr obj, Transform trans);
825 */
468 826
469[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 827[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
470public static extern Vector3 GetPosition2(IntPtr obj); 828public static extern Vector3 GetPosition2(IntPtr obj);
@@ -473,85 +831,290 @@ public static extern Vector3 GetPosition2(IntPtr obj);
473public static extern Quaternion GetOrientation2(IntPtr obj); 831public static extern Quaternion GetOrientation2(IntPtr obj);
474 832
475[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 833[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
476public static extern bool SetTranslation2(IntPtr obj, Vector3 position, Quaternion rotation); 834public static extern void SetTranslation2(IntPtr obj, Vector3 position, Quaternion rotation);
477 835
478[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 836[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
479public static extern bool SetVelocity2(IntPtr obj, Vector3 velocity); 837public static extern IntPtr GetBroadphaseHandle2(IntPtr obj);
480 838
481[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 839[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
482public static extern bool SetAngularVelocity2(IntPtr obj, Vector3 angularVelocity); 840public static extern void SetBroadphaseHandle2(IntPtr obj, IntPtr handle);
483 841
842 /*
484[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 843[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
485public static extern bool SetObjectForce2(IntPtr obj, Vector3 force); 844public static extern Transform GetInterpolationWorldTransform2(IntPtr obj);
486 845
487[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 846[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
488public static extern bool AddObjectForce2(IntPtr obj, Vector3 force); 847public static extern void SetInterpolationWorldTransform2(IntPtr obj, Transform trans);
848 */
489 849
490[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 850[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
491public static extern bool SetCcdMotionThreshold2(IntPtr obj, float val); 851public static extern void SetInterpolationLinearVelocity2(IntPtr obj, Vector3 vel);
492 852
493[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 853[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
494public static extern bool SetCcdSweepSphereRadius2(IntPtr obj, float val); 854public static extern void SetInterpolationAngularVelocity2(IntPtr obj, Vector3 vel);
495 855
496[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 856[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
497public static extern bool SetDamping2(IntPtr obj, float lin_damping, float ang_damping); 857public static extern void SetInterpolationVelocity2(IntPtr obj, Vector3 linearVel, Vector3 angularVel);
498 858
499[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 859[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
500public static extern bool SetDeactivationTime2(IntPtr obj, float val); 860public static extern float GetHitFraction2(IntPtr obj);
501 861
502[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 862[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
503public static extern bool SetSleepingThresholds2(IntPtr obj, float lin_threshold, float ang_threshold); 863public static extern void SetHitFraction2(IntPtr obj, float val);
504 864
505[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 865[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
506public static extern bool SetContactProcessingThreshold2(IntPtr obj, float val); 866public static extern CollisionFlags GetCollisionFlags2(IntPtr obj);
507 867
508[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 868[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
509public static extern bool SetFriction2(IntPtr obj, float val); 869public static extern CollisionFlags SetCollisionFlags2(IntPtr obj, CollisionFlags flags);
510 870
511[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 871[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
512public static extern bool SetRestitution2(IntPtr obj, float val); 872public static extern CollisionFlags AddToCollisionFlags2(IntPtr obj, CollisionFlags flags);
513 873
514[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 874[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
515public static extern bool SetLinearVelocity2(IntPtr obj, Vector3 val); 875public static extern CollisionFlags RemoveFromCollisionFlags2(IntPtr obj, CollisionFlags flags);
516 876
517[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 877[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
518public static extern bool SetInterpolation2(IntPtr obj, Vector3 lin, Vector3 ang); 878public static extern float GetCcdMotionThreshold2(IntPtr obj);
519 879
520[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 880[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
521public static extern CollisionFlags GetCollisionFlags2(IntPtr obj); 881public static extern void SetCcdMotionThreshold2(IntPtr obj, float val);
882
883[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
884public static extern float GetCcdSweepSphereRadius2(IntPtr obj);
885
886[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
887public static extern void SetCcdSweepSphereRadius2(IntPtr obj, float val);
888
889[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
890public static extern IntPtr GetUserPointer2(IntPtr obj);
891
892[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
893public static extern void SetUserPointer2(IntPtr obj, IntPtr val);
894
895// =====================================================================================
896// btRigidBody entries
897[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
898public static extern void ApplyGravity2(IntPtr obj);
899
900[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
901public static extern void SetGravity2(IntPtr obj, Vector3 val);
902
903[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
904public static extern Vector3 GetGravity2(IntPtr obj);
905
906[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
907public static extern void SetDamping2(IntPtr obj, float lin_damping, float ang_damping);
908
909[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
910public static extern float GetLinearDamping2(IntPtr obj);
911
912[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
913public static extern float GetAngularDamping2(IntPtr obj);
914
915[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
916public static extern float GetLinearSleepingThreshold2(IntPtr obj);
917
918[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
919public static extern float GetAngularSleepingThreshold2(IntPtr obj);
920
921[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
922public static extern void ApplyDamping2(IntPtr obj, float timeStep);
923
924[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
925public static extern void SetMassProps2(IntPtr obj, float mass, Vector3 inertia);
926
927[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
928public static extern Vector3 GetLinearFactor2(IntPtr obj);
929
930[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
931public static extern void SetLinearFactor2(IntPtr obj, Vector3 factor);
932
933 /*
934[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
935public static extern void SetCenterOfMassTransform2(IntPtr obj, Transform trans);
936 */
937
938[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
939public static extern void SetCenterOfMassByPosRot2(IntPtr obj, Vector3 pos, Quaternion rot);
940
941// Add a force to the object as if its mass is one.
942[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
943public static extern void ApplyCentralForce2(IntPtr obj, Vector3 force);
944
945// Set the force being applied to the object as if its mass is one.
946[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
947public static extern void SetObjectForce2(IntPtr obj, Vector3 force);
948
949[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
950public static extern Vector3 GetTotalForce2(IntPtr obj);
951
952[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
953public static extern Vector3 GetTotalTorque2(IntPtr obj);
954
955[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
956public static extern Vector3 GetInvInertiaDiagLocal2(IntPtr obj);
957
958[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
959public static extern void SetInvInertiaDiagLocal2(IntPtr obj, Vector3 inert);
960
961[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
962public static extern void SetSleepingThresholds2(IntPtr obj, float lin_threshold, float ang_threshold);
963
964[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
965public static extern void ApplyTorque2(IntPtr obj, Vector3 torque);
966
967// Apply force at the given point. Will add torque to the object.
968[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
969public static extern void ApplyForce2(IntPtr obj, Vector3 force, Vector3 pos);
970
971// Apply impulse to the object. Same as "ApplycentralForce" but force scaled by object's mass.
972[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
973public static extern void ApplyCentralImpulse2(IntPtr obj, Vector3 imp);
974
975// Apply impulse to the object's torque. Force is scaled by object's mass.
976[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
977public static extern void ApplyTorqueImpulse2(IntPtr obj, Vector3 imp);
978
979// Apply impulse at the point given. For is scaled by object's mass and effects both linear and angular forces.
980[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
981public static extern void ApplyImpulse2(IntPtr obj, Vector3 imp, Vector3 pos);
982
983[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
984public static extern void ClearForces2(IntPtr obj);
985
986[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
987public static extern void ClearAllForces2(IntPtr obj);
988
989[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
990public static extern void UpdateInertiaTensor2(IntPtr obj);
991
992[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
993public static extern Vector3 GetCenterOfMassPosition2(IntPtr obj);
994
995 /*
996[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
997public static extern Transform GetCenterOfMassTransform2(IntPtr obj);
998 */
999
1000[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1001public static extern Vector3 GetLinearVelocity2(IntPtr obj);
1002
1003[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1004public static extern Vector3 GetAngularVelocity2(IntPtr obj);
1005
1006[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1007public static extern void SetLinearVelocity2(IntPtr obj, Vector3 val);
1008
1009[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1010public static extern void SetAngularVelocity2(IntPtr obj, Vector3 angularVelocity);
1011
1012[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1013public static extern Vector3 GetVelocityInLocalPoint2(IntPtr obj, Vector3 pos);
1014
1015[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1016public static extern void Translate2(IntPtr obj, Vector3 trans);
1017
1018[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1019public static extern void UpdateDeactivation2(IntPtr obj, float timeStep);
1020
1021[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1022public static extern bool WantsSleeping2(IntPtr obj);
1023
1024[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1025public static extern void SetAngularFactor2(IntPtr obj, float factor);
1026
1027[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1028public static extern void SetAngularFactorV2(IntPtr obj, Vector3 factor);
1029
1030[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1031public static extern Vector3 GetAngularFactor2(IntPtr obj);
1032
1033[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1034public static extern bool IsInWorld2(IntPtr obj);
1035
1036[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1037public static extern void AddConstraintRef2(IntPtr obj, IntPtr constrain);
1038
1039[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1040public static extern void RemoveConstraintRef2(IntPtr obj, IntPtr constrain);
1041
1042[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1043public static extern IntPtr GetConstraintRef2(IntPtr obj, int index);
1044
1045[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1046public static extern int GetNumConstraintRefs2(IntPtr obj);
1047
1048[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1049public static extern void SetCollisionFilterMask2(IntPtr body, uint filter, uint mask);
1050
1051// =====================================================================================
1052// btCollisionShape entries
1053
1054[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1055public static extern float GetAngularMotionDisc2(IntPtr shape);
1056
1057[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1058public static extern float GetContactBreakingThreshold2(IntPtr shape, float defaultFactor);
1059
1060[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1061public static extern bool IsPolyhedral2(IntPtr shape);
1062
1063[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1064public static extern bool IsConvex2d2(IntPtr shape);
1065
1066[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1067public static extern bool IsConvex2(IntPtr shape);
1068
1069[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1070public static extern bool IsNonMoving2(IntPtr shape);
1071
1072[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1073public static extern bool IsConcave2(IntPtr shape);
1074
1075[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1076public static extern bool IsCompound2(IntPtr shape);
1077
1078[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1079public static extern bool IsSoftBody2(IntPtr shape);
1080
1081[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1082public static extern bool IsInfinite2(IntPtr shape);
522 1083
523[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1084[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
524public static extern IntPtr SetCollisionFlags2(IntPtr obj, CollisionFlags flags); 1085public static extern void SetLocalScaling2(IntPtr shape, Vector3 scale);
525 1086
526[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1087[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
527public static extern IntPtr AddToCollisionFlags2(IntPtr obj, CollisionFlags flags); 1088public static extern Vector3 GetLocalScaling2(IntPtr shape);
528 1089
529[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1090[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
530public static extern IntPtr RemoveFromCollisionFlags2(IntPtr obj, CollisionFlags flags); 1091public static extern Vector3 CalculateLocalInertia2(IntPtr shape, float mass);
531 1092
532[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1093[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
533public static extern bool SetMassProps2(IntPtr obj, float mass, Vector3 inertia); 1094public static extern int GetShapeType2(IntPtr shape);
534 1095
535[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1096[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
536public static extern bool UpdateInertiaTensor2(IntPtr obj); 1097public static extern void SetMargin2(IntPtr shape, float val);
537 1098
538[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1099[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
539public static extern bool SetGravity2(IntPtr obj, Vector3 val); 1100public static extern float GetMargin2(IntPtr shape);
540 1101
1102// =====================================================================================
1103// Debugging
541[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1104[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
542public static extern IntPtr ClearForces2(IntPtr obj); 1105public static extern void DumpRigidBody2(IntPtr sim, IntPtr collisionObject);
543 1106
544[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1107[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
545public static extern IntPtr ClearAllForces2(IntPtr obj); 1108public static extern void DumpCollisionShape2(IntPtr sim, IntPtr collisionShape);
546 1109
547[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1110[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
548public static extern bool SetMargin2(IntPtr obj, float val); 1111public static extern void DumpConstraint2(IntPtr sim, IntPtr constrain);
549 1112
550[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1113[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
551public static extern bool UpdateSingleAabb2(IntPtr world, IntPtr obj); 1114public static extern void DumpAllInfo2(IntPtr sim);
552 1115
553[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1116[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
554public static extern bool DestroyObject2(IntPtr world, uint id); 1117public static extern void DumpMapInfo2(IntPtr sim, IntPtr manInfo);
555 1118
556[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1119[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
557public static extern void DumpPhysicsStatistics2(IntPtr sim); 1120public static extern void DumpPhysicsStatistics2(IntPtr sim);
diff --git a/OpenSim/Region/Physics/Manager/PhysicsActor.cs b/OpenSim/Region/Physics/Manager/PhysicsActor.cs
index 14f65b8..5af6373 100644
--- a/OpenSim/Region/Physics/Manager/PhysicsActor.cs
+++ b/OpenSim/Region/Physics/Manager/PhysicsActor.cs
@@ -340,6 +340,12 @@ 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
343 public abstract Vector3 Velocity { get; set; } 349 public abstract Vector3 Velocity { get; set; }
344 350
345 public abstract Vector3 Torque { get; set; } 351 public abstract Vector3 Torque { get; set; }
diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
index f3b0630..c736557 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 103 internal bool m_avatarplanted = false;
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) 416 if (value && !m_avatarplanted)
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 2e78de5..a59f63f 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
@@ -67,6 +67,14 @@ 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>
70 /// Is this prim subject to physics? Even if not, it's still solid for collision purposes. 78 /// Is this prim subject to physics? Even if not, it's still solid for collision purposes.
71 /// </summary> 79 /// </summary>
72 public override bool IsPhysical 80 public override bool IsPhysical
@@ -156,7 +164,7 @@ namespace OpenSim.Region.Physics.OdePlugin
156 164
157 private PrimitiveBaseShape _pbs; 165 private PrimitiveBaseShape _pbs;
158 private OdeScene _parent_scene; 166 private OdeScene _parent_scene;
159 167
160 /// <summary> 168 /// <summary>
161 /// The physics space which contains prim geometries 169 /// The physics space which contains prim geometries
162 /// </summary> 170 /// </summary>
@@ -3333,7 +3341,6 @@ Console.WriteLine(" JointCreateFixed");
3333 m_material = pMaterial; 3341 m_material = pMaterial;
3334 } 3342 }
3335 3343
3336
3337 private void CheckMeshAsset() 3344 private void CheckMeshAsset()
3338 { 3345 {
3339 if (_pbs.SculptEntry && !m_assetFailed && _pbs.SculptTexture != UUID.Zero) 3346 if (_pbs.SculptEntry && !m_assetFailed && _pbs.SculptTexture != UUID.Zero)
@@ -3343,14 +3350,14 @@ Console.WriteLine(" JointCreateFixed");
3343 { 3350 {
3344 RequestAssetDelegate assetProvider = _parent_scene.RequestAssetMethod; 3351 RequestAssetDelegate assetProvider = _parent_scene.RequestAssetMethod;
3345 if (assetProvider != null) 3352 if (assetProvider != null)
3346 assetProvider(_pbs.SculptTexture, MeshAssetReveived); 3353 assetProvider(_pbs.SculptTexture, MeshAssetReceived);
3347 }); 3354 });
3348 } 3355 }
3349 } 3356 }
3350 3357
3351 void MeshAssetReveived(AssetBase asset) 3358 private void MeshAssetReceived(AssetBase asset)
3352 { 3359 {
3353 if (asset.Data != null && asset.Data.Length > 0) 3360 if (asset != null && asset.Data != null && asset.Data.Length > 0)
3354 { 3361 {
3355 if (!_pbs.SculptEntry) 3362 if (!_pbs.SculptEntry)
3356 return; 3363 return;
@@ -3363,6 +3370,12 @@ Console.WriteLine(" JointCreateFixed");
3363 m_taintshape = true; 3370 m_taintshape = true;
3364 _parent_scene.AddPhysicsActorTaint(this); 3371 _parent_scene.AddPhysicsActorTaint(this);
3365 } 3372 }
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 }
3366 } 3379 }
3367 } 3380 }
3368} \ No newline at end of file 3381}
diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
index 7a50c4c..d53bd90 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
@@ -501,6 +501,8 @@ 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;
504 506
505 public d.Vector3 xyz = new d.Vector3(128.1640f, 128.3079f, 25.7600f); 507 public d.Vector3 xyz = new d.Vector3(128.1640f, 128.3079f, 25.7600f);
506 public d.Vector3 hpr = new d.Vector3(125.5000f, -17.0000f, 0.0000f); 508 public d.Vector3 hpr = new d.Vector3(125.5000f, -17.0000f, 0.0000f);
@@ -644,6 +646,9 @@ namespace OpenSim.Region.Physics.OdePlugin
644 avMovementDivisorWalk = physicsconfig.GetFloat("av_movement_divisor_walk", 1.3f); 646 avMovementDivisorWalk = physicsconfig.GetFloat("av_movement_divisor_walk", 1.3f);
645 avMovementDivisorRun = physicsconfig.GetFloat("av_movement_divisor_run", 0.8f); 647 avMovementDivisorRun = physicsconfig.GetFloat("av_movement_divisor_run", 0.8f);
646 avCapRadius = physicsconfig.GetFloat("av_capsule_radius", 0.37f); 648 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
647 IsAvCapsuleTilted = physicsconfig.GetBoolean("av_capsule_tilted", false); 652 IsAvCapsuleTilted = physicsconfig.GetBoolean("av_capsule_tilted", false);
648 653
649 contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", 80); 654 contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", 80);
@@ -663,6 +668,8 @@ namespace OpenSim.Region.Physics.OdePlugin
663 meshSculptLOD = physicsconfig.GetFloat("mesh_lod", 32f); 668 meshSculptLOD = physicsconfig.GetFloat("mesh_lod", 32f);
664 MeshSculptphysicalLOD = physicsconfig.GetFloat("mesh_physical_lod", 16f); 669 MeshSculptphysicalLOD = physicsconfig.GetFloat("mesh_physical_lod", 16f);
665 m_filterCollisions = physicsconfig.GetBoolean("filter_collisions", false); 670 m_filterCollisions = physicsconfig.GetBoolean("filter_collisions", false);
671
672
666 673
667 if (Environment.OSVersion.Platform == PlatformID.Unix) 674 if (Environment.OSVersion.Platform == PlatformID.Unix)
668 { 675 {
@@ -1309,6 +1316,10 @@ namespace OpenSim.Region.Physics.OdePlugin
1309 if ((p1 is OdePrim) && (((OdePrim)p1).m_isVolumeDetect)) 1316 if ((p1 is OdePrim) && (((OdePrim)p1).m_isVolumeDetect))
1310 skipThisContact = true; // No collision on volume detect prims 1317 skipThisContact = true; // No collision on volume detect prims
1311 1318
1319 if (av_av_collisions_off)
1320 if ((p1 is OdeCharacter) && (p2 is OdeCharacter))
1321 skipThisContact = true;
1322
1312 if (!skipThisContact && (p2 is OdePrim) && (((OdePrim)p2).m_isVolumeDetect)) 1323 if (!skipThisContact && (p2 is OdePrim) && (((OdePrim)p2).m_isVolumeDetect))
1313 skipThisContact = true; // No collision on volume detect prims 1324 skipThisContact = true; // No collision on volume detect prims
1314 1325
@@ -1972,7 +1983,8 @@ namespace OpenSim.Region.Physics.OdePlugin
1972 1983
1973 newAv.Flying = isFlying; 1984 newAv.Flying = isFlying;
1974 newAv.MinimumGroundFlightOffset = minimumGroundFlightOffset; 1985 newAv.MinimumGroundFlightOffset = minimumGroundFlightOffset;
1975 1986 newAv.m_avatarplanted = avplanted;
1987
1976 return newAv; 1988 return newAv;
1977 } 1989 }
1978 1990
@@ -1987,6 +1999,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1987 1999
1988 internal void AddCharacter(OdeCharacter chr) 2000 internal void AddCharacter(OdeCharacter chr)
1989 { 2001 {
2002 chr.m_avatarplanted = avplanted;
1990 if (!_characters.Contains(chr)) 2003 if (!_characters.Contains(chr))
1991 { 2004 {
1992 _characters.Add(chr); 2005 _characters.Add(chr);
@@ -4307,4 +4320,4 @@ namespace OpenSim.Region.Physics.OdePlugin
4307 m_stats[ODEPrimUpdateFrameMsStatName] = 0; 4320 m_stats[ODEPrimUpdateFrameMsStatName] = 0;
4308 } 4321 }
4309 } 4322 }
4310} \ No newline at end of file 4323}
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
index 3144d76..905540d 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
+++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
@@ -39,11 +39,8 @@ 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")]
44namespace OpenSim.Region.RegionCombinerModule 42namespace OpenSim.Region.RegionCombinerModule
45{ 43{
46 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
47 public class RegionCombinerModule : ISharedRegionModule, IRegionCombinerModule 44 public class RegionCombinerModule : ISharedRegionModule, IRegionCombinerModule
48 { 45 {
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -722,21 +719,21 @@ namespace OpenSim.Region.RegionCombinerModule
722 rootConn.ClientEventForwarder = new RegionCombinerClientEventForwarder(rootConn); 719 rootConn.ClientEventForwarder = new RegionCombinerClientEventForwarder(rootConn);
723 720
724 // Sets up the CoarseLocationUpdate forwarder for this root region 721 // Sets up the CoarseLocationUpdate forwarder for this root region
725 scene.EventManager.OnNewPresence += SetCourseLocationDelegate; 722 scene.EventManager.OnNewPresence += SetCoarseLocationDelegate;
726 723
727 // Adds this root region to a dictionary of regions that are connectable 724 // Adds this root region to a dictionary of regions that are connectable
728 m_regions.Add(scene.RegionInfo.originRegionID, rootConn); 725 m_regions.Add(scene.RegionInfo.originRegionID, rootConn);
729 } 726 }
730 } 727 }
731 728
732 private void SetCourseLocationDelegate(ScenePresence presence) 729 private void SetCoarseLocationDelegate(ScenePresence presence)
733 { 730 {
734 presence.SetSendCourseLocationMethod(SendCourseLocationUpdates); 731 presence.SetSendCoarseLocationMethod(SendCoarseLocationUpdates);
735 } 732 }
736 733
737 // This delegate was refactored for non-combined regions. 734 // This delegate was refactored for non-combined regions.
738 // This combined region version will not use the pre-compiled lists of locations and ids 735 // This combined region version will not use the pre-compiled lists of locations and ids
739 private void SendCourseLocationUpdates(UUID sceneId, ScenePresence presence, List<Vector3> coarseLocations, List<UUID> avatarUUIDs) 736 private void SendCoarseLocationUpdates(UUID sceneId, ScenePresence presence, List<Vector3> coarseLocations, List<UUID> avatarUUIDs)
740 { 737 {
741 RegionConnections connectiondata = null; 738 RegionConnections connectiondata = null;
742 lock (m_regions) 739 lock (m_regions)
@@ -759,18 +756,18 @@ namespace OpenSim.Region.RegionCombinerModule
759 } 756 }
760 }); 757 });
761 758
762 DistributeCourseLocationUpdates(CoarseLocations, AvatarUUIDs, connectiondata, presence); 759 DistributeCoarseLocationUpdates(CoarseLocations, AvatarUUIDs, connectiondata, presence);
763 } 760 }
764 761
765 private void DistributeCourseLocationUpdates(List<Vector3> locations, List<UUID> uuids, 762 private void DistributeCoarseLocationUpdates(List<Vector3> locations, List<UUID> uuids,
766 RegionConnections connectiondata, ScenePresence rootPresence) 763 RegionConnections connectiondata, ScenePresence rootPresence)
767 { 764 {
768 RegionData[] rdata = connectiondata.ConnectedRegions.ToArray(); 765 RegionData[] rdata = connectiondata.ConnectedRegions.ToArray();
769 //List<IClientAPI> clients = new List<IClientAPI>(); 766 //List<IClientAPI> clients = new List<IClientAPI>();
770 Dictionary<Vector2, RegionCourseLocationStruct> updates = new Dictionary<Vector2, RegionCourseLocationStruct>(); 767 Dictionary<Vector2, RegionCoarseLocationStruct> updates = new Dictionary<Vector2, RegionCoarseLocationStruct>();
771 768
772 // Root Region entry 769 // Root Region entry
773 RegionCourseLocationStruct rootupdatedata = new RegionCourseLocationStruct(); 770 RegionCoarseLocationStruct rootupdatedata = new RegionCoarseLocationStruct();
774 rootupdatedata.Locations = new List<Vector3>(); 771 rootupdatedata.Locations = new List<Vector3>();
775 rootupdatedata.Uuids = new List<UUID>(); 772 rootupdatedata.Uuids = new List<UUID>();
776 rootupdatedata.Offset = Vector2.Zero; 773 rootupdatedata.Offset = Vector2.Zero;
@@ -784,7 +781,7 @@ namespace OpenSim.Region.RegionCombinerModule
784 foreach (RegionData regiondata in rdata) 781 foreach (RegionData regiondata in rdata)
785 { 782 {
786 Vector2 offset = new Vector2(regiondata.Offset.X, regiondata.Offset.Y); 783 Vector2 offset = new Vector2(regiondata.Offset.X, regiondata.Offset.Y);
787 RegionCourseLocationStruct updatedata = new RegionCourseLocationStruct(); 784 RegionCoarseLocationStruct updatedata = new RegionCoarseLocationStruct();
788 updatedata.Locations = new List<Vector3>(); 785 updatedata.Locations = new List<Vector3>();
789 updatedata.Uuids = new List<UUID>(); 786 updatedata.Uuids = new List<UUID>();
790 updatedata.Offset = offset; 787 updatedata.Offset = offset;
@@ -810,7 +807,7 @@ namespace OpenSim.Region.RegionCombinerModule
810 if (!updates.ContainsKey(offset)) 807 if (!updates.ContainsKey(offset))
811 { 808 {
812 // This shouldn't happen 809 // This shouldn't happen
813 RegionCourseLocationStruct updatedata = new RegionCourseLocationStruct(); 810 RegionCoarseLocationStruct updatedata = new RegionCoarseLocationStruct();
814 updatedata.Locations = new List<Vector3>(); 811 updatedata.Locations = new List<Vector3>();
815 updatedata.Uuids = new List<UUID>(); 812 updatedata.Uuids = new List<UUID>();
816 updatedata.Offset = offset; 813 updatedata.Offset = offset;
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCourseLocation.cs b/OpenSim/Region/RegionCombinerModule/RegionCourseLocation.cs
index 53a678f..224ac99 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 RegionCourseLocationStruct 36 struct RegionCoarseLocationStruct
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
new file mode 100644
index 0000000..13cb8b6
--- /dev/null
+++ b/OpenSim/Region/RegionCombinerModule/Resources/RegionCombinerModule.addin.xml
@@ -0,0 +1,14 @@
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 82de06f..3bbdbe8 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -59,6 +59,7 @@ 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;
62 63
63using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; 64using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
64using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; 65using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
@@ -112,6 +113,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
112 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache = 113 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache =
113 new Dictionary<UUID, UserInfoCacheEntry>(); 114 new Dictionary<UUID, UserInfoCacheEntry>();
114 protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp. 115 protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp.
116 protected ISoundModule m_SoundModule = null;
115 117
116// protected Timer m_ShoutSayTimer; 118// protected Timer m_ShoutSayTimer;
117 protected int m_SayShoutCount = 0; 119 protected int m_SayShoutCount = 0;
@@ -159,6 +161,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
159 m_TransferModule = 161 m_TransferModule =
160 m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>(); 162 m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>();
161 m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>(); 163 m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>();
164 m_SoundModule = m_ScriptEngine.World.RequestModuleInterface<ISoundModule>();
162 165
163 AsyncCommands = new AsyncCommandManager(ScriptEngine); 166 AsyncCommands = new AsyncCommandManager(ScriptEngine);
164 } 167 }
@@ -341,7 +344,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
341 return GetLinkParts(m_host, linkType); 344 return GetLinkParts(m_host, linkType);
342 } 345 }
343 346
344 private List<SceneObjectPart> GetLinkParts(SceneObjectPart part, int linkType) 347 public static List<SceneObjectPart> GetLinkParts(SceneObjectPart part, int linkType)
345 { 348 {
346 List<SceneObjectPart> ret = new List<SceneObjectPart>(); 349 List<SceneObjectPart> ret = new List<SceneObjectPart>();
347 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) 350 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
@@ -426,12 +429,40 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
426 return key; 429 return key;
427 } 430 }
428 431
429 // convert a LSL_Rotation to a Quaternion 432 /// <summary>
430 public static Quaternion Rot2Quaternion(LSL_Rotation r) 433 /// Return the UUID of the asset matching the specified key or name
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)
431 { 440 {
432 Quaternion q = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s); 441 UUID key;
433 q.Normalize(); 442
434 return q; 443 if (!UUID.TryParse(k, out key))
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;
435 } 466 }
436 467
437 //These are the implementations of the various ll-functions used by the LSL scripts. 468 //These are the implementations of the various ll-functions used by the LSL scripts.
@@ -1240,9 +1271,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1240 public LSL_Float llGround(LSL_Vector offset) 1271 public LSL_Float llGround(LSL_Vector offset)
1241 { 1272 {
1242 m_host.AddScriptLPS(1); 1273 m_host.AddScriptLPS(1);
1243 Vector3 pos = m_host.GetWorldPosition() + new Vector3((float)offset.x, 1274 Vector3 pos = m_host.GetWorldPosition() + (Vector3)offset;
1244 (float)offset.y,
1245 (float)offset.z);
1246 1275
1247 //Get the slope normal. This gives us the equation of the plane tangent to the slope. 1276 //Get the slope normal. This gives us the equation of the plane tangent to the slope.
1248 LSL_Vector vsn = llGroundNormal(offset); 1277 LSL_Vector vsn = llGroundNormal(offset);
@@ -1492,31 +1521,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1492 if (part == null || part.ParentGroup.IsDeleted) 1521 if (part == null || part.ParentGroup.IsDeleted)
1493 return; 1522 return;
1494 1523
1495 if (scale.x < 0.01) 1524 // First we need to check whether or not we need to clamp the size of a physics-enabled prim
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
1502 PhysicsActor pa = part.ParentGroup.RootPart.PhysActor; 1525 PhysicsActor pa = part.ParentGroup.RootPart.PhysActor;
1503
1504 if (pa != null && pa.IsPhysical) 1526 if (pa != null && pa.IsPhysical)
1505 { 1527 {
1506 if (scale.x > World.m_maxPhys) 1528 scale.x = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.x));
1507 scale.x = World.m_maxPhys; 1529 scale.y = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.y));
1508 if (scale.y > World.m_maxPhys) 1530 scale.z = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.z));
1509 scale.y = World.m_maxPhys; 1531 }
1510 if (scale.z > World.m_maxPhys) 1532 else
1511 scale.z = World.m_maxPhys; 1533 {
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));
1512 } 1538 }
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 1539
1521 Vector3 tmp = part.Scale; 1540 Vector3 tmp = part.Scale;
1522 tmp.X = (float)scale.x; 1541 tmp.X = (float)scale.x;
@@ -1590,7 +1609,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1590 if (face == ScriptBaseClass.ALL_SIDES) 1609 if (face == ScriptBaseClass.ALL_SIDES)
1591 face = SceneObjectPart.ALL_SIDES; 1610 face = SceneObjectPart.ALL_SIDES;
1592 1611
1593 m_host.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); 1612 m_host.SetFaceColorAlpha(face, color, null);
1594 } 1613 }
1595 1614
1596 public void SetTexGen(SceneObjectPart part, int face,int style) 1615 public void SetTexGen(SceneObjectPart part, int face,int style)
@@ -2202,7 +2221,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2202 pos.x > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a east-adjacent region. 2221 pos.x > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a east-adjacent region.
2203 pos.y < -10.0 || // return FALSE if more than 10 meters into a south-adjacent region. 2222 pos.y < -10.0 || // return FALSE if more than 10 meters into a south-adjacent region.
2204 pos.y > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a north-adjacent region. 2223 pos.y > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a north-adjacent region.
2205 pos.z > 4096 // return FALSE if altitude than 4096m 2224 pos.z > Constants.RegionHeight // return FALSE if altitude than 4096m
2206 ) 2225 )
2207 ) 2226 )
2208 { 2227 {
@@ -2213,14 +2232,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
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. 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.
2214 2233
2215 Vector3 objectPos = m_host.ParentGroup.RootPart.AbsolutePosition; 2234 Vector3 objectPos = m_host.ParentGroup.RootPart.AbsolutePosition;
2216 LandData here = World.GetLandData((float)objectPos.X, (float)objectPos.Y); 2235 LandData here = World.GetLandData(objectPos);
2217 LandData there = World.GetLandData((float)pos.x, (float)pos.y); 2236 LandData there = World.GetLandData(pos);
2218 2237
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. 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.
2220 2239
2221 bool sameParcel = here.GlobalID == there.GlobalID; 2240 bool sameParcel = here.GlobalID == there.GlobalID;
2222 2241
2223 if (!sameParcel && !World.Permissions.CanObjectEntry(m_host.UUID, false, new Vector3((float)pos.x, (float)pos.y, (float)pos.z))) 2242 if (!sameParcel && !World.Permissions.CanRezObject(
2243 m_host.ParentGroup.PrimCount, m_host.ParentGroup.OwnerID, pos))
2224 { 2244 {
2225 return 0; 2245 return 0;
2226 } 2246 }
@@ -2279,16 +2299,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2279 if (part.ParentGroup.RootPart == part) 2299 if (part.ParentGroup.RootPart == part)
2280 { 2300 {
2281 SceneObjectGroup parent = part.ParentGroup; 2301 SceneObjectGroup parent = part.ParentGroup;
2282 Vector3 dest = new Vector3((float)toPos.x, (float)toPos.y, (float)toPos.z); 2302 if (!World.Permissions.CanObjectEntry(parent.UUID, false, (Vector3)toPos))
2283 if (!World.Permissions.CanObjectEntry(parent.UUID, false, dest))
2284 return; 2303 return;
2285 Util.FireAndForget(delegate(object x) { 2304 Util.FireAndForget(delegate(object x) {
2286 parent.UpdateGroupPosition(dest); 2305 parent.UpdateGroupPosition((Vector3)toPos);
2287 }); 2306 });
2288 } 2307 }
2289 else 2308 else
2290 { 2309 {
2291 part.OffsetPosition = new Vector3((float)toPos.x, (float)toPos.y, (float)toPos.z); 2310 part.OffsetPosition = (Vector3)toPos;
2292 SceneObjectGroup parent = part.ParentGroup; 2311 SceneObjectGroup parent = part.ParentGroup;
2293 parent.HasGroupChanged = true; 2312 parent.HasGroupChanged = true;
2294 parent.ScheduleGroupForTerseUpdate(); 2313 parent.ScheduleGroupForTerseUpdate();
@@ -2298,8 +2317,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2298 public LSL_Vector llGetPos() 2317 public LSL_Vector llGetPos()
2299 { 2318 {
2300 m_host.AddScriptLPS(1); 2319 m_host.AddScriptLPS(1);
2301 Vector3 pos = m_host.GetWorldPosition(); 2320 return m_host.GetWorldPosition();
2302 return new LSL_Vector(pos.X, pos.Y, pos.Z);
2303 } 2321 }
2304 2322
2305 public LSL_Vector llGetLocalPos() 2323 public LSL_Vector llGetLocalPos()
@@ -2326,7 +2344,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2326 pos = part.AbsolutePosition; 2344 pos = part.AbsolutePosition;
2327 } 2345 }
2328 2346
2329 return new LSL_Vector(pos.X, pos.Y, pos.Z); 2347// m_log.DebugFormat("[LSL API]: Returning {0} in GetPartLocalPos()", pos);
2348
2349 return new LSL_Vector(pos);
2330 } 2350 }
2331 2351
2332 public void llSetRot(LSL_Rotation rot) 2352 public void llSetRot(LSL_Rotation rot)
@@ -2334,26 +2354,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2334 m_host.AddScriptLPS(1); 2354 m_host.AddScriptLPS(1);
2335 2355
2336 // try to let this work as in SL... 2356 // try to let this work as in SL...
2337 if (m_host.LinkNum < 2) 2357 if (m_host.ParentID == 0)
2338 { 2358 {
2339 // Special case: If we are root, rotate complete SOG to new 2359 // special case: If we are root, rotate complete SOG to new rotation
2340 // rotation. 2360 SetRot(m_host, rot);
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));
2347 } 2361 }
2348 else 2362 else
2349 { 2363 {
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. 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.
2351 SceneObjectPart rootPart; 2365 SceneObjectPart rootPart = m_host.ParentGroup.RootPart;
2352 if (m_host.ParentGroup != null) // better safe than sorry 2366 if (rootPart != null) // better safe than sorry
2353 { 2367 {
2354 rootPart = m_host.ParentGroup.RootPart; 2368 SetRot(m_host, rootPart.RotationOffset * (Quaternion)rot);
2355 if (rootPart != null)
2356 SetRot(m_host, rootPart.RotationOffset * Rot2Quaternion(rot));
2357 } 2369 }
2358 } 2370 }
2359 2371
@@ -2363,8 +2375,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2363 public void llSetLocalRot(LSL_Rotation rot) 2375 public void llSetLocalRot(LSL_Rotation rot)
2364 { 2376 {
2365 m_host.AddScriptLPS(1); 2377 m_host.AddScriptLPS(1);
2366 2378 SetRot(m_host, rot);
2367 SetRot(m_host, Rot2Quaternion(rot));
2368 ScriptSleep(200); 2379 ScriptSleep(200);
2369 } 2380 }
2370 2381
@@ -2476,7 +2487,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2476 if (local != 0) 2487 if (local != 0)
2477 force *= llGetRot(); 2488 force *= llGetRot();
2478 2489
2479 m_host.ParentGroup.RootPart.SetForce(new Vector3((float)force.x, (float)force.y, (float)force.z)); 2490 m_host.ParentGroup.RootPart.SetForce(force);
2480 } 2491 }
2481 } 2492 }
2482 2493
@@ -2488,10 +2499,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2488 2499
2489 if (!m_host.ParentGroup.IsDeleted) 2500 if (!m_host.ParentGroup.IsDeleted)
2490 { 2501 {
2491 Vector3 tmpForce = m_host.ParentGroup.RootPart.GetForce(); 2502 force = m_host.ParentGroup.RootPart.GetForce();
2492 force.x = tmpForce.X;
2493 force.y = tmpForce.Y;
2494 force.z = tmpForce.Z;
2495 } 2503 }
2496 2504
2497 return force; 2505 return force;
@@ -2500,8 +2508,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2500 public LSL_Integer llTarget(LSL_Vector position, double range) 2508 public LSL_Integer llTarget(LSL_Vector position, double range)
2501 { 2509 {
2502 m_host.AddScriptLPS(1); 2510 m_host.AddScriptLPS(1);
2503 return m_host.ParentGroup.registerTargetWaypoint( 2511 return m_host.ParentGroup.registerTargetWaypoint(position,
2504 new Vector3((float)position.x, (float)position.y, (float)position.z), (float)range); 2512 (float)range);
2505 } 2513 }
2506 2514
2507 public void llTargetRemove(int number) 2515 public void llTargetRemove(int number)
@@ -2513,8 +2521,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2513 public LSL_Integer llRotTarget(LSL_Rotation rot, double error) 2521 public LSL_Integer llRotTarget(LSL_Rotation rot, double error)
2514 { 2522 {
2515 m_host.AddScriptLPS(1); 2523 m_host.AddScriptLPS(1);
2516 return m_host.ParentGroup.registerRotTargetWaypoint( 2524 return m_host.ParentGroup.registerRotTargetWaypoint(rot, (float)error);
2517 new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s), (float)error);
2518 } 2525 }
2519 2526
2520 public void llRotTargetRemove(int number) 2527 public void llRotTargetRemove(int number)
@@ -2526,7 +2533,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2526 public void llMoveToTarget(LSL_Vector target, double tau) 2533 public void llMoveToTarget(LSL_Vector target, double tau)
2527 { 2534 {
2528 m_host.AddScriptLPS(1); 2535 m_host.AddScriptLPS(1);
2529 m_host.MoveToTarget(new Vector3((float)target.x, (float)target.y, (float)target.z), (float)tau); 2536 m_host.MoveToTarget(target, (float)tau);
2530 } 2537 }
2531 2538
2532 public void llStopMoveToTarget() 2539 public void llStopMoveToTarget()
@@ -2539,7 +2546,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2539 { 2546 {
2540 m_host.AddScriptLPS(1); 2547 m_host.AddScriptLPS(1);
2541 //No energy force yet 2548 //No energy force yet
2542 Vector3 v = new Vector3((float)force.x, (float)force.y, (float)force.z); 2549 Vector3 v = force;
2543 if (v.Length() > 20000.0f) 2550 if (v.Length() > 20000.0f)
2544 { 2551 {
2545 v.Normalize(); 2552 v.Normalize();
@@ -2552,13 +2559,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2552 public void llApplyRotationalImpulse(LSL_Vector force, int local) 2559 public void llApplyRotationalImpulse(LSL_Vector force, int local)
2553 { 2560 {
2554 m_host.AddScriptLPS(1); 2561 m_host.AddScriptLPS(1);
2555 m_host.ParentGroup.RootPart.ApplyAngularImpulse(new Vector3((float)force.x, (float)force.y, (float)force.z), local != 0); 2562 m_host.ParentGroup.RootPart.ApplyAngularImpulse(force, local != 0);
2556 } 2563 }
2557 2564
2558 public void llSetTorque(LSL_Vector torque, int local) 2565 public void llSetTorque(LSL_Vector torque, int local)
2559 { 2566 {
2560 m_host.AddScriptLPS(1); 2567 m_host.AddScriptLPS(1);
2561 m_host.ParentGroup.RootPart.SetAngularImpulse(new Vector3((float)torque.x, (float)torque.y, (float)torque.z), local != 0); 2568 m_host.ParentGroup.RootPart.SetAngularImpulse(torque, local != 0);
2562 } 2569 }
2563 2570
2564 public LSL_Vector llGetTorque() 2571 public LSL_Vector llGetTorque()
@@ -2668,63 +2675,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2668 m_host.AddScriptLPS(1); 2675 m_host.AddScriptLPS(1);
2669 2676
2670 // send the sound, once, to all clients in range 2677 // send the sound, once, to all clients in range
2671 m_host.SendSound(KeyOrName(sound).ToString(), volume, false, 0, 0, false, false); 2678 if (m_SoundModule != null)
2679 {
2680 m_SoundModule.SendSound(m_host.UUID,
2681 KeyOrName(sound, AssetType.Sound), volume, false, 0,
2682 0, false, false);
2683 }
2672 } 2684 }
2673 2685
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
2682 public void llLoopSound(string sound, double volume) 2686 public void llLoopSound(string sound, double volume)
2683 { 2687 {
2684 m_host.AddScriptLPS(1); 2688 m_host.AddScriptLPS(1);
2685 2689 if (m_SoundModule != null)
2686 if (m_host.Sound != UUID.Zero) 2690 {
2687 llStopSound(); 2691 m_SoundModule.LoopSound(m_host.UUID, KeyOrName(sound),
2688 2692 volume, 20, false);
2689 m_host.Sound = KeyOrName(sound); 2693 }
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();
2696 } 2694 }
2697 2695
2698 public void llLoopSoundMaster(string sound, double volume) 2696 public void llLoopSoundMaster(string sound, double volume)
2699 { 2697 {
2700 m_host.AddScriptLPS(1); 2698 m_host.AddScriptLPS(1);
2701 m_host.ParentGroup.LoopSoundMasterPrim = m_host; 2699 if (m_SoundModule != null)
2702 lock (m_host.ParentGroup.LoopSoundSlavePrims)
2703 { 2700 {
2704 foreach (SceneObjectPart prim in m_host.ParentGroup.LoopSoundSlavePrims) 2701 m_SoundModule.LoopSound(m_host.UUID, KeyOrName(sound),
2705 { 2702 volume, 20, true);
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 }
2717 } 2703 }
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();
2728 } 2704 }
2729 2705
2730 public void llLoopSoundSlave(string sound, double volume) 2706 public void llLoopSoundSlave(string sound, double volume)
@@ -2741,61 +2717,39 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2741 m_host.AddScriptLPS(1); 2717 m_host.AddScriptLPS(1);
2742 2718
2743 // send the sound, once, to all clients in range 2719 // send the sound, once, to all clients in range
2744 m_host.SendSound(KeyOrName(sound).ToString(), volume, false, 0, 0, true, false); 2720 if (m_SoundModule != null)
2721 {
2722 m_SoundModule.SendSound(m_host.UUID,
2723 KeyOrName(sound, AssetType.Sound), volume, false, 0,
2724 0, true, false);
2725 }
2745 } 2726 }
2746 2727
2747 public void llTriggerSound(string sound, double volume) 2728 public void llTriggerSound(string sound, double volume)
2748 { 2729 {
2749 m_host.AddScriptLPS(1); 2730 m_host.AddScriptLPS(1);
2750 // send the sound, once, to all clients in range 2731 // send the sound, once, to all clients in rangeTrigger or play an attached sound in this part's inventory.
2751 m_host.SendSound(KeyOrName(sound).ToString(), volume, true, 0, 0, false, false); 2732 if (m_SoundModule != null)
2733 {
2734 m_SoundModule.SendSound(m_host.UUID,
2735 KeyOrName(sound, AssetType.Sound), volume, true, 0, 0,
2736 false, false);
2737 }
2752 } 2738 }
2753 2739
2754 // Xantor 20080528: Clear prim data of sound instead
2755 public void llStopSound() 2740 public void llStopSound()
2756 { 2741 {
2757 m_host.AddScriptLPS(1); 2742 m_host.AddScriptLPS(1);
2758 if (m_host.ParentGroup.LoopSoundSlavePrims.Contains(m_host)) 2743
2759 { 2744 if (m_SoundModule != null)
2760 if (m_host.ParentGroup.LoopSoundMasterPrim == m_host) 2745 m_SoundModule.StopSound(m_host.UUID);
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 }
2793 } 2746 }
2794 2747
2795 public void llPreloadSound(string sound) 2748 public void llPreloadSound(string sound)
2796 { 2749 {
2797 m_host.AddScriptLPS(1); 2750 m_host.AddScriptLPS(1);
2798 m_host.PreloadSound(sound); 2751 if (m_SoundModule != null)
2752 m_SoundModule.PreloadSound(m_host.UUID, KeyOrName(sound), 0);
2799 ScriptSleep(1000); 2753 ScriptSleep(1000);
2800 } 2754 }
2801 2755
@@ -3123,13 +3077,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3123 return; 3077 return;
3124 } 3078 }
3125 3079
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
3129 // need the magnitude later 3080 // need the magnitude later
3130 // float velmag = (float)Util.GetMagnitude(llvel); 3081 // float velmag = (float)Util.GetMagnitude(llvel);
3131 3082
3132 SceneObjectGroup new_group = World.RezObject(m_host, item, llpos, Rot2Quaternion(rot), llvel, param); 3083 SceneObjectGroup new_group = World.RezObject(m_host, item, pos, rot, vel, param);
3133 3084
3134 // If either of these are null, then there was an unknown error. 3085 // If either of these are null, then there was an unknown error.
3135 if (new_group == null) 3086 if (new_group == null)
@@ -3156,11 +3107,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3156 3107
3157 PhysicsActor pa = new_group.RootPart.PhysActor; 3108 PhysicsActor pa = new_group.RootPart.PhysActor;
3158 3109
3159 if (pa != null && pa.IsPhysical && llvel != Vector3.Zero) 3110 if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero)
3160 { 3111 {
3161 float groupmass = new_group.GetMass(); 3112 float groupmass = new_group.GetMass();
3162 llvel *= -groupmass; 3113 vel *= -groupmass;
3163 llApplyImpulse(new LSL_Vector(llvel.X, llvel.Y,llvel.Z), 0); 3114 llApplyImpulse(vel, 0);
3164 } 3115 }
3165 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay) 3116 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
3166 return; 3117 return;
@@ -3211,7 +3162,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3211 return; 3162 return;
3212 } 3163 }
3213 3164
3214 m_host.StartLookAt(Rot2Quaternion(r3 * r2 * r1), (float)strength, (float)damping); 3165 m_host.StartLookAt((Quaternion)(r3 * r2 * r1), (float)strength, (float)damping);
3215 } 3166 }
3216 } 3167 }
3217 3168
@@ -3637,7 +3588,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3637 } 3588 }
3638 else 3589 else
3639 { 3590 {
3640 m_host.RotLookAt(Rot2Quaternion(target), (float)strength, (float)damping); 3591 m_host.RotLookAt(target, (float)strength, (float)damping);
3641 } 3592 }
3642 } 3593 }
3643 3594
@@ -3718,7 +3669,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3718 3669
3719 protected void TargetOmega(SceneObjectPart part, LSL_Vector axis, double spinrate, double gain) 3670 protected void TargetOmega(SceneObjectPart part, LSL_Vector axis, double spinrate, double gain)
3720 { 3671 {
3721 part.UpdateAngularVelocity(new Vector3((float)(axis.x * spinrate), (float)(axis.y * spinrate), (float)(axis.z * spinrate))); 3672 part.UpdateAngularVelocity(axis * spinrate);
3722 } 3673 }
3723 3674
3724 public LSL_Integer llGetStartParameter() 3675 public LSL_Integer llGetStartParameter()
@@ -3932,7 +3883,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3932 try 3883 try
3933 { 3884 {
3934 foreach (SceneObjectPart part in parts) 3885 foreach (SceneObjectPart part in parts)
3935 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); 3886 part.SetFaceColorAlpha(face, color, null);
3936 } 3887 }
3937 finally 3888 finally
3938 { 3889 {
@@ -4158,6 +4109,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4158 } 4109 }
4159 4110
4160 /// <summary> 4111 /// <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>
4161 /// The rules governing the returned name are not simple. The only 4122 /// The rules governing the returned name are not simple. The only
4162 /// time a blank name is returned is if the target prim has a blank 4123 /// time a blank name is returned is if the target prim has a blank
4163 /// name. If no prim with the given link number can be found then 4124 /// name. If no prim with the given link number can be found then
@@ -4185,10 +4146,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4185 /// Mentions NULL_KEY being returned 4146 /// Mentions NULL_KEY being returned
4186 /// http://wiki.secondlife.com/wiki/LlGetLinkName 4147 /// http://wiki.secondlife.com/wiki/LlGetLinkName
4187 /// Mentions using the LINK_* constants, some of which are negative 4148 /// Mentions using the LINK_* constants, some of which are negative
4188 /// </summary> 4149 /// </remarks>
4189 public LSL_String llGetLinkName(int linknum) 4150 public LSL_String llGetLinkName(int linknum)
4190 { 4151 {
4191 m_host.AddScriptLPS(1); 4152 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
4192 // parse for sitting avatare-names 4157 // parse for sitting avatare-names
4193 List<String> nametable = new List<String>(); 4158 List<String> nametable = new List<String>();
4194 World.ForEachRootScenePresence(delegate(ScenePresence presence) 4159 World.ForEachRootScenePresence(delegate(ScenePresence presence)
@@ -4212,10 +4177,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4212 return nametable[totalprims - linknum]; 4177 return nametable[totalprims - linknum];
4213 } 4178 }
4214 4179
4215 // simplest case, this prims link number
4216 if (m_host.LinkNum == linknum)
4217 return m_host.Name;
4218
4219 // Single prim 4180 // Single prim
4220 if (m_host.LinkNum == 0) 4181 if (m_host.LinkNum == 0)
4221 { 4182 {
@@ -4364,7 +4325,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4364 World.RegionInfo.RegionName+" "+ 4325 World.RegionInfo.RegionName+" "+
4365 m_host.AbsolutePosition.ToString(), 4326 m_host.AbsolutePosition.ToString(),
4366 agentItem.ID, true, m_host.AbsolutePosition, 4327 agentItem.ID, true, m_host.AbsolutePosition,
4367 bucket); 4328 bucket, true);
4368 4329
4369 ScenePresence sp; 4330 ScenePresence sp;
4370 4331
@@ -4402,9 +4363,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4402 public void llSetText(string text, LSL_Vector color, double alpha) 4363 public void llSetText(string text, LSL_Vector color, double alpha)
4403 { 4364 {
4404 m_host.AddScriptLPS(1); 4365 m_host.AddScriptLPS(1);
4405 Vector3 av3 = new Vector3(Util.Clip((float)color.x, 0.0f, 1.0f), 4366 Vector3 av3 = Util.Clip(color, 0.0f, 1.0f);
4406 Util.Clip((float)color.y, 0.0f, 1.0f),
4407 Util.Clip((float)color.z, 0.0f, 1.0f));
4408 if (text.Length > 254) 4367 if (text.Length > 254)
4409 text = text.Remove(254); 4368 text = text.Remove(254);
4410 4369
@@ -4631,14 +4590,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4631 ScriptSleep(5000); 4590 ScriptSleep(5000);
4632 } 4591 }
4633 4592
4634 public void llTeleportAgent(string agent, string destination, LSL_Vector pos, LSL_Vector lookAt) 4593 public void llTeleportAgent(string agent, string destination, LSL_Vector targetPos, LSL_Vector targetLookAt)
4635 { 4594 {
4636 m_host.AddScriptLPS(1); 4595 m_host.AddScriptLPS(1);
4637 UUID agentId = new UUID(); 4596 UUID agentId = new UUID();
4638 4597
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
4642 if (UUID.TryParse(agent, out agentId)) 4598 if (UUID.TryParse(agent, out agentId))
4643 { 4599 {
4644 ScenePresence presence = World.GetScenePresence(agentId); 4600 ScenePresence presence = World.GetScenePresence(agentId);
@@ -4667,15 +4623,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4667 } 4623 }
4668 } 4624 }
4669 4625
4670 public void llTeleportAgentGlobalCoords(string agent, LSL_Vector global_coords, LSL_Vector pos, LSL_Vector lookAt) 4626 public void llTeleportAgentGlobalCoords(string agent, LSL_Vector global_coords, LSL_Vector targetPos, LSL_Vector targetLookAt)
4671 { 4627 {
4672 m_host.AddScriptLPS(1); 4628 m_host.AddScriptLPS(1);
4673 UUID agentId = new UUID(); 4629 UUID agentId = new UUID();
4674 4630
4675 ulong regionHandle = Utils.UIntsToLong((uint)global_coords.x, (uint)global_coords.y); 4631 ulong regionHandle = Utils.UIntsToLong((uint)global_coords.x, (uint)global_coords.y);
4676 4632
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);
4679 if (UUID.TryParse(agent, out agentId)) 4633 if (UUID.TryParse(agent, out agentId))
4680 { 4634 {
4681 ScenePresence presence = World.GetScenePresence(agentId); 4635 ScenePresence presence = World.GetScenePresence(agentId);
@@ -4777,16 +4731,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4777 return; 4731 return;
4778 } 4732 }
4779 // TODO: Parameter check logic required. 4733 // TODO: Parameter check logic required.
4780 UUID soundId = UUID.Zero; 4734 m_host.CollisionSound = KeyOrName(impact_sound, AssetType.Sound);
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;
4790 m_host.CollisionSoundVolume = (float)impact_volume; 4735 m_host.CollisionSoundVolume = (float)impact_volume;
4791 m_host.CollisionSoundType = 1; 4736 m_host.CollisionSoundType = 1;
4792 } 4737 }
@@ -4972,7 +4917,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4972 distance_attenuation = 1f / normalized_units; 4917 distance_attenuation = 1f / normalized_units;
4973 } 4918 }
4974 4919
4975 Vector3 applied_linear_impulse = new Vector3((float)impulse.x, (float)impulse.y, (float)impulse.z); 4920 Vector3 applied_linear_impulse = impulse;
4976 { 4921 {
4977 float impulse_length = applied_linear_impulse.Length(); 4922 float impulse_length = applied_linear_impulse.Length();
4978 4923
@@ -5620,25 +5565,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5620 /// separated list. There is a space after 5565 /// separated list. There is a space after
5621 /// each comma. 5566 /// each comma.
5622 /// </summary> 5567 /// </summary>
5623
5624 public LSL_String llList2CSV(LSL_List src) 5568 public LSL_String llList2CSV(LSL_List src)
5625 { 5569 {
5626
5627 string ret = String.Empty;
5628 int x = 0;
5629
5630 m_host.AddScriptLPS(1); 5570 m_host.AddScriptLPS(1);
5631 5571
5632 if (src.Data.Length > 0) 5572 return string.Join(", ",
5633 { 5573 (new List<object>(src.Data)).ConvertAll<string>(o =>
5634 ret = src.Data[x++].ToString(); 5574 {
5635 for (; x < src.Data.Length; x++) 5575 return o.ToString();
5636 { 5576 }).ToArray());
5637 ret += ", "+src.Data[x].ToString();
5638 }
5639 }
5640
5641 return ret;
5642 } 5577 }
5643 5578
5644 /// <summary> 5579 /// <summary>
@@ -5937,27 +5872,36 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5937 /// Returns the index of the first occurrence of test 5872 /// Returns the index of the first occurrence of test
5938 /// in src. 5873 /// in src.
5939 /// </summary> 5874 /// </summary>
5940 5875 /// <param name="src">Source list</param>
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>
5941 public LSL_Integer llListFindList(LSL_List src, LSL_List test) 5881 public LSL_Integer llListFindList(LSL_List src, LSL_List test)
5942 { 5882 {
5943
5944 int index = -1; 5883 int index = -1;
5945 int length = src.Length - test.Length + 1; 5884 int length = src.Length - test.Length + 1;
5946 5885
5947 m_host.AddScriptLPS(1); 5886 m_host.AddScriptLPS(1);
5948 5887
5949 // If either list is empty, do not match 5888 // If either list is empty, do not match
5950
5951 if (src.Length != 0 && test.Length != 0) 5889 if (src.Length != 0 && test.Length != 0)
5952 { 5890 {
5953 for (int i = 0; i < length; i++) 5891 for (int i = 0; i < length; i++)
5954 { 5892 {
5955 if (src.Data[i].Equals(test.Data[0])) 5893 // Why this piece of insanity? This is because most script constants are C# value types (e.g. int)
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]))
5956 { 5899 {
5957 int j; 5900 int j;
5958 for (j = 1; j < test.Length; j++) 5901 for (j = 1; j < test.Length; j++)
5959 if (!src.Data[i+j].Equals(test.Data[j])) 5902 if (!(src.Data[i+j].Equals(test.Data[j]) || test.Data[j].Equals(src.Data[i+j])))
5960 break; 5903 break;
5904
5961 if (j == test.Length) 5905 if (j == test.Length)
5962 { 5906 {
5963 index = i; 5907 index = i;
@@ -5968,19 +5912,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5968 } 5912 }
5969 5913
5970 return index; 5914 return index;
5971
5972 } 5915 }
5973 5916
5974 public LSL_String llGetObjectName() 5917 public LSL_String llGetObjectName()
5975 { 5918 {
5976 m_host.AddScriptLPS(1); 5919 m_host.AddScriptLPS(1);
5977 return m_host.Name!=null?m_host.Name:String.Empty; 5920 return m_host.Name !=null ? m_host.Name : String.Empty;
5978 } 5921 }
5979 5922
5980 public void llSetObjectName(string name) 5923 public void llSetObjectName(string name)
5981 { 5924 {
5982 m_host.AddScriptLPS(1); 5925 m_host.AddScriptLPS(1);
5983 m_host.Name = name!=null?name:String.Empty; 5926 m_host.Name = name != null ? name : String.Empty;
5984 } 5927 }
5985 5928
5986 public LSL_String llGetDate() 5929 public LSL_String llGetDate()
@@ -6154,7 +6097,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6154 flags |= ScriptBaseClass.AGENT_SITTING; 6097 flags |= ScriptBaseClass.AGENT_SITTING;
6155 } 6098 }
6156 6099
6157 if (agent.Animator.Animations.DefaultAnimation.AnimID 6100 if (agent.Animator.Animations.ImplicitDefaultAnimation.AnimID
6158 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) 6101 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
6159 { 6102 {
6160 flags |= ScriptBaseClass.AGENT_SITTING; 6103 flags |= ScriptBaseClass.AGENT_SITTING;
@@ -6311,19 +6254,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6311 m_host.AddScriptLPS(1); 6254 m_host.AddScriptLPS(1);
6312 6255
6313 List<SceneObjectPart> parts = GetLinkParts(linknumber); 6256 List<SceneObjectPart> parts = GetLinkParts(linknumber);
6314 if (parts.Count > 0) 6257
6258 try
6315 { 6259 {
6316 try 6260 foreach (SceneObjectPart part in parts)
6317 {
6318 foreach (var part in parts)
6319 {
6320 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
6321 }
6322 }
6323 finally
6324 { 6261 {
6262 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
6325 } 6263 }
6326 } 6264 }
6265 finally
6266 {
6267 }
6327 } 6268 }
6328 6269
6329 private void SetTextureAnim(SceneObjectPart part, int mode, int face, int sizex, int sizey, double start, double length, double rate) 6270 private void SetTextureAnim(SceneObjectPart part, int mode, int face, int sizex, int sizey, double start, double length, double rate)
@@ -6352,10 +6293,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6352 LSL_Vector bottom_south_west) 6293 LSL_Vector bottom_south_west)
6353 { 6294 {
6354 m_host.AddScriptLPS(1); 6295 m_host.AddScriptLPS(1);
6355 float radius1 = (float)llVecDist(llGetPos(), top_north_east); 6296 if (m_SoundModule != null)
6356 float radius2 = (float)llVecDist(llGetPos(), bottom_south_west); 6297 {
6357 float radius = Math.Abs(radius1 - radius2); 6298 m_SoundModule.TriggerSoundLimited(m_host.UUID,
6358 m_host.SendSound(KeyOrName(sound).ToString(), volume, true, 0, radius, false, false); 6299 KeyOrName(sound, AssetType.Sound), volume,
6300 bottom_south_west, top_north_east);
6301 }
6359 } 6302 }
6360 6303
6361 public void llEjectFromLand(string pest) 6304 public void llEjectFromLand(string pest)
@@ -6541,9 +6484,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6541 6484
6542 //Plug the x,y coordinates of the slope normal into the equation of the plane to get 6485 //Plug the x,y coordinates of the slope normal into the equation of the plane to get
6543 //the height of that point on the plane. The resulting vector gives the slope. 6486 //the height of that point on the plane. The resulting vector gives the slope.
6544 Vector3 vsl = new Vector3(); 6487 Vector3 vsl = vsn;
6545 vsl.X = (float)vsn.x;
6546 vsl.Y = (float)vsn.y;
6547 vsl.Z = (float)(((vsn.x * vsn.x) + (vsn.y * vsn.y)) / (-1 * vsn.z)); 6488 vsl.Z = (float)(((vsn.x * vsn.x) + (vsn.y * vsn.y)) / (-1 * vsn.z));
6548 vsl.Normalize(); 6489 vsl.Normalize();
6549 //Normalization might be overkill here 6490 //Normalization might be overkill here
@@ -6554,9 +6495,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6554 public LSL_Vector llGroundNormal(LSL_Vector offset) 6495 public LSL_Vector llGroundNormal(LSL_Vector offset)
6555 { 6496 {
6556 m_host.AddScriptLPS(1); 6497 m_host.AddScriptLPS(1);
6557 Vector3 pos = m_host.GetWorldPosition() + new Vector3((float)offset.x, 6498 Vector3 pos = m_host.GetWorldPosition() + (Vector3)offset;
6558 (float)offset.y,
6559 (float)offset.z);
6560 // Clamp to valid position 6499 // Clamp to valid position
6561 if (pos.X < 0) 6500 if (pos.X < 0)
6562 pos.X = 0; 6501 pos.X = 0;
@@ -6721,7 +6660,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6721 6660
6722 List<SceneObjectPart> parts = GetLinkParts(linknumber); 6661 List<SceneObjectPart> parts = GetLinkParts(linknumber);
6723 6662
6724 foreach (var part in parts) 6663 foreach (SceneObjectPart part in parts)
6725 { 6664 {
6726 SetParticleSystem(part, rules); 6665 SetParticleSystem(part, rules);
6727 } 6666 }
@@ -6965,16 +6904,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6965 if (m_TransferModule != null) 6904 if (m_TransferModule != null)
6966 { 6905 {
6967 byte[] bucket = new byte[] { (byte)AssetType.Folder }; 6906 byte[] bucket = new byte[] { (byte)AssetType.Folder };
6968 6907
6908 Vector3 pos = m_host.AbsolutePosition;
6909
6969 GridInstantMessage msg = new GridInstantMessage(World, 6910 GridInstantMessage msg = new GridInstantMessage(World,
6970 m_host.UUID, m_host.Name + ", an object owned by " + 6911 m_host.OwnerID, m_host.Name, destID,
6971 resolveName(m_host.OwnerID) + ",", destID,
6972 (byte)InstantMessageDialog.TaskInventoryOffered, 6912 (byte)InstantMessageDialog.TaskInventoryOffered,
6973 false, category + "\n" + m_host.Name + " is located at " + 6913 false, string.Format("'{0}'", category),
6974 World.RegionInfo.RegionName + " " + 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
6975 m_host.AbsolutePosition.ToString(), 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),
6976 folderID, true, m_host.AbsolutePosition, 6916 folderID, false, pos,
6977 bucket); 6917 bucket, false);
6978 6918
6979 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); 6919 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
6980 } 6920 }
@@ -7010,8 +6950,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7010 6950
7011 if (!m_host.ParentGroup.IsDeleted) 6951 if (!m_host.ParentGroup.IsDeleted)
7012 { 6952 {
7013 m_host.ParentGroup.RootPart.SetVehicleVectorParam(param, 6953 m_host.ParentGroup.RootPart.SetVehicleVectorParam(param, vec);
7014 new Vector3((float)vec.x, (float)vec.y, (float)vec.z));
7015 } 6954 }
7016 } 6955 }
7017 6956
@@ -7023,7 +6962,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7023 6962
7024 if (!m_host.ParentGroup.IsDeleted) 6963 if (!m_host.ParentGroup.IsDeleted)
7025 { 6964 {
7026 m_host.ParentGroup.RootPart.SetVehicleRotationParam(param, Rot2Quaternion(rot)); 6965 m_host.ParentGroup.RootPart.SetVehicleRotationParam(param, rot);
7027 } 6966 }
7028 } 6967 }
7029 6968
@@ -7053,8 +6992,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7053 if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0) 6992 if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0)
7054 rot.s = 1; // ZERO_ROTATION = 0,0,0,1 6993 rot.s = 1; // ZERO_ROTATION = 0,0,0,1
7055 6994
7056 part.SitTargetPosition = new Vector3((float)offset.x, (float)offset.y, (float)offset.z); 6995 part.SitTargetPosition = offset;
7057 part.SitTargetOrientation = Rot2Quaternion(rot); 6996 part.SitTargetOrientation = rot;
7058 part.ParentGroup.HasGroupChanged = true; 6997 part.ParentGroup.HasGroupChanged = true;
7059 } 6998 }
7060 6999
@@ -7157,13 +7096,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7157 public void llSetCameraEyeOffset(LSL_Vector offset) 7096 public void llSetCameraEyeOffset(LSL_Vector offset)
7158 { 7097 {
7159 m_host.AddScriptLPS(1); 7098 m_host.AddScriptLPS(1);
7160 m_host.SetCameraEyeOffset(new Vector3((float)offset.x, (float)offset.y, (float)offset.z)); 7099 m_host.SetCameraEyeOffset(offset);
7161 } 7100 }
7162 7101
7163 public void llSetCameraAtOffset(LSL_Vector offset) 7102 public void llSetCameraAtOffset(LSL_Vector offset)
7164 { 7103 {
7165 m_host.AddScriptLPS(1); 7104 m_host.AddScriptLPS(1);
7166 m_host.SetCameraAtOffset(new Vector3((float)offset.x, (float)offset.y, (float)offset.z)); 7105 m_host.SetCameraAtOffset(offset);
7167 } 7106 }
7168 7107
7169 public LSL_String llDumpList2String(LSL_List src, string seperator) 7108 public LSL_String llDumpList2String(LSL_List src, string seperator)
@@ -7185,7 +7124,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7185 public LSL_Integer llScriptDanger(LSL_Vector pos) 7124 public LSL_Integer llScriptDanger(LSL_Vector pos)
7186 { 7125 {
7187 m_host.AddScriptLPS(1); 7126 m_host.AddScriptLPS(1);
7188 bool result = World.ScriptDanger(m_host.LocalId, new Vector3((float)pos.x, (float)pos.y, (float)pos.z)); 7127 bool result = World.ScriptDanger(m_host.LocalId, pos);
7189 if (result) 7128 if (result)
7190 { 7129 {
7191 return 1; 7130 return 1;
@@ -7767,7 +7706,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7767 { 7706 {
7768 m_host.AddScriptLPS(1); 7707 m_host.AddScriptLPS(1);
7769 7708
7770 setLinkPrimParams(ScriptBaseClass.LINK_THIS, rules); 7709 setLinkPrimParams(ScriptBaseClass.LINK_THIS, rules, "llSetPrimitiveParams");
7771 7710
7772 ScriptSleep(200); 7711 ScriptSleep(200);
7773 } 7712 }
@@ -7776,10 +7715,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7776 { 7715 {
7777 m_host.AddScriptLPS(1); 7716 m_host.AddScriptLPS(1);
7778 7717
7779 setLinkPrimParams(linknumber, rules); 7718 setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParamsFast");
7719
7720 ScriptSleep(200);
7780 } 7721 }
7781 7722
7782 private void setLinkPrimParams(int linknumber, LSL_List rules) 7723 private void setLinkPrimParams(int linknumber, LSL_List rules, string originFunc)
7783 { 7724 {
7784 List<object> parts = new List<object>(); 7725 List<object> parts = new List<object>();
7785 List<SceneObjectPart> prims = GetLinkParts(linknumber); 7726 List<SceneObjectPart> prims = GetLinkParts(linknumber);
@@ -7790,15 +7731,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7790 parts.Add(p); 7731 parts.Add(p);
7791 7732
7792 LSL_List remaining = null; 7733 LSL_List remaining = null;
7734 uint rulesParsed = 0;
7793 7735
7794 if (parts.Count > 0) 7736 if (parts.Count > 0)
7795 { 7737 {
7796 foreach (object part in parts) 7738 foreach (object part in parts)
7797 { 7739 {
7798 if (part is SceneObjectPart) 7740 if (part is SceneObjectPart)
7799 remaining = SetPrimParams((SceneObjectPart)part, rules); 7741 remaining = SetPrimParams((SceneObjectPart)part, rules, originFunc, ref rulesParsed);
7800 else 7742 else
7801 remaining = SetPrimParams((ScenePresence)part, rules); 7743 remaining = SetPrimParams((ScenePresence)part, rules, originFunc, ref rulesParsed);
7802 } 7744 }
7803 7745
7804 while ((object)remaining != null && remaining.Length > 2) 7746 while ((object)remaining != null && remaining.Length > 2)
@@ -7817,9 +7759,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7817 foreach (object part in parts) 7759 foreach (object part in parts)
7818 { 7760 {
7819 if (part is SceneObjectPart) 7761 if (part is SceneObjectPart)
7820 remaining = SetPrimParams((SceneObjectPart)part, rules); 7762 remaining = SetPrimParams((SceneObjectPart)part, rules, originFunc, ref rulesParsed);
7821 else 7763 else
7822 remaining = SetPrimParams((ScenePresence)part, rules); 7764 remaining = SetPrimParams((ScenePresence)part, rules, originFunc, ref rulesParsed);
7823 } 7765 }
7824 } 7766 }
7825 } 7767 }
@@ -7857,6 +7799,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7857 7799
7858 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) 7800 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
7859 { 7801 {
7802 setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParams");
7860 llSetLinkPrimitiveParamsFast(linknumber, rules); 7803 llSetLinkPrimitiveParamsFast(linknumber, rules);
7861 ScriptSleep(200); 7804 ScriptSleep(200);
7862 } 7805 }
@@ -7884,195 +7827,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7884 return new Vector3((float)x, (float)y, (float)z); 7827 return new Vector3((float)x, (float)y, (float)z);
7885 } 7828 }
7886 7829
7887 protected LSL_List SetPrimParams(ScenePresence av, LSL_List rules) 7830 protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules, string originFunc, ref uint rulesParsed)
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)
8071 { 7831 {
8072 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) 7832 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
8073 return null; 7833 return null;
8074 7834
8075 int idx = 0; 7835 int idx = 0;
7836 int idxStart = 0;
8076 7837
8077 SceneObjectGroup parentgrp = part.ParentGroup; 7838 SceneObjectGroup parentgrp = part.ParentGroup;
8078 7839
@@ -8083,9 +7844,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8083 { 7844 {
8084 while (idx < rules.Length) 7845 while (idx < rules.Length)
8085 { 7846 {
7847 ++rulesParsed;
8086 int code = rules.GetLSLIntegerItem(idx++); 7848 int code = rules.GetLSLIntegerItem(idx++);
8087 7849
8088 int remain = rules.Length - idx; 7850 int remain = rules.Length - idx;
7851 idxStart = idx;
8089 7852
8090 int face; 7853 int face;
8091 LSL_Vector v; 7854 LSL_Vector v;
@@ -8115,18 +7878,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8115 return null; 7878 return null;
8116 7879
8117 LSL_Rotation q = rules.GetQuaternionItem(idx++); 7880 LSL_Rotation q = rules.GetQuaternionItem(idx++);
8118 SceneObjectPart rootPart = parentgrp.RootPart;
8119 // try to let this work as in SL... 7881 // try to let this work as in SL...
8120 if (rootPart == part) 7882 if (part.ParentID == 0)
8121 { 7883 {
8122 // special case: If we are root, rotate complete SOG to new rotation 7884 // special case: If we are root, rotate complete SOG to new rotation
8123 SetRot(part, Rot2Quaternion(q)); 7885 SetRot(part, q);
8124 } 7886 }
8125 else 7887 else
8126 { 7888 {
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. 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.
8128 // sounds like sl bug that we need to replicate 7890 SceneObjectPart rootPart = part.ParentGroup.RootPart;
8129 SetRot(part, rootPart.RotationOffset * Rot2Quaternion(q)); 7891 SetRot(part, rootPart.RotationOffset * (Quaternion)q);
8130 } 7892 }
8131 7893
8132 break; 7894 break;
@@ -8300,8 +8062,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8300 LSL_Vector color=rules.GetVector3Item(idx++); 8062 LSL_Vector color=rules.GetVector3Item(idx++);
8301 double alpha=(double)rules.GetLSLFloatItem(idx++); 8063 double alpha=(double)rules.GetLSLFloatItem(idx++);
8302 8064
8303 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); 8065 part.SetFaceColorAlpha(face, color, alpha);
8304 SetAlpha(part, alpha, face);
8305 8066
8306 break; 8067 break;
8307 8068
@@ -8449,9 +8210,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8449 string primText = rules.GetLSLStringItem(idx++); 8210 string primText = rules.GetLSLStringItem(idx++);
8450 LSL_Vector primTextColor = rules.GetVector3Item(idx++); 8211 LSL_Vector primTextColor = rules.GetVector3Item(idx++);
8451 LSL_Float primTextAlpha = rules.GetLSLFloatItem(idx++); 8212 LSL_Float primTextAlpha = rules.GetLSLFloatItem(idx++);
8452 Vector3 av3 = new Vector3(Util.Clip((float)primTextColor.x, 0.0f, 1.0f), 8213 Vector3 av3 = Util.Clip(primTextColor, 0.0f, 1.0f);
8453 Util.Clip((float)primTextColor.y, 0.0f, 1.0f),
8454 Util.Clip((float)primTextColor.z, 0.0f, 1.0f));
8455 part.SetText(primText, av3, Util.Clip((float)primTextAlpha, 0.0f, 1.0f)); 8214 part.SetText(primText, av3, Util.Clip((float)primTextAlpha, 0.0f, 1.0f));
8456 8215
8457 break; 8216 break;
@@ -8470,8 +8229,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8470 case (int)ScriptBaseClass.PRIM_ROT_LOCAL: 8229 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
8471 if (remain < 1) 8230 if (remain < 1)
8472 return null; 8231 return null;
8473 LSL_Rotation lr = rules.GetQuaternionItem(idx++); 8232 SetRot(part, rules.GetQuaternionItem(idx++));
8474 SetRot(part, Rot2Quaternion(lr));
8475 break; 8233 break;
8476 case (int)ScriptBaseClass.PRIM_OMEGA: 8234 case (int)ScriptBaseClass.PRIM_OMEGA:
8477 if (remain < 3) 8235 if (remain < 3)
@@ -8481,7 +8239,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8481 LSL_Float gain = rules.GetLSLFloatItem(idx++); 8239 LSL_Float gain = rules.GetLSLFloatItem(idx++);
8482 TargetOmega(part, axis, (double)spinrate, (double)gain); 8240 TargetOmega(part, axis, (double)spinrate, (double)gain);
8483 break; 8241 break;
8484 8242 case (int)ScriptBaseClass.PRIM_SLICE:
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;
8485 case (int)ScriptBaseClass.PRIM_LINK_TARGET: 8248 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
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. 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.
8487 return null; 8250 return null;
@@ -8490,6 +8253,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8490 } 8253 }
8491 } 8254 }
8492 } 8255 }
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 }
8493 finally 8262 finally
8494 { 8263 {
8495 if (positionChanged) 8264 if (positionChanged)
@@ -8498,12 +8267,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8498 { 8267 {
8499 SceneObjectGroup parent = part.ParentGroup; 8268 SceneObjectGroup parent = part.ParentGroup;
8500 Util.FireAndForget(delegate(object x) { 8269 Util.FireAndForget(delegate(object x) {
8501 parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z)); 8270 parent.UpdateGroupPosition(currentPosition);
8502 }); 8271 });
8503 } 8272 }
8504 else 8273 else
8505 { 8274 {
8506 part.OffsetPosition = new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z); 8275 part.OffsetPosition = currentPosition;
8507 SceneObjectGroup parent = part.ParentGroup; 8276 SceneObjectGroup parent = part.ParentGroup;
8508 parent.HasGroupChanged = true; 8277 parent.HasGroupChanged = true;
8509 parent.ScheduleGroupForTerseUpdate(); 8278 parent.ScheduleGroupForTerseUpdate();
@@ -8792,7 +8561,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8792 // and standing avatar since server 1.36 8561 // and standing avatar since server 1.36
8793 LSL_Vector lower; 8562 LSL_Vector lower;
8794 LSL_Vector upper; 8563 LSL_Vector upper;
8795 if (presence.Animator.Animations.DefaultAnimation.AnimID 8564 if (presence.Animator.Animations.ImplicitDefaultAnimation.AnimID
8796 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) 8565 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
8797 { 8566 {
8798 // This is for ground sitting avatars 8567 // This is for ground sitting avatars
@@ -8881,7 +8650,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8881 public LSL_List llGetPrimitiveParams(LSL_List rules) 8650 public LSL_List llGetPrimitiveParams(LSL_List rules)
8882 { 8651 {
8883 m_host.AddScriptLPS(1); 8652 m_host.AddScriptLPS(1);
8884 return GetLinkPrimitiveParams(m_host, rules); 8653
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;
8885 } 8669 }
8886 8670
8887 public LSL_List llGetLinkPrimitiveParams(int linknumber, LSL_List rules) 8671 public LSL_List llGetLinkPrimitiveParams(int linknumber, LSL_List rules)
@@ -8891,294 +8675,39 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8891 // acording to SL wiki this must indicate a single link number or link_root or link_this. 8675 // acording to SL wiki this must indicate a single link number or link_root or link_this.
8892 // keep other options as before 8676 // keep other options as before
8893 8677
8894 List<SceneObjectPart> parts = GetLinkParts(linknumber); 8678 List<SceneObjectPart> parts;
8895 List<ScenePresence> avatars = GetLinkAvatars(linknumber); 8679 List<ScenePresence> avatars;
8896 8680
8897 LSL_List res = new LSL_List(); 8681 LSL_List res = new LSL_List();
8682 LSL_List remaining = null;
8898 8683
8899 if (parts.Count > 0) 8684 while (rules.Length > 0)
8900 { 8685 {
8901 foreach (var part in parts) 8686 parts = GetLinkParts(linknumber);
8687 avatars = GetLinkAvatars(linknumber);
8688
8689 remaining = null;
8690 foreach (SceneObjectPart part in parts)
8902 { 8691 {
8903 LSL_List partRes = GetLinkPrimitiveParams(part, rules); 8692 remaining = GetPrimParams(part, rules, ref res);
8904 res += partRes;
8905 } 8693 }
8906 }
8907 if (avatars.Count > 0)
8908 {
8909 foreach (ScenePresence avatar in avatars) 8694 foreach (ScenePresence avatar in avatars)
8910 { 8695 {
8911 LSL_List avaRes = GetLinkPrimitiveParams(avatar, rules); 8696 remaining = GetPrimParams(avatar, rules, ref res);
8912 res += avaRes;
8913 } 8697 }
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
8922 8698
8923 LSL_List res = new LSL_List(); 8699 if (remaining != null && remaining.Length > 0)
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)
8934 { 8700 {
8935 case (int)ScriptBaseClass.PRIM_MATERIAL: 8701 linknumber = remaining.GetLSLIntegerItem(0);
8936 res.Add(new LSL_Integer((int)SOPMaterialData.SopMaterial.Flesh)); 8702 rules = remaining.GetSublist(1, -1);
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;
9174 } 8703 }
9175 } 8704 }
8705
9176 return res; 8706 return res;
9177 } 8707 }
9178 8708
9179 public LSL_List GetLinkPrimitiveParams(SceneObjectPart part, LSL_List rules) 8709 public LSL_List GetPrimParams(SceneObjectPart part, LSL_List rules, ref LSL_List res)
9180 { 8710 {
9181 LSL_List res = new LSL_List();
9182 int idx=0; 8711 int idx=0;
9183 while (idx < rules.Length) 8712 while (idx < rules.Length)
9184 { 8713 {
@@ -9316,7 +8845,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9316 8845
9317 case (int)ScriptBaseClass.PRIM_TEXTURE: 8846 case (int)ScriptBaseClass.PRIM_TEXTURE:
9318 if (remain < 1) 8847 if (remain < 1)
9319 return res; 8848 return null;
9320 8849
9321 int face = (int)rules.GetLSLIntegerItem(idx++); 8850 int face = (int)rules.GetLSLIntegerItem(idx++);
9322 Primitive.TextureEntry tex = part.Shape.Textures; 8851 Primitive.TextureEntry tex = part.Shape.Textures;
@@ -9356,7 +8885,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9356 8885
9357 case (int)ScriptBaseClass.PRIM_COLOR: 8886 case (int)ScriptBaseClass.PRIM_COLOR:
9358 if (remain < 1) 8887 if (remain < 1)
9359 return res; 8888 return null;
9360 8889
9361 face=(int)rules.GetLSLIntegerItem(idx++); 8890 face=(int)rules.GetLSLIntegerItem(idx++);
9362 8891
@@ -9385,7 +8914,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9385 8914
9386 case (int)ScriptBaseClass.PRIM_BUMP_SHINY: 8915 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
9387 if (remain < 1) 8916 if (remain < 1)
9388 return res; 8917 return null;
8918
9389 face = (int)rules.GetLSLIntegerItem(idx++); 8919 face = (int)rules.GetLSLIntegerItem(idx++);
9390 8920
9391 tex = part.Shape.Textures; 8921 tex = part.Shape.Textures;
@@ -9441,7 +8971,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9441 8971
9442 case (int)ScriptBaseClass.PRIM_FULLBRIGHT: 8972 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
9443 if (remain < 1) 8973 if (remain < 1)
9444 return res; 8974 return null;
8975
9445 face = (int)rules.GetLSLIntegerItem(idx++); 8976 face = (int)rules.GetLSLIntegerItem(idx++);
9446 8977
9447 tex = part.Shape.Textures; 8978 tex = part.Shape.Textures;
@@ -9495,7 +9026,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9495 case (int)ScriptBaseClass.PRIM_TEXGEN: 9026 case (int)ScriptBaseClass.PRIM_TEXGEN:
9496 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR) 9027 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
9497 if (remain < 1) 9028 if (remain < 1)
9498 return res; 9029 return null;
9030
9499 face = (int)rules.GetLSLIntegerItem(idx++); 9031 face = (int)rules.GetLSLIntegerItem(idx++);
9500 9032
9501 tex = part.Shape.Textures; 9033 tex = part.Shape.Textures;
@@ -9543,7 +9075,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9543 9075
9544 case (int)ScriptBaseClass.PRIM_GLOW: 9076 case (int)ScriptBaseClass.PRIM_GLOW:
9545 if (remain < 1) 9077 if (remain < 1)
9546 return res; 9078 return null;
9079
9547 face = (int)rules.GetLSLIntegerItem(idx++); 9080 face = (int)rules.GetLSLIntegerItem(idx++);
9548 9081
9549 tex = part.Shape.Textures; 9082 tex = part.Shape.Textures;
@@ -9587,18 +9120,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9587 case (int)ScriptBaseClass.PRIM_POS_LOCAL: 9120 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
9588 res.Add(new LSL_Vector(GetPartLocalPos(part))); 9121 res.Add(new LSL_Vector(GetPartLocalPos(part)));
9589 break; 9122 break;
9590 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;
9591 case (int)ScriptBaseClass.PRIM_LINK_TARGET: 9132 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. 9133 if(remain < 3)
9593 return res; 9134 return null;
9594 LSL_Integer new_linknumber = rules.GetLSLIntegerItem(idx++); 9135
9595 LSL_List new_rules = rules.GetSublist(idx, -1); 9136 return rules.GetSublist(idx, -1);
9596 LSL_List tres = llGetLinkPrimitiveParams((int)new_linknumber, new_rules);
9597 res += tres;
9598 return res;
9599 } 9137 }
9600 } 9138 }
9601 return res; 9139
9140 return null;
9602 } 9141 }
9603 9142
9604 public LSL_List llGetPrimMediaParams(int face, LSL_List rules) 9143 public LSL_List llGetPrimMediaParams(int face, LSL_List rules)
@@ -10511,11 +10050,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10511 10050
10512 GridRegion info; 10051 GridRegion info;
10513 10052
10514 if (m_ScriptEngine.World.RegionInfo.RegionName == simulator) //Det data for this simulator? 10053 if (World.RegionInfo.RegionName == simulator)
10515 10054 info = new GridRegion(World.RegionInfo);
10516 info = new GridRegion(m_ScriptEngine.World.RegionInfo);
10517 else 10055 else
10518 info = m_ScriptEngine.World.GridService.GetRegionByName(m_ScriptEngine.World.RegionInfo.ScopeID, simulator); 10056 info = World.GridService.GetRegionByName(m_ScriptEngine.World.RegionInfo.ScopeID, simulator);
10519 10057
10520 switch (data) 10058 switch (data)
10521 { 10059 {
@@ -10525,9 +10063,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10525 ScriptSleep(1000); 10063 ScriptSleep(1000);
10526 return UUID.Zero.ToString(); 10064 return UUID.Zero.ToString();
10527 } 10065 }
10528 if (m_ScriptEngine.World.RegionInfo.RegionName != simulator) 10066
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)
10529 { 10083 {
10530 //Hypergrid Region co-ordinates
10531 uint rx = 0, ry = 0; 10084 uint rx = 0, ry = 0;
10532 Utils.LongToUInts(Convert.ToUInt64(info.RegionSecret), out rx, out ry); 10085 Utils.LongToUInts(Convert.ToUInt64(info.RegionSecret), out rx, out ry);
10533 10086
@@ -10538,7 +10091,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10538 } 10091 }
10539 else 10092 else
10540 { 10093 {
10541 //Local-cooridnates 10094 // Local grid co-oridnates
10542 reply = new LSL_Vector( 10095 reply = new LSL_Vector(
10543 info.RegionLocX, 10096 info.RegionLocX,
10544 info.RegionLocY, 10097 info.RegionLocY,
@@ -10992,20 +10545,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10992 switch ((ParcelMediaCommandEnum) Convert.ToInt32(aList.Data[i].ToString())) 10545 switch ((ParcelMediaCommandEnum) Convert.ToInt32(aList.Data[i].ToString()))
10993 { 10546 {
10994 case ParcelMediaCommandEnum.Url: 10547 case ParcelMediaCommandEnum.Url:
10995 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL)); 10548 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaURL));
10996 break; 10549 break;
10997 case ParcelMediaCommandEnum.Desc: 10550 case ParcelMediaCommandEnum.Desc:
10998 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).Description)); 10551 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).Description));
10999 break; 10552 break;
11000 case ParcelMediaCommandEnum.Texture: 10553 case ParcelMediaCommandEnum.Texture:
11001 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaID.ToString())); 10554 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaID.ToString()));
11002 break; 10555 break;
11003 case ParcelMediaCommandEnum.Type: 10556 case ParcelMediaCommandEnum.Type:
11004 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaType)); 10557 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaType));
11005 break; 10558 break;
11006 case ParcelMediaCommandEnum.Size: 10559 case ParcelMediaCommandEnum.Size:
11007 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaWidth)); 10560 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaWidth));
11008 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaHeight)); 10561 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaHeight));
11009 break; 10562 break;
11010 default: 10563 default:
11011 ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url; 10564 ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url;
@@ -11175,9 +10728,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11175 ScenePresence avatar = World.GetScenePresence(detectedParams.Key); 10728 ScenePresence avatar = World.GetScenePresence(detectedParams.Key);
11176 if (avatar != null) 10729 if (avatar != null)
11177 { 10730 {
11178 avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name, simname, 10731 avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name,
11179 new Vector3((float)pos.x, (float)pos.y, (float)pos.z), 10732 simname, pos, lookAt);
11180 new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z));
11181 } 10733 }
11182 10734
11183 ScriptSleep(1000); 10735 ScriptSleep(1000);
@@ -11362,31 +10914,30 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11362 public LSL_Float llListStatistics(int operation, LSL_List src) 10914 public LSL_Float llListStatistics(int operation, LSL_List src)
11363 { 10915 {
11364 m_host.AddScriptLPS(1); 10916 m_host.AddScriptLPS(1);
11365 LSL_List nums = LSL_List.ToDoubleList(src);
11366 switch (operation) 10917 switch (operation)
11367 { 10918 {
11368 case ScriptBaseClass.LIST_STAT_RANGE: 10919 case ScriptBaseClass.LIST_STAT_RANGE:
11369 return nums.Range(); 10920 return src.Range();
11370 case ScriptBaseClass.LIST_STAT_MIN: 10921 case ScriptBaseClass.LIST_STAT_MIN:
11371 return nums.Min(); 10922 return src.Min();
11372 case ScriptBaseClass.LIST_STAT_MAX: 10923 case ScriptBaseClass.LIST_STAT_MAX:
11373 return nums.Max(); 10924 return src.Max();
11374 case ScriptBaseClass.LIST_STAT_MEAN: 10925 case ScriptBaseClass.LIST_STAT_MEAN:
11375 return nums.Mean(); 10926 return src.Mean();
11376 case ScriptBaseClass.LIST_STAT_MEDIAN: 10927 case ScriptBaseClass.LIST_STAT_MEDIAN:
11377 return nums.Median(); 10928 return LSL_List.ToDoubleList(src).Median();
11378 case ScriptBaseClass.LIST_STAT_NUM_COUNT: 10929 case ScriptBaseClass.LIST_STAT_NUM_COUNT:
11379 return nums.NumericLength(); 10930 return src.NumericLength();
11380 case ScriptBaseClass.LIST_STAT_STD_DEV: 10931 case ScriptBaseClass.LIST_STAT_STD_DEV:
11381 return nums.StdDev(); 10932 return src.StdDev();
11382 case ScriptBaseClass.LIST_STAT_SUM: 10933 case ScriptBaseClass.LIST_STAT_SUM:
11383 return nums.Sum(); 10934 return src.Sum();
11384 case ScriptBaseClass.LIST_STAT_SUM_SQUARES: 10935 case ScriptBaseClass.LIST_STAT_SUM_SQUARES:
11385 return nums.SumSqrs(); 10936 return src.SumSqrs();
11386 case ScriptBaseClass.LIST_STAT_GEOMETRIC_MEAN: 10937 case ScriptBaseClass.LIST_STAT_GEOMETRIC_MEAN:
11387 return nums.GeometricMean(); 10938 return src.GeometricMean();
11388 case ScriptBaseClass.LIST_STAT_HARMONIC_MEAN: 10939 case ScriptBaseClass.LIST_STAT_HARMONIC_MEAN:
11389 return nums.HarmonicMean(); 10940 return src.HarmonicMean();
11390 default: 10941 default:
11391 return 0.0; 10942 return 0.0;
11392 } 10943 }
@@ -11744,7 +11295,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11744 public LSL_List llGetParcelDetails(LSL_Vector pos, LSL_List param) 11295 public LSL_List llGetParcelDetails(LSL_Vector pos, LSL_List param)
11745 { 11296 {
11746 m_host.AddScriptLPS(1); 11297 m_host.AddScriptLPS(1);
11747 LandData land = World.GetLandData((float)pos.x, (float)pos.y); 11298 LandData land = World.GetLandData(pos);
11748 if (land == null) 11299 if (land == null)
11749 { 11300 {
11750 return new LSL_List(0); 11301 return new LSL_List(0);
@@ -11912,13 +11463,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11912 else 11463 else
11913 rot = obj.GetWorldRotation(); 11464 rot = obj.GetWorldRotation();
11914 11465
11915 LSL_Rotation objrot = new LSL_Rotation(rot.X, rot.Y, rot.Z, rot.W); 11466 LSL_Rotation objrot = new LSL_Rotation(rot);
11916 ret.Add(objrot); 11467 ret.Add(objrot);
11917 } 11468 }
11918 break; 11469 break;
11919 case ScriptBaseClass.OBJECT_VELOCITY: 11470 case ScriptBaseClass.OBJECT_VELOCITY:
11920 Vector3 ovel = obj.Velocity; 11471 ret.Add(new LSL_Vector(obj.Velocity));
11921 ret.Add(new LSL_Vector(ovel.X, ovel.Y, ovel.Z));
11922 break; 11472 break;
11923 case ScriptBaseClass.OBJECT_OWNER: 11473 case ScriptBaseClass.OBJECT_OWNER:
11924 ret.Add(new LSL_String(obj.OwnerID.ToString())); 11474 ret.Add(new LSL_String(obj.OwnerID.ToString()));
@@ -12005,12 +11555,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12005 11555
12006 internal void Deprecated(string command) 11556 internal void Deprecated(string command)
12007 { 11557 {
12008 throw new Exception("Command deprecated: " + command); 11558 throw new ScriptException("Command deprecated: " + command);
12009 } 11559 }
12010 11560
12011 internal void LSLError(string msg) 11561 internal void LSLError(string msg)
12012 { 11562 {
12013 throw new Exception("LSL Runtime Error: " + msg); 11563 throw new ScriptException("LSL Runtime Error: " + msg);
12014 } 11564 }
12015 11565
12016 public delegate void AssetRequestCallback(UUID assetID, AssetBase asset); 11566 public delegate void AssetRequestCallback(UUID assetID, AssetBase asset);
@@ -12131,7 +11681,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12131 return tid.ToString(); 11681 return tid.ToString();
12132 } 11682 }
12133 11683
12134 public void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules) 11684 public void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules, string originFunc)
12135 { 11685 {
12136 SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim)); 11686 SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim));
12137 if (obj == null) 11687 if (obj == null)
@@ -12140,28 +11690,41 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12140 if (obj.OwnerID != m_host.OwnerID) 11690 if (obj.OwnerID != m_host.OwnerID)
12141 return; 11691 return;
12142 11692
12143 LSL_List remaining = SetPrimParams(obj, rules); 11693 uint rulesParsed = 0;
11694 LSL_List remaining = SetPrimParams(obj, rules, originFunc, ref rulesParsed);
12144 11695
12145 while ((object)remaining != null && remaining.Length > 2) 11696 while ((object)remaining != null && remaining.Length > 2)
12146 { 11697 {
12147 LSL_Integer newLink = remaining.GetLSLIntegerItem(0); 11698 LSL_Integer newLink = remaining.GetLSLIntegerItem(0);
12148 LSL_List newrules = remaining.GetSublist(1, -1); 11699 LSL_List newrules = remaining.GetSublist(1, -1);
12149 foreach(SceneObjectPart part in GetLinkParts(obj, newLink)){ 11700 foreach(SceneObjectPart part in GetLinkParts(obj, newLink)){
12150 remaining = SetPrimParams(part, newrules); 11701 remaining = SetPrimParams(part, newrules, originFunc, ref rulesParsed);
12151 } 11702 }
12152 } 11703 }
12153 } 11704 }
12154 11705
12155 public LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules) 11706 public LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules)
12156 { 11707 {
12157 SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim)); 11708 SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim));
12158 if (obj == null)
12159 return new LSL_List();
12160 11709
12161 if (obj.OwnerID != m_host.OwnerID) 11710 LSL_List result = new LSL_List();
12162 return new LSL_List();
12163 11711
12164 return GetLinkPrimitiveParams(obj, rules); 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
11727 return result;
12165 } 11728 }
12166 11729
12167 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link) 11730 public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link)
@@ -12524,8 +12087,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12524 12087
12525 m_host.AddScriptLPS(1); 12088 m_host.AddScriptLPS(1);
12526 12089
12527 Vector3 rayStart = new Vector3((float)start.x, (float)start.y, (float)start.z); 12090 Vector3 rayStart = start;
12528 Vector3 rayEnd = new Vector3((float)end.x, (float)end.y, (float)end.z); 12091 Vector3 rayEnd = end;
12529 Vector3 dir = rayEnd - rayStart; 12092 Vector3 dir = rayEnd - rayStart;
12530 12093
12531 float dist = Vector3.Mag(dir); 12094 float dist = Vector3.Mag(dir);
@@ -13099,6 +12662,455 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13099 } 12662 }
13100 } 12663 }
13101 } 12664 }
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 }
13102 } 13114 }
13103 13115
13104 public class NotecardCache 13116 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 795de80..ceb4660 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 = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); 307 wl.cloudDetailXYDensity = iV;
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 = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); 332 wl.cloudXYDensity = iV;
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 = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); 387 wl.reflectionWaveletScale = iV;
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 = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); 425 wl.waterColor = iV;
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 7844c75..8f34833 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 Exception("MOD Runtime Error: " + msg); 98 throw new ScriptException("MOD Runtime Error: " + msg);
99 } 99 }
100 100
101 // 101 /// <summary>
102 //Dumps an error message on the debug console. 102 /// Dumps an error message on the debug console.
103 // 103 /// </summary>
104 104 /// <param name='message'></param>
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]); 257 convertedParms[i] = ConvertFromLSL(parms[i],signature[i], fname);
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) 297 protected object ConvertFromLSL(object lslparm, Type type, string fname)
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)) 313 if (type == typeof(int) || type == typeof(float))
314 return (int)(LSL_Integer)lslparm; 314 return (int)(LSL_Integer)lslparm;
315 } 315 }
316 316
@@ -333,8 +333,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
333 { 333 {
334 if (type == typeof(OpenMetaverse.Quaternion)) 334 if (type == typeof(OpenMetaverse.Quaternion))
335 { 335 {
336 LSL_Rotation rot = (LSL_Rotation)lslparm; 336 return (OpenMetaverse.Quaternion)((LSL_Rotation)lslparm);
337 return new OpenMetaverse.Quaternion((float)rot.x,(float)rot.y,(float)rot.z,(float)rot.s);
338 } 337 }
339 } 338 }
340 339
@@ -343,8 +342,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
343 { 342 {
344 if (type == typeof(OpenMetaverse.Vector3)) 343 if (type == typeof(OpenMetaverse.Vector3))
345 { 344 {
346 LSL_Vector vect = (LSL_Vector)lslparm; 345 return (OpenMetaverse.Vector3)((LSL_Vector)lslparm);
347 return new OpenMetaverse.Vector3((float)vect.x,(float)vect.y,(float)vect.z);
348 } 346 }
349 } 347 }
350 348
@@ -361,29 +359,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
361 result[i] = (string)(LSL_String)plist[i]; 359 result[i] = (string)(LSL_String)plist[i];
362 else if (plist[i] is LSL_Integer) 360 else if (plist[i] is LSL_Integer)
363 result[i] = (int)(LSL_Integer)plist[i]; 361 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];
364 else if (plist[i] is LSL_Float) 366 else if (plist[i] is LSL_Float)
365 result[i] = (float)(LSL_Float)plist[i]; 367 result[i] = (float)(LSL_Float)plist[i];
366 else if (plist[i] is LSL_Key) 368 else if (plist[i] is LSL_Key)
367 result[i] = new UUID((LSL_Key)plist[i]); 369 result[i] = new UUID((LSL_Key)plist[i]);
368 else if (plist[i] is LSL_Rotation) 370 else if (plist[i] is LSL_Rotation)
369 { 371 result[i] = (Quaternion)((LSL_Rotation)plist[i]);
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 }
373 else if (plist[i] is LSL_Vector) 372 else if (plist[i] is LSL_Vector)
374 { 373 result[i] = (Vector3)((LSL_Vector)plist[i]);
375 LSL_Vector vect = (LSL_Vector)plist[i];
376 result[i] = new OpenMetaverse.Vector3((float)vect.x,(float)vect.y,(float)vect.z);
377 }
378 else 374 else
379 MODError("unknown LSL list element type"); 375 MODError(String.Format("{0}: unknown LSL list element type", fname));
380 } 376 }
381 377
382 return result; 378 return result;
383 } 379 }
384 } 380 }
385 381
386 MODError(String.Format("parameter type mismatch; expecting {0}",type.Name)); 382 MODError(String.Format("{1}: parameter type mismatch; expecting {0}",type.Name, fname));
387 return null; 383 return null;
388 } 384 }
389 385
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 80111f9..51c8c7e 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -141,6 +141,8 @@ 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
144 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) 146 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item)
145 { 147 {
146 m_ScriptEngine = ScriptEngine; 148 m_ScriptEngine = ScriptEngine;
@@ -148,6 +150,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
148 m_item = item; 150 m_item = item;
149 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false); 151 m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false);
150 152
153 m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>();
154
151 if (m_ScriptEngine.Config.GetBoolean("AllowOSFunctions", false)) 155 if (m_ScriptEngine.Config.GetBoolean("AllowOSFunctions", false))
152 m_OSFunctionsEnabled = true; 156 m_OSFunctionsEnabled = true;
153 157
@@ -214,7 +218,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
214 } 218 }
215 else 219 else
216 { 220 {
217 throw new Exception("OSSL Runtime Error: " + msg); 221 throw new ScriptException("OSSL Runtime Error: " + msg);
218 } 222 }
219 } 223 }
220 224
@@ -782,10 +786,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
782 786
783 // We will launch the teleport on a new thread so that when the script threads are terminated 787 // We will launch the teleport on a new thread so that when the script threads are terminated
784 // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting. 788 // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting.
785 Util.FireAndForget( 789 Util.FireAndForget(o => World.RequestTeleportLocation(
786 o => World.RequestTeleportLocation(presence.ControllingClient, regionName, 790 presence.ControllingClient, regionName, position,
787 new Vector3((float)position.x, (float)position.y, (float)position.z), 791 lookat, (uint)TPFlags.ViaLocation));
788 new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation));
789 792
790 ScriptSleep(5000); 793 ScriptSleep(5000);
791 794
@@ -828,10 +831,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
828 831
829 // We will launch the teleport on a new thread so that when the script threads are terminated 832 // We will launch the teleport on a new thread so that when the script threads are terminated
830 // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting. 833 // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting.
831 Util.FireAndForget( 834 Util.FireAndForget(o => World.RequestTeleportLocation(
832 o => World.RequestTeleportLocation(presence.ControllingClient, regionHandle, 835 presence.ControllingClient, regionHandle,
833 new Vector3((float)position.x, (float)position.y, (float)position.z), 836 position, lookat, (uint)TPFlags.ViaLocation));
834 new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation));
835 837
836 ScriptSleep(5000); 838 ScriptSleep(5000);
837 839
@@ -1680,6 +1682,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1680 return; 1682 return;
1681 } 1683 }
1682 1684
1685 MessageObject(objUUID, message);
1686 }
1687
1688 private void MessageObject(UUID objUUID, string message)
1689 {
1683 object[] resobj = new object[] { new LSL_Types.LSLString(m_host.UUID.ToString()), new LSL_Types.LSLString(message) }; 1690 object[] resobj = new object[] { new LSL_Types.LSLString(m_host.UUID.ToString()), new LSL_Types.LSLString(message) };
1684 1691
1685 SceneObjectPart sceneOP = World.GetSceneObjectPart(objUUID); 1692 SceneObjectPart sceneOP = World.GetSceneObjectPart(objUUID);
@@ -1782,18 +1789,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1782 protected string LoadNotecard(string notecardNameOrUuid) 1789 protected string LoadNotecard(string notecardNameOrUuid)
1783 { 1790 {
1784 UUID assetID = CacheNotecard(notecardNameOrUuid); 1791 UUID assetID = CacheNotecard(notecardNameOrUuid);
1785 StringBuilder notecardData = new StringBuilder();
1786 1792
1787 for (int count = 0; count < NotecardCache.GetLines(assetID); count++) 1793 if (assetID != UUID.Zero)
1788 { 1794 {
1789 string line = NotecardCache.GetLine(assetID, count) + "\n"; 1795 StringBuilder notecardData = new StringBuilder();
1790 1796
1791// m_log.DebugFormat("[OSSL]: From notecard {0} loading line {1}", notecardNameOrUuid, line); 1797 for (int count = 0; count < NotecardCache.GetLines(assetID); count++)
1792 1798 {
1793 notecardData.Append(line); 1799 string line = NotecardCache.GetLine(assetID, count) + "\n";
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();
1794 } 1807 }
1795 1808
1796 return notecardData.ToString(); 1809 return null;
1797 } 1810 }
1798 1811
1799 /// <summary> 1812 /// <summary>
@@ -2259,11 +2272,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2259 CheckThreatLevel(ThreatLevel.High, "osGetLinkPrimitiveParams"); 2272 CheckThreatLevel(ThreatLevel.High, "osGetLinkPrimitiveParams");
2260 m_host.AddScriptLPS(1); 2273 m_host.AddScriptLPS(1);
2261 InitLSL(); 2274 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;
2262 LSL_List retVal = new LSL_List(); 2278 LSL_List retVal = new LSL_List();
2263 List<SceneObjectPart> parts = ((LSL_Api)m_LSL_Api).GetLinkParts(linknumber); 2279 LSL_List remaining = null;
2280 List<SceneObjectPart> parts = LSL_Api.GetLinkParts(linknumber);
2264 foreach (SceneObjectPart part in parts) 2281 foreach (SceneObjectPart part in parts)
2265 { 2282 {
2266 retVal += ((LSL_Api)m_LSL_Api).GetLinkPrimitiveParams(part, rules); 2283 remaining = LSL_Api.GetPrimParams(part, rules, ref retVal);
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);
2267 } 2294 }
2268 return retVal; 2295 return retVal;
2269 } 2296 }
@@ -2352,17 +2379,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2352 return UUID.Zero.ToString(); 2379 return UUID.Zero.ToString();
2353 } 2380 }
2354 } 2381 }
2382 else
2383 {
2384 OSSLError(string.Format("osNpcCreate: Notecard reference '{0}' not found.", notecard));
2385 }
2355 } 2386 }
2356 2387
2357 if (appearance == null)
2358 return new LSL_Key(UUID.Zero.ToString());
2359
2360 UUID ownerID = UUID.Zero; 2388 UUID ownerID = UUID.Zero;
2361 if (owned) 2389 if (owned)
2362 ownerID = m_host.OwnerID; 2390 ownerID = m_host.OwnerID;
2363 UUID x = module.CreateNPC(firstname, 2391 UUID x = module.CreateNPC(firstname,
2364 lastname, 2392 lastname,
2365 new Vector3((float) position.x, (float) position.y, (float) position.z), 2393 position,
2366 ownerID, 2394 ownerID,
2367 senseAsAgent, 2395 senseAsAgent,
2368 World, 2396 World,
@@ -2425,6 +2453,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2425 return; 2453 return;
2426 2454
2427 string appearanceSerialized = LoadNotecard(notecard); 2455 string appearanceSerialized = LoadNotecard(notecard);
2456
2457 if (appearanceSerialized == null)
2458 OSSLError(string.Format("osNpcCreate: Notecard reference '{0}' not found.", notecard));
2459
2428 OSDMap appearanceOsd = (OSDMap)OSDParser.DeserializeLLSDXml(appearanceSerialized); 2460 OSDMap appearanceOsd = (OSDMap)OSDParser.DeserializeLLSDXml(appearanceSerialized);
2429// OSD a = OSDParser.DeserializeLLSDXml(appearanceSerialized); 2461// OSD a = OSDParser.DeserializeLLSDXml(appearanceSerialized);
2430// Console.WriteLine("appearanceSerialized {0}", appearanceSerialized); 2462// Console.WriteLine("appearanceSerialized {0}", appearanceSerialized);
@@ -2485,7 +2517,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2485 return new LSL_Vector(0, 0, 0); 2517 return new LSL_Vector(0, 0, 0);
2486 } 2518 }
2487 2519
2488 public void osNpcMoveTo(LSL_Key npc, LSL_Vector position) 2520 public void osNpcMoveTo(LSL_Key npc, LSL_Vector pos)
2489 { 2521 {
2490 CheckThreatLevel(ThreatLevel.High, "osNpcMoveTo"); 2522 CheckThreatLevel(ThreatLevel.High, "osNpcMoveTo");
2491 m_host.AddScriptLPS(1); 2523 m_host.AddScriptLPS(1);
@@ -2500,7 +2532,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2500 if (!module.CheckPermissions(npcId, m_host.OwnerID)) 2532 if (!module.CheckPermissions(npcId, m_host.OwnerID))
2501 return; 2533 return;
2502 2534
2503 Vector3 pos = new Vector3((float) position.x, (float) position.y, (float) position.z);
2504 module.MoveToTarget(npcId, World, pos, false, true, false); 2535 module.MoveToTarget(npcId, World, pos, false, true, false);
2505 } 2536 }
2506 } 2537 }
@@ -2520,11 +2551,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2520 if (!module.CheckPermissions(npcId, m_host.OwnerID)) 2551 if (!module.CheckPermissions(npcId, m_host.OwnerID))
2521 return; 2552 return;
2522 2553
2523 Vector3 pos = new Vector3((float)target.x, (float)target.y, (float)target.z);
2524 module.MoveToTarget( 2554 module.MoveToTarget(
2525 new UUID(npc.m_string), 2555 new UUID(npc.m_string),
2526 World, 2556 World,
2527 pos, 2557 target,
2528 (options & ScriptBaseClass.OS_NPC_NO_FLY) != 0, 2558 (options & ScriptBaseClass.OS_NPC_NO_FLY) != 0,
2529 (options & ScriptBaseClass.OS_NPC_LAND_AT_TARGET) != 0, 2559 (options & ScriptBaseClass.OS_NPC_LAND_AT_TARGET) != 0,
2530 (options & ScriptBaseClass.OS_NPC_RUNNING) != 0); 2560 (options & ScriptBaseClass.OS_NPC_RUNNING) != 0);
@@ -2576,7 +2606,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2576 ScenePresence sp = World.GetScenePresence(npcId); 2606 ScenePresence sp = World.GetScenePresence(npcId);
2577 2607
2578 if (sp != null) 2608 if (sp != null)
2579 sp.Rotation = LSL_Api.Rot2Quaternion(rotation); 2609 sp.Rotation = rotation;
2580 } 2610 }
2581 } 2611 }
2582 2612
@@ -2936,7 +2966,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2936 avatar.SpeedModifier = (float)SpeedModifier; 2966 avatar.SpeedModifier = (float)SpeedModifier;
2937 } 2967 }
2938 2968
2939 public void osKickAvatar(string FirstName,string SurName,string alert) 2969 public void osKickAvatar(string FirstName, string SurName, string alert)
2940 { 2970 {
2941 CheckThreatLevel(ThreatLevel.Severe, "osKickAvatar"); 2971 CheckThreatLevel(ThreatLevel.Severe, "osKickAvatar");
2942 m_host.AddScriptLPS(1); 2972 m_host.AddScriptLPS(1);
@@ -2950,10 +2980,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2950 sp.ControllingClient.Kick(alert); 2980 sp.ControllingClient.Kick(alert);
2951 2981
2952 // ...and close on our side 2982 // ...and close on our side
2953 sp.Scene.IncomingCloseAgent(sp.UUID); 2983 sp.Scene.IncomingCloseAgent(sp.UUID, false);
2954 } 2984 }
2955 }); 2985 });
2956 } 2986 }
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 }
2957 2998
2958 public void osCauseDamage(string avatar, double damage) 2999 public void osCauseDamage(string avatar, double damage)
2959 { 3000 {
@@ -2966,7 +3007,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2966 ScenePresence presence = World.GetScenePresence(avatarId); 3007 ScenePresence presence = World.GetScenePresence(avatarId);
2967 if (presence != null) 3008 if (presence != null)
2968 { 3009 {
2969 LandData land = World.GetLandData((float)pos.X, (float)pos.Y); 3010 LandData land = World.GetLandData(pos);
2970 if ((land.Flags & (uint)ParcelFlags.AllowDamage) == (uint)ParcelFlags.AllowDamage) 3011 if ((land.Flags & (uint)ParcelFlags.AllowDamage) == (uint)ParcelFlags.AllowDamage)
2971 { 3012 {
2972 float health = presence.Health; 3013 float health = presence.Health;
@@ -3013,7 +3054,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3013 m_host.AddScriptLPS(1); 3054 m_host.AddScriptLPS(1);
3014 InitLSL(); 3055 InitLSL();
3015 3056
3016 return m_LSL_Api.GetLinkPrimitiveParamsEx(prim, rules); 3057 return m_LSL_Api.GetPrimitiveParamsEx(prim, rules);
3017 } 3058 }
3018 3059
3019 public void osSetPrimitiveParams(LSL_Key prim, LSL_List rules) 3060 public void osSetPrimitiveParams(LSL_Key prim, LSL_List rules)
@@ -3022,7 +3063,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3022 m_host.AddScriptLPS(1); 3063 m_host.AddScriptLPS(1);
3023 InitLSL(); 3064 InitLSL();
3024 3065
3025 m_LSL_Api.SetPrimitiveParamsEx(prim, rules); 3066 m_LSL_Api.SetPrimitiveParamsEx(prim, rules, "osSetPrimitiveParams");
3026 } 3067 }
3027 3068
3028 /// <summary> 3069 /// <summary>
@@ -3254,6 +3295,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3254 } 3295 }
3255 } 3296 }
3256 3297
3298 #region Attachment commands
3299
3257 public void osForceAttachToAvatar(int attachmentPoint) 3300 public void osForceAttachToAvatar(int attachmentPoint)
3258 { 3301 {
3259 CheckThreatLevel(ThreatLevel.High, "osForceAttachToAvatar"); 3302 CheckThreatLevel(ThreatLevel.High, "osForceAttachToAvatar");
@@ -3343,6 +3386,175 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3343 ((LSL_Api)m_LSL_Api).DetachFromAvatar(); 3386 ((LSL_Api)m_LSL_Api).DetachFromAvatar();
3344 } 3387 }
3345 3388
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
3346 /// <summary> 3558 /// <summary>
3347 /// Checks if thing is a UUID. 3559 /// Checks if thing is a UUID.
3348 /// </summary> 3560 /// </summary>
@@ -3392,5 +3604,166 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3392 3604
3393 return new LSL_Key(m_host.ParentGroup.FromPartID.ToString()); 3605 return new LSL_Key(m_host.ParentGroup.FromPartID.ToString());
3394 } 3606 }
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 }
3395 } 3768 }
3396} 3769}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
index 678f9d5..4dd795d 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.X, q.Y, q.Z, q.W); 355 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q);
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,9 +429,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
429 try 429 try
430 { 430 {
431 Vector3 diff = toRegionPos - fromRegionPos; 431 Vector3 diff = toRegionPos - fromRegionPos;
432 LSL_Types.Vector3 obj_dir = new LSL_Types.Vector3(diff.X, diff.Y, diff.Z); 432 double dot = LSL_Types.Vector3.Dot(forward_dir, diff);
433 double dot = LSL_Types.Vector3.Dot(forward_dir, obj_dir); 433 double mag_obj = LSL_Types.Vector3.Mag(diff);
434 double mag_obj = LSL_Types.Vector3.Mag(obj_dir);
435 ang_obj = Math.Acos(dot / (mag_fwd * mag_obj)); 434 ang_obj = Math.Acos(dot / (mag_fwd * mag_obj));
436 } 435 }
437 catch 436 catch
@@ -483,7 +482,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
483 q = avatar.Rotation; 482 q = avatar.Rotation;
484 } 483 }
485 484
486 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); 485 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q);
487 LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r); 486 LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r);
488 double mag_fwd = LSL_Types.Vector3.Mag(forward_dir); 487 double mag_fwd = LSL_Types.Vector3.Mag(forward_dir);
489 bool attached = (SensePoint.ParentGroup.AttachmentPoint != 0); 488 bool attached = (SensePoint.ParentGroup.AttachmentPoint != 0);
@@ -564,8 +563,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
564 double ang_obj = 0; 563 double ang_obj = 0;
565 try 564 try
566 { 565 {
567 Vector3 diff = toRegionPos - fromRegionPos; 566 LSL_Types.Vector3 obj_dir = new LSL_Types.Vector3(
568 LSL_Types.Vector3 obj_dir = new LSL_Types.Vector3(diff.X, diff.Y, diff.Z); 567 toRegionPos - fromRegionPos);
569 double dot = LSL_Types.Vector3.Dot(forward_dir, obj_dir); 568 double dot = LSL_Types.Vector3.Dot(forward_dir, obj_dir);
570 double mag_obj = LSL_Types.Vector3.Mag(obj_dir); 569 double mag_obj = LSL_Types.Vector3.Mag(obj_dir);
571 ang_obj = Math.Acos(dot / (mag_fwd * mag_obj)); 570 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 af35258..05c20f9 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); 432 void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules, string originFunc);
433 LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules);
434 void llSetKeyframedMotion(LSL_List frames, LSL_List options); 433 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 8c34ed3..c447d1f 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
@@ -40,16 +40,75 @@ 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>
43 public enum ThreatLevel 51 public enum ThreatLevel
44 { 52 {
53 // Not documented, presumably means permanently disabled ?
45 NoAccess = -1, 54 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>
46 None = 0, 60 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>
47 Nuisance = 1, 66 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>
48 VeryLow = 2, 73 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>
49 Low = 3, 80 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>
50 Moderate = 4, 87 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>
51 High = 5, 96 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>
52 VeryHigh = 6, 104 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>
53 Severe = 7 112 Severe = 7
54 }; 113 };
55 114
@@ -98,7 +157,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
98 void osAvatarPlayAnimation(string avatar, string animation); 157 void osAvatarPlayAnimation(string avatar, string animation);
99 void osAvatarStopAnimation(string avatar, string animation); 158 void osAvatarStopAnimation(string avatar, string animation);
100 159
101 // Attachment commands 160 #region Attachment commands
102 161
103 /// <summary> 162 /// <summary>
104 /// Attach the object containing this script to the avatar that owns it without asking for PERMISSION_ATTACH 163 /// Attach the object containing this script to the avatar that owns it without asking for PERMISSION_ATTACH
@@ -133,6 +192,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
133 /// <remarks>Nothing happens if the object is not attached.</remarks> 192 /// <remarks>Nothing happens if the object is not attached.</remarks>
134 void osForceDetachFromAvatar(); 193 void osForceDetachFromAvatar();
135 194
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
136 //texture draw functions 218 //texture draw functions
137 string osMovePen(string drawList, int x, int y); 219 string osMovePen(string drawList, int x, int y);
138 string osDrawLine(string drawList, int startX, int startY, int endX, int endY); 220 string osDrawLine(string drawList, int startX, int startY, int endX, int endY);
@@ -258,6 +340,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
258 int osGetSimulatorMemory(); 340 int osGetSimulatorMemory();
259 void osKickAvatar(string FirstName,string SurName,string alert); 341 void osKickAvatar(string FirstName,string SurName,string alert);
260 void osSetSpeed(string UUID, LSL_Float SpeedModifier); 342 void osSetSpeed(string UUID, LSL_Float SpeedModifier);
343 LSL_Float osGetHealth(string avatar);
261 void osCauseHealing(string avatar, double healing); 344 void osCauseHealing(string avatar, double healing);
262 void osCauseDamage(string avatar, double damage); 345 void osCauseDamage(string avatar, double damage);
263 LSL_List osGetPrimitiveParams(LSL_Key prim, LSL_List rules); 346 LSL_List osGetPrimitiveParams(LSL_Key prim, LSL_List rules);
@@ -305,5 +388,59 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
305 /// </summary> 388 /// </summary>
306 /// <returns>Rezzing object key or NULL_KEY if rezzed by agent or otherwise unknown.</returns> 389 /// <returns>Rezzing object key or NULL_KEY if rezzed by agent or otherwise unknown.</returns>
307 LSL_Key osGetRezzingObject(); 390 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);
308 } 445 }
309} 446}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
index f989cc6..0dd5a57 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
@@ -237,6 +237,58 @@ 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
240 public const int LAND_LEVEL = 0; 292 public const int LAND_LEVEL = 0;
241 public const int LAND_RAISE = 1; 293 public const int LAND_RAISE = 1;
242 public const int LAND_LOWER = 2; 294 public const int LAND_LOWER = 2;
@@ -329,6 +381,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
329 public const int PRIM_OMEGA = 32; 381 public const int PRIM_OMEGA = 32;
330 public const int PRIM_POS_LOCAL = 33; 382 public const int PRIM_POS_LOCAL = 33;
331 public const int PRIM_LINK_TARGET = 34; 383 public const int PRIM_LINK_TARGET = 34;
384 public const int PRIM_SLICE = 35;
332 public const int PRIM_TEXGEN_DEFAULT = 0; 385 public const int PRIM_TEXGEN_DEFAULT = 0;
333 public const int PRIM_TEXGEN_PLANAR = 1; 386 public const int PRIM_TEXGEN_PLANAR = 1;
334 387
@@ -560,6 +613,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
560 public const int CLICK_ACTION_OPEN = 4; 613 public const int CLICK_ACTION_OPEN = 4;
561 public const int CLICK_ACTION_PLAY = 5; 614 public const int CLICK_ACTION_PLAY = 5;
562 public const int CLICK_ACTION_OPEN_MEDIA = 6; 615 public const int CLICK_ACTION_OPEN_MEDIA = 6;
616 public const int CLICK_ACTION_ZOOM = 7;
563 617
564 // constants for the llDetectedTouch* functions 618 // constants for the llDetectedTouch* functions
565 public const int TOUCH_INVALID_FACE = -1; 619 public const int TOUCH_INVALID_FACE = -1;
@@ -687,5 +741,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
687 public const int KFM_CMD_PLAY = 0; 741 public const int KFM_CMD_PLAY = 0;
688 public const int KFM_CMD_STOP = 1; 742 public const int KFM_CMD_STOP = 1;
689 public const int KFM_CMD_PAUSE = 2; 743 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;
690 } 754 }
691} 755}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
index 94405d2..afa9ae0 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 // Avatar functions 292 #region Attachment commands
293 293
294 public void osForceAttachToAvatar(int attachmentPoint) 294 public void osForceAttachToAvatar(int attachmentPoint)
295 { 295 {
@@ -311,6 +311,18 @@ 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
314 // Texture Draw functions 326 // Texture Draw functions
315 327
316 public string osMovePen(string drawList, int x, int y) 328 public string osMovePen(string drawList, int x, int y)
@@ -865,7 +877,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
865 { 877 {
866 m_OSSL_Functions.osSetSpeed(UUID, SpeedModifier); 878 m_OSSL_Functions.osSetSpeed(UUID, SpeedModifier);
867 } 879 }
868 880
881 public LSL_Float osGetHealth(string avatar)
882 {
883 return m_OSSL_Functions.osGetHealth(avatar);
884 }
885
869 public void osCauseDamage(string avatar, double damage) 886 public void osCauseDamage(string avatar, double damage)
870 { 887 {
871 m_OSSL_Functions.osCauseDamage(avatar, damage); 888 m_OSSL_Functions.osCauseDamage(avatar, damage);
@@ -950,5 +967,40 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
950 { 967 {
951 return m_OSSL_Functions.osGetRezzingObject(); 968 return m_OSSL_Functions.osGetRezzingObject();
952 } 969 }
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 }
953 } 1005 }
954} 1006}
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
index 17a0d69..03be2ab 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
@@ -546,6 +546,8 @@ 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"));
549 551
550 if (lang == enumCompileType.yp) 552 if (lang == enumCompileType.yp)
551 { 553 {
diff --git a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
index 9e5fb24..22804f5 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.X, value.STCoord.Y, value.STCoord.Z); 167 touchST = new LSL_Types.Vector3(value.STCoord);
168 touchUV = new LSL_Types.Vector3(value.UVCoord.X, value.UVCoord.Y, value.UVCoord.Z); 168 touchUV = new LSL_Types.Vector3(value.UVCoord);
169 touchNormal = new LSL_Types.Vector3(value.Normal.X, value.Normal.Y, value.Normal.Z); 169 touchNormal = new LSL_Types.Vector3(value.Normal);
170 touchBinormal = new LSL_Types.Vector3(value.Binormal.X, value.Binormal.Y, value.Binormal.Z); 170 touchBinormal = new LSL_Types.Vector3(value.Binormal);
171 touchPos = new LSL_Types.Vector3(value.Position.X, value.Position.Y, value.Position.Z); 171 touchPos = new LSL_Types.Vector3(value.Position);
172 touchFace = value.FaceIndex; 172 touchFace = value.FaceIndex;
173 } 173 }
174 } 174 }
@@ -189,19 +189,13 @@ 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( 192 Position = new LSL_Types.Vector3(presence.AbsolutePosition);
193 presence.AbsolutePosition.X,
194 presence.AbsolutePosition.Y,
195 presence.AbsolutePosition.Z);
196 Rotation = new LSL_Types.Quaternion( 193 Rotation = new LSL_Types.Quaternion(
197 presence.Rotation.X, 194 presence.Rotation.X,
198 presence.Rotation.Y, 195 presence.Rotation.Y,
199 presence.Rotation.Z, 196 presence.Rotation.Z,
200 presence.Rotation.W); 197 presence.Rotation.W);
201 Velocity = new LSL_Types.Vector3( 198 Velocity = new LSL_Types.Vector3(presence.Velocity);
202 presence.Velocity.X,
203 presence.Velocity.Y,
204 presence.Velocity.Z);
205 199
206 Type = 0x01; // Avatar 200 Type = 0x01; // Avatar
207 if (presence.PresenceType == PresenceType.Npc) 201 if (presence.PresenceType == PresenceType.Npc)
@@ -254,16 +248,12 @@ namespace OpenSim.Region.ScriptEngine.Shared
254 } 248 }
255 } 249 }
256 250
257 Position = new LSL_Types.Vector3(part.AbsolutePosition.X, 251 Position = new LSL_Types.Vector3(part.AbsolutePosition);
258 part.AbsolutePosition.Y,
259 part.AbsolutePosition.Z);
260 252
261 Quaternion wr = part.ParentGroup.GroupRotation; 253 Quaternion wr = part.ParentGroup.GroupRotation;
262 Rotation = new LSL_Types.Quaternion(wr.X, wr.Y, wr.Z, wr.W); 254 Rotation = new LSL_Types.Quaternion(wr.X, wr.Y, wr.Z, wr.W);
263 255
264 Velocity = new LSL_Types.Vector3(part.Velocity.X, 256 Velocity = new LSL_Types.Vector3(part.Velocity);
265 part.Velocity.Y,
266 part.Velocity.Z);
267 } 257 }
268 } 258 }
269 259
diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
index 8adf4c5..c9c4753 100644
--- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
@@ -31,6 +31,11 @@ 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
34namespace OpenSim.Region.ScriptEngine.Shared 39namespace OpenSim.Region.ScriptEngine.Shared
35{ 40{
36 [Serializable] 41 [Serializable]
@@ -54,6 +59,20 @@ namespace OpenSim.Region.ScriptEngine.Shared
54 z = (float)vector.z; 59 z = (float)vector.z;
55 } 60 }
56 61
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
57 public Vector3(double X, double Y, double Z) 76 public Vector3(double X, double Y, double Z)
58 { 77 {
59 x = X; 78 x = X;
@@ -109,6 +128,26 @@ namespace OpenSim.Region.ScriptEngine.Shared
109 return new list(new object[] { vec }); 128 return new list(new object[] { vec });
110 } 129 }
111 130
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
112 public static bool operator ==(Vector3 lhs, Vector3 rhs) 151 public static bool operator ==(Vector3 lhs, Vector3 rhs)
113 { 152 {
114 return (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z); 153 return (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z);
@@ -322,6 +361,14 @@ namespace OpenSim.Region.ScriptEngine.Shared
322 s = 1; 361 s = 1;
323 } 362 }
324 363
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
325 #endregion 372 #endregion
326 373
327 #region Overriders 374 #region Overriders
@@ -368,6 +415,21 @@ namespace OpenSim.Region.ScriptEngine.Shared
368 return new list(new object[] { r }); 415 return new list(new object[] { r });
369 } 416 }
370 417
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
371 public static bool operator ==(Quaternion lhs, Quaternion rhs) 433 public static bool operator ==(Quaternion lhs, Quaternion rhs)
372 { 434 {
373 // Return true if the fields match: 435 // Return true if the fields match:
@@ -562,12 +624,23 @@ namespace OpenSim.Region.ScriptEngine.Shared
562 else if (m_data[itemIndex] is LSL_Types.LSLString) 624 else if (m_data[itemIndex] is LSL_Types.LSLString)
563 return new LSLInteger(m_data[itemIndex].ToString()); 625 return new LSLInteger(m_data[itemIndex].ToString());
564 else 626 else
565 throw new InvalidCastException(); 627 throw new InvalidCastException(string.Format(
628 "{0} expected but {1} given",
629 typeof(LSL_Types.LSLInteger).Name,
630 m_data[itemIndex] != null ?
631 m_data[itemIndex].GetType().Name : "null"));
566 } 632 }
567 633
568 public LSL_Types.Vector3 GetVector3Item(int itemIndex) 634 public LSL_Types.Vector3 GetVector3Item(int itemIndex)
569 { 635 {
570 return (LSL_Types.Vector3)m_data[itemIndex]; 636 if(m_data[itemIndex] is LSL_Types.Vector3)
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"));
571 } 644 }
572 645
573 public LSL_Types.Quaternion GetQuaternionItem(int itemIndex) 646 public LSL_Types.Quaternion GetQuaternionItem(int itemIndex)
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGUuidGatherer.cs b/OpenSim/Region/ScriptEngine/Shared/ScriptException.cs
index fcb544f..f55ba7e 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGUuidGatherer.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/ScriptException.cs
@@ -26,32 +26,19 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Runtime.Serialization;
30 30
31using OpenSim.Framework; 31namespace OpenSim.Region.ScriptEngine.Shared
32using OpenSim.Region.Framework.Scenes;
33using OpenSim.Services.Interfaces;
34using OpenMetaverse;
35
36namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
37{ 32{
38 public class HGUuidGatherer : UuidGatherer 33 [Serializable]
34 public class ScriptException : Exception
39 { 35 {
40 protected string m_assetServerURL; 36 public ScriptException() : base() {}
41 protected HGAssetMapper m_assetMapper; 37
38 public ScriptException(string message) : base(message) {}
42 39
43 public HGUuidGatherer(HGAssetMapper assMap, IAssetService assetCache, string assetServerURL) : base(assetCache) 40 public ScriptException(string message, Exception innerException) : base(message, innerException) {}
44 {
45 m_assetMapper = assMap;
46 m_assetServerURL = assetServerURL;
47 }
48 41
49 protected override AssetBase GetAsset(UUID uuid) 42 public ScriptException(SerializationInfo info, StreamingContext context) :base(info, context) {}
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 }
56 } 43 }
57} 44} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs
new file mode 100644
index 0000000..dd23be8
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs
@@ -0,0 +1,134 @@
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 c8718d9..c401794 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs
@@ -75,76 +75,6 @@ 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
148 [Test] 78 [Test]
149 public void TestOsOwnerSaveAppearance() 79 public void TestOsOwnerSaveAppearance()
150 { 80 {
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs
index 25679a6..b49bcc2 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs
@@ -36,6 +36,7 @@ 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;
39using OpenSim.Region.CoreModules.Avatar.AvatarFactory; 40using OpenSim.Region.CoreModules.Avatar.AvatarFactory;
40using OpenSim.Region.OptionalModules.World.NPC; 41using OpenSim.Region.OptionalModules.World.NPC;
41using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
@@ -71,7 +72,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
71 config.Set("Enabled", "true"); 72 config.Set("Enabled", "true");
72 73
73 m_scene = new SceneHelpers().SetupScene(); 74 m_scene = new SceneHelpers().SetupScene();
74 SceneHelpers.SetupSceneModules(m_scene, initConfigSource, new AvatarFactoryModule(), new NPCModule()); 75 SceneHelpers.SetupSceneModules(
76 m_scene, initConfigSource, new AvatarFactoryModule(), new AttachmentsModule(), new NPCModule());
75 77
76 m_engine = new XEngine.XEngine(); 78 m_engine = new XEngine.XEngine();
77 m_engine.Initialise(initConfigSource); 79 m_engine.Initialise(initConfigSource);
@@ -79,13 +81,191 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
79 } 81 }
80 82
81 /// <summary> 83 /// <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>
82 /// Test removal of an owned NPC. 263 /// Test removal of an owned NPC.
83 /// </summary> 264 /// </summary>
84 [Test] 265 [Test]
85 public void TestOsNpcRemoveOwned() 266 public void TestOsNpcRemoveOwned()
86 { 267 {
87 TestHelpers.InMethod(); 268 TestHelpers.InMethod();
88// log4net.Config.XmlConfigurator.Configure();
89 269
90 // Store an avatar with a different height from default in a notecard. 270 // Store an avatar with a different height from default in a notecard.
91 UUID userId = TestHelpers.ParseTail(0x1); 271 UUID userId = TestHelpers.ParseTail(0x1);
diff --git a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs
index 5c4174e..9405075 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs
@@ -96,9 +96,12 @@ 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
99 m_log.Debug("Paid: " + objectID + " from " + agentID + ", amount " + amount); 102 m_log.Debug("Paid: " + objectID + " from " + agentID + ", amount " + amount);
100 103
101 part = part.ParentGroup.RootPart; 104// part = part.ParentGroup.RootPart;
102 money(part.LocalId, agentID, amount); 105 money(part.LocalId, agentID, amount);
103 } 106 }
104 107
@@ -152,9 +155,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
152 det[0] = new DetectParams(); 155 det[0] = new DetectParams();
153 det[0].Key = remoteClient.AgentId; 156 det[0].Key = remoteClient.AgentId;
154 det[0].Populate(myScriptEngine.World); 157 det[0].Populate(myScriptEngine.World);
155 det[0].OffsetPos = new LSL_Types.Vector3(offsetPos.X, 158 det[0].OffsetPos = offsetPos;
156 offsetPos.Y,
157 offsetPos.Z);
158 159
159 if (originalID == 0) 160 if (originalID == 0)
160 { 161 {
@@ -298,9 +299,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
298 foreach (DetectedObject detobj in col.Colliders) 299 foreach (DetectedObject detobj in col.Colliders)
299 { 300 {
300 DetectParams d = new DetectParams(); 301 DetectParams d = new DetectParams();
301 d.Position = new LSL_Types.Vector3(detobj.posVector.X, 302 d.Position = detobj.posVector;
302 detobj.posVector.Y,
303 detobj.posVector.Z);
304 d.Populate(myScriptEngine.World); 303 d.Populate(myScriptEngine.World);
305 det.Add(d); 304 det.Add(d);
306 myScriptEngine.PostObjectEvent(localID, new EventParams( 305 myScriptEngine.PostObjectEvent(localID, new EventParams(
@@ -318,9 +317,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
318 foreach (DetectedObject detobj in col.Colliders) 317 foreach (DetectedObject detobj in col.Colliders)
319 { 318 {
320 DetectParams d = new DetectParams(); 319 DetectParams d = new DetectParams();
321 d.Position = new LSL_Types.Vector3(detobj.posVector.X, 320 d.Position = detobj.posVector;
322 detobj.posVector.Y,
323 detobj.posVector.Z);
324 d.Populate(myScriptEngine.World); 321 d.Populate(myScriptEngine.World);
325 det.Add(d); 322 det.Add(d);
326 myScriptEngine.PostObjectEvent(localID, new EventParams( 323 myScriptEngine.PostObjectEvent(localID, new EventParams(
@@ -337,9 +334,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
337 foreach (DetectedObject detobj in col.Colliders) 334 foreach (DetectedObject detobj in col.Colliders)
338 { 335 {
339 DetectParams d = new DetectParams(); 336 DetectParams d = new DetectParams();
340 d.Position = new LSL_Types.Vector3(detobj.posVector.X, 337 d.Position = detobj.posVector;
341 detobj.posVector.Y,
342 detobj.posVector.Z);
343 d.Populate(myScriptEngine.World); 338 d.Populate(myScriptEngine.World);
344 det.Add(d); 339 det.Add(d);
345 myScriptEngine.PostObjectEvent(localID, new EventParams( 340 myScriptEngine.PostObjectEvent(localID, new EventParams(
@@ -381,8 +376,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
381 myScriptEngine.PostObjectEvent(localID, new EventParams( 376 myScriptEngine.PostObjectEvent(localID, new EventParams(
382 "at_target", new object[] { 377 "at_target", new object[] {
383 new LSL_Types.LSLInteger(handle), 378 new LSL_Types.LSLInteger(handle),
384 new LSL_Types.Vector3(targetpos.X,targetpos.Y,targetpos.Z), 379 new LSL_Types.Vector3(targetpos),
385 new LSL_Types.Vector3(atpos.X,atpos.Y,atpos.Z) }, 380 new LSL_Types.Vector3(atpos) },
386 new DetectParams[0])); 381 new DetectParams[0]));
387 } 382 }
388 383
@@ -399,8 +394,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
399 myScriptEngine.PostObjectEvent(localID, new EventParams( 394 myScriptEngine.PostObjectEvent(localID, new EventParams(
400 "at_rot_target", new object[] { 395 "at_rot_target", new object[] {
401 new LSL_Types.LSLInteger(handle), 396 new LSL_Types.LSLInteger(handle),
402 new LSL_Types.Quaternion(targetrot.X,targetrot.Y,targetrot.Z,targetrot.W), 397 new LSL_Types.Quaternion(targetrot),
403 new LSL_Types.Quaternion(atrot.X,atrot.Y,atrot.Z,atrot.W) }, 398 new LSL_Types.Quaternion(atrot) },
404 new DetectParams[0])); 399 new DetectParams[0]));
405 } 400 }
406 401
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs
index f247a0b..f331658 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(0x2); 93// UUID objectId = TestHelpers.ParseTail(0x100);
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,12 +105,18 @@ namespace OpenSim.Region.ScriptEngine.XEngine.Tests
105 105
106 m_scene.EventManager.OnChatFromWorld += OnChatFromWorld; 106 m_scene.EventManager.OnChatFromWorld += OnChatFromWorld;
107 107
108 m_scene.RezNewScript(userId, itemTemplate); 108 SceneObjectPart partWhereRezzed = 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);
114 } 120 }
115 121
116 private void OnChatFromWorld(object sender, OSChatMessage oscm) 122 private void OnChatFromWorld(object sender, OSChatMessage oscm)
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index f6cb7df..9f05666 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -656,7 +656,19 @@ 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 instance.SaveState(assembly); 659
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 }
660 } 672 }
661 673
662 // Clear the event queue and abort the instance thread 674 // Clear the event queue and abort the instance thread
@@ -778,7 +790,18 @@ namespace OpenSim.Region.ScriptEngine.XEngine
778 assembly = m_Assemblies[i.AssetID]; 790 assembly = m_Assemblies[i.AssetID];
779 791
780 792
781 i.SaveState(assembly); 793 try
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 }
782 } 805 }
783 806
784 instances.Clear(); 807 instances.Clear();
@@ -971,6 +994,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
971 // This delay exists to stop mono problems where script compilation and startup would stop the sim 994 // This delay exists to stop mono problems where script compilation and startup would stop the sim
972 // working properly for the session. 995 // working properly for the session.
973 System.Threading.Thread.Sleep(m_StartDelay); 996 System.Threading.Thread.Sleep(m_StartDelay);
997
998 m_log.InfoFormat("[XEngine]: Performing initial script startup on {0}", m_Scene.Name);
974 } 999 }
975 1000
976 object[] o; 1001 object[] o;
@@ -986,13 +1011,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine
986 if (m_InitialStartup) 1011 if (m_InitialStartup)
987 if (scriptsStarted % 50 == 0) 1012 if (scriptsStarted % 50 == 0)
988 m_log.InfoFormat( 1013 m_log.InfoFormat(
989 "[XEngine]: Started {0} scripts in {1}", scriptsStarted, m_Scene.RegionInfo.RegionName); 1014 "[XEngine]: Started {0} scripts in {1}", scriptsStarted, m_Scene.Name);
990 } 1015 }
991 } 1016 }
992 1017
993 if (m_InitialStartup) 1018 if (m_InitialStartup)
994 m_log.InfoFormat( 1019 m_log.InfoFormat(
995 "[XEngine]: Completed starting {0} scripts on {1}", scriptsStarted, m_Scene.RegionInfo.RegionName); 1020 "[XEngine]: Completed starting {0} scripts on {1}", scriptsStarted, m_Scene.Name);
996 1021
997 // NOTE: Despite having a lockless queue, this lock is required 1022 // NOTE: Despite having a lockless queue, this lock is required
998 // to make sure there is never no compile thread while there 1023 // to make sure there is never no compile thread while there
@@ -1053,10 +1078,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1053 return false; 1078 return false;
1054 } 1079 }
1055 1080
1056 UUID assetID = item.AssetID; 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);
1057 1085
1058 //m_log.DebugFormat("[XEngine] Compiling script {0} ({1} on object {2})", 1086 UUID assetID = item.AssetID;
1059 // item.Name, itemID.ToString(), part.ParentGroup.RootPart.Name);
1060 1087
1061 ScenePresence presence = m_Scene.GetScenePresence(item.OwnerID); 1088 ScenePresence presence = m_Scene.GetScenePresence(item.OwnerID);
1062 1089
@@ -1235,10 +1262,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1235 item.Name, startParam, postOnRez, 1262 item.Name, startParam, postOnRez,
1236 stateSource, m_MaxScriptQueue); 1263 stateSource, m_MaxScriptQueue);
1237 1264
1238 m_log.DebugFormat( 1265// m_log.DebugFormat(
1239 "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}", 1266// "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}",
1240 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, 1267// part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID,
1241 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); 1268// part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1242 1269
1243 if (presence != null) 1270 if (presence != null)
1244 { 1271 {
@@ -1554,9 +1581,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1554 else if (p[i] is string) 1581 else if (p[i] is string)
1555 lsl_p[i] = new LSL_Types.LSLString((string)p[i]); 1582 lsl_p[i] = new LSL_Types.LSLString((string)p[i]);
1556 else if (p[i] is Vector3) 1583 else if (p[i] is Vector3)
1557 lsl_p[i] = new LSL_Types.Vector3(((Vector3)p[i]).X, ((Vector3)p[i]).Y, ((Vector3)p[i]).Z); 1584 lsl_p[i] = new LSL_Types.Vector3((Vector3)p[i]);
1558 else if (p[i] is Quaternion) 1585 else if (p[i] is Quaternion)
1559 lsl_p[i] = new LSL_Types.Quaternion(((Quaternion)p[i]).X, ((Quaternion)p[i]).Y, ((Quaternion)p[i]).Z, ((Quaternion)p[i]).W); 1586 lsl_p[i] = new LSL_Types.Quaternion((Quaternion)p[i]);
1560 else if (p[i] is float) 1587 else if (p[i] is float)
1561 lsl_p[i] = new LSL_Types.LSLFloat((float)p[i]); 1588 lsl_p[i] = new LSL_Types.LSLFloat((float)p[i]);
1562 else 1589 else
@@ -1580,9 +1607,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1580 else if (p[i] is string) 1607 else if (p[i] is string)
1581 lsl_p[i] = new LSL_Types.LSLString((string)p[i]); 1608 lsl_p[i] = new LSL_Types.LSLString((string)p[i]);
1582 else if (p[i] is Vector3) 1609 else if (p[i] is Vector3)
1583 lsl_p[i] = new LSL_Types.Vector3(((Vector3)p[i]).X, ((Vector3)p[i]).Y, ((Vector3)p[i]).Z); 1610 lsl_p[i] = new LSL_Types.Vector3((Vector3)p[i]);
1584 else if (p[i] is Quaternion) 1611 else if (p[i] is Quaternion)
1585 lsl_p[i] = new LSL_Types.Quaternion(((Quaternion)p[i]).X, ((Quaternion)p[i]).Y, ((Quaternion)p[i]).Z, ((Quaternion)p[i]).W); 1612 lsl_p[i] = new LSL_Types.Quaternion((Quaternion)p[i]);
1586 else if (p[i] is float) 1613 else if (p[i] is float)
1587 lsl_p[i] = new LSL_Types.LSLFloat((float)p[i]); 1614 lsl_p[i] = new LSL_Types.LSLFloat((float)p[i]);
1588 else 1615 else
diff --git a/OpenSim/Region/UserStatistics/WebStatsModule.cs b/OpenSim/Region/UserStatistics/WebStatsModule.cs
index c11ea02..625eba4 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, UserSessionID> m_sessions = new Dictionary<UUID, UserSessionID>(); 64 private Dictionary<UUID, UserSession> m_sessions = new Dictionary<UUID, UserSession>();
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,14 +319,18 @@ 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
322 lock (m_sessions) 326 lock (m_sessions)
323 { 327 {
324 UserSessionID uid; 328 UserSession uid;
325 329
326 if (!m_sessions.ContainsKey(agent.UUID)) 330 if (!m_sessions.ContainsKey(agent.UUID))
327 { 331 {
328 UserSessionData usd = UserSessionUtil.newUserSessionData(); 332 UserSessionData usd = UserSessionUtil.newUserSessionData();
329 uid = new UserSessionID(); 333 uid = new UserSession();
330 uid.name_f = agent.Firstname; 334 uid.name_f = agent.Firstname;
331 uid.name_l = agent.Lastname; 335 uid.name_l = agent.Lastname;
332 uid.session_data = usd; 336 uid.session_data = usd;
@@ -411,9 +415,9 @@ namespace OpenSim.Region.UserStatistics
411 return String.Empty; 415 return String.Empty;
412 } 416 }
413 417
414 private UserSessionID ParseViewerStats(string request, UUID agentID) 418 private UserSession ParseViewerStats(string request, UUID agentID)
415 { 419 {
416 UserSessionID uid = new UserSessionID(); 420 UserSession uid = new UserSession();
417 UserSessionData usd; 421 UserSessionData usd;
418 OSD message = OSDParser.DeserializeLLSDXml(request); 422 OSD message = OSDParser.DeserializeLLSDXml(request);
419 OSDMap mmap; 423 OSDMap mmap;
@@ -425,22 +429,25 @@ namespace OpenSim.Region.UserStatistics
425 if (!m_sessions.ContainsKey(agentID)) 429 if (!m_sessions.ContainsKey(agentID))
426 { 430 {
427 m_log.WarnFormat("[WEB STATS MODULE]: no session for stat disclosure for agent {0}", agentID); 431 m_log.WarnFormat("[WEB STATS MODULE]: no session for stat disclosure for agent {0}", agentID);
428 return new UserSessionID(); 432 return new UserSession();
429 } 433 }
434
430 uid = m_sessions[agentID]; 435 uid = m_sessions[agentID];
436
437// m_log.DebugFormat("[WEB STATS MODULE]: Got session {0} for {1}", uid.session_id, agentID);
431 } 438 }
432 else 439 else
433 { 440 {
434 // parse through the beginning to locate the session 441 // parse through the beginning to locate the session
435 if (message.Type != OSDType.Map) 442 if (message.Type != OSDType.Map)
436 return new UserSessionID(); 443 return new UserSession();
437 444
438 mmap = (OSDMap)message; 445 mmap = (OSDMap)message;
439 { 446 {
440 UUID sessionID = mmap["session_id"].AsUUID(); 447 UUID sessionID = mmap["session_id"].AsUUID();
441 448
442 if (sessionID == UUID.Zero) 449 if (sessionID == UUID.Zero)
443 return new UserSessionID(); 450 return new UserSession();
444 451
445 452
446 // search through each session looking for the owner 453 // search through each session looking for the owner
@@ -459,7 +466,7 @@ namespace OpenSim.Region.UserStatistics
459 // can't find a session 466 // can't find a session
460 if (agentID == UUID.Zero) 467 if (agentID == UUID.Zero)
461 { 468 {
462 return new UserSessionID(); 469 return new UserSession();
463 } 470 }
464 } 471 }
465 } 472 }
@@ -468,12 +475,12 @@ namespace OpenSim.Region.UserStatistics
468 usd = uid.session_data; 475 usd = uid.session_data;
469 476
470 if (message.Type != OSDType.Map) 477 if (message.Type != OSDType.Map)
471 return new UserSessionID(); 478 return new UserSession();
472 479
473 mmap = (OSDMap)message; 480 mmap = (OSDMap)message;
474 { 481 {
475 if (mmap["agent"].Type != OSDType.Map) 482 if (mmap["agent"].Type != OSDType.Map)
476 return new UserSessionID(); 483 return new UserSession();
477 OSDMap agent_map = (OSDMap)mmap["agent"]; 484 OSDMap agent_map = (OSDMap)mmap["agent"];
478 usd.agent_id = agentID; 485 usd.agent_id = agentID;
479 usd.name_f = uid.name_f; 486 usd.name_f = uid.name_f;
@@ -493,17 +500,18 @@ namespace OpenSim.Region.UserStatistics
493 (float)agent_map["fps"].AsReal()); 500 (float)agent_map["fps"].AsReal());
494 501
495 if (mmap["downloads"].Type != OSDType.Map) 502 if (mmap["downloads"].Type != OSDType.Map)
496 return new UserSessionID(); 503 return new UserSession();
497 OSDMap downloads_map = (OSDMap)mmap["downloads"]; 504 OSDMap downloads_map = (OSDMap)mmap["downloads"];
498 usd.d_object_kb = (float)downloads_map["object_kbytes"].AsReal(); 505 usd.d_object_kb = (float)downloads_map["object_kbytes"].AsReal();
499 usd.d_texture_kb = (float)downloads_map["texture_kbytes"].AsReal(); 506 usd.d_texture_kb = (float)downloads_map["texture_kbytes"].AsReal();
500 usd.d_world_kb = (float)downloads_map["workd_kbytes"].AsReal(); 507 usd.d_world_kb = (float)downloads_map["workd_kbytes"].AsReal();
501 508
509// m_log.DebugFormat("[WEB STATS MODULE]: mmap[\"session_id\"] = [{0}]", mmap["session_id"].AsUUID());
502 510
503 usd.session_id = mmap["session_id"].AsUUID(); 511 usd.session_id = mmap["session_id"].AsUUID();
504 512
505 if (mmap["system"].Type != OSDType.Map) 513 if (mmap["system"].Type != OSDType.Map)
506 return new UserSessionID(); 514 return new UserSession();
507 OSDMap system_map = (OSDMap)mmap["system"]; 515 OSDMap system_map = (OSDMap)mmap["system"];
508 516
509 usd.s_cpu = system_map["cpu"].AsString(); 517 usd.s_cpu = system_map["cpu"].AsString();
@@ -512,13 +520,13 @@ namespace OpenSim.Region.UserStatistics
512 usd.s_ram = system_map["ram"].AsInteger(); 520 usd.s_ram = system_map["ram"].AsInteger();
513 521
514 if (mmap["stats"].Type != OSDType.Map) 522 if (mmap["stats"].Type != OSDType.Map)
515 return new UserSessionID(); 523 return new UserSession();
516 524
517 OSDMap stats_map = (OSDMap)mmap["stats"]; 525 OSDMap stats_map = (OSDMap)mmap["stats"];
518 { 526 {
519 527
520 if (stats_map["failures"].Type != OSDType.Map) 528 if (stats_map["failures"].Type != OSDType.Map)
521 return new UserSessionID(); 529 return new UserSession();
522 OSDMap stats_failures = (OSDMap)stats_map["failures"]; 530 OSDMap stats_failures = (OSDMap)stats_map["failures"];
523 usd.f_dropped = stats_failures["dropped"].AsInteger(); 531 usd.f_dropped = stats_failures["dropped"].AsInteger();
524 usd.f_failed_resends = stats_failures["failed_resends"].AsInteger(); 532 usd.f_failed_resends = stats_failures["failed_resends"].AsInteger();
@@ -527,18 +535,18 @@ namespace OpenSim.Region.UserStatistics
527 usd.f_send_packet = stats_failures["send_packet"].AsInteger(); 535 usd.f_send_packet = stats_failures["send_packet"].AsInteger();
528 536
529 if (stats_map["net"].Type != OSDType.Map) 537 if (stats_map["net"].Type != OSDType.Map)
530 return new UserSessionID(); 538 return new UserSession();
531 OSDMap stats_net = (OSDMap)stats_map["net"]; 539 OSDMap stats_net = (OSDMap)stats_map["net"];
532 { 540 {
533 if (stats_net["in"].Type != OSDType.Map) 541 if (stats_net["in"].Type != OSDType.Map)
534 return new UserSessionID(); 542 return new UserSession();
535 543
536 OSDMap net_in = (OSDMap)stats_net["in"]; 544 OSDMap net_in = (OSDMap)stats_net["in"];
537 usd.n_in_kb = (float)net_in["kbytes"].AsReal(); 545 usd.n_in_kb = (float)net_in["kbytes"].AsReal();
538 usd.n_in_pk = net_in["packets"].AsInteger(); 546 usd.n_in_pk = net_in["packets"].AsInteger();
539 547
540 if (stats_net["out"].Type != OSDType.Map) 548 if (stats_net["out"].Type != OSDType.Map)
541 return new UserSessionID(); 549 return new UserSession();
542 OSDMap net_out = (OSDMap)stats_net["out"]; 550 OSDMap net_out = (OSDMap)stats_net["out"];
543 551
544 usd.n_out_kb = (float)net_out["kbytes"].AsReal(); 552 usd.n_out_kb = (float)net_out["kbytes"].AsReal();
@@ -549,11 +557,18 @@ namespace OpenSim.Region.UserStatistics
549 557
550 uid.session_data = usd; 558 uid.session_data = usd;
551 m_sessions[agentID] = uid; 559 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
552 return uid; 564 return uid;
553 } 565 }
554 566
555 private void UpdateUserStats(UserSessionID uid, SqliteConnection db) 567 private void UpdateUserStats(UserSession uid, SqliteConnection db)
556 { 568 {
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
557 if (uid.session_id == UUID.Zero) 572 if (uid.session_id == UUID.Zero)
558 return; 573 return;
559 574
@@ -740,7 +755,6 @@ VALUES
740 s.min_ping = ArrayMin_f(__ping); 755 s.min_ping = ArrayMin_f(__ping);
741 s.max_ping = ArrayMax_f(__ping); 756 s.max_ping = ArrayMax_f(__ping);
742 s.mode_ping = ArrayMode_f(__ping); 757 s.mode_ping = ArrayMode_f(__ping);
743
744 } 758 }
745 759
746 #region Statistics 760 #region Statistics
@@ -985,7 +999,7 @@ VALUES
985 } 999 }
986 #region structs 1000 #region structs
987 1001
988 public struct UserSessionID 1002 public class UserSession
989 { 1003 {
990 public UUID session_id; 1004 public UUID session_id;
991 public UUID region_id; 1005 public UUID region_id;
diff --git a/OpenSim/Server/Base/ServicesServerBase.cs b/OpenSim/Server/Base/ServicesServerBase.cs
index b137c05..0cff6ed 100644
--- a/OpenSim/Server/Base/ServicesServerBase.cs
+++ b/OpenSim/Server/Base/ServicesServerBase.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic;
29using System.IO; 30using System.IO;
30using System.Reflection; 31using System.Reflection;
31using System.Threading; 32using System.Threading;
@@ -71,10 +72,17 @@ namespace OpenSim.Server.Base
71 // 72 //
72 private string m_pidFile = String.Empty; 73 private string m_pidFile = String.Empty;
73 74
75 /// <summary>
76 /// Time at which this server was started
77 /// </summary>
78 protected DateTime m_startuptime;
79
74 // Handle all the automagical stuff 80 // Handle all the automagical stuff
75 // 81 //
76 public ServicesServerBase(string prompt, string[] args) 82 public ServicesServerBase(string prompt, string[] args)
77 { 83 {
84 m_startuptime = DateTime.Now;
85
78 // Save raw arguments 86 // Save raw arguments
79 // 87 //
80 m_Arguments = args; 88 m_Arguments = args;
@@ -250,6 +258,10 @@ namespace OpenSim.Server.Base
250 "command-script <script>", 258 "command-script <script>",
251 "Run a command script from file", HandleScript); 259 "Run a command script from file", HandleScript);
252 260
261 MainConsole.Instance.Commands.AddCommand("General", false, "show uptime",
262 "show uptime",
263 "Show server uptime", HandleShow);
264
253 265
254 // Allow derived classes to perform initialization that 266 // Allow derived classes to perform initialization that
255 // needs to be done after the console has opened 267 // needs to be done after the console has opened
@@ -345,5 +357,34 @@ namespace OpenSim.Server.Base
345 { 357 {
346 } 358 }
347 } 359 }
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 }
348 } 389 }
349} 390}
diff --git a/OpenSim/Server/Handlers/Asset/AssetServerConnector.cs b/OpenSim/Server/Handlers/Asset/AssetServerConnector.cs
index 46b0c67..ff45d94 100644
--- a/OpenSim/Server/Handlers/Asset/AssetServerConnector.cs
+++ b/OpenSim/Server/Handlers/Asset/AssetServerConnector.cs
@@ -67,10 +67,25 @@ 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 }
70 85
71 server.AddStreamHandler(new AssetServerGetHandler(m_AssetService)); 86 server.AddStreamHandler(new AssetServerGetHandler(m_AssetService));
72 server.AddStreamHandler(new AssetServerPostHandler(m_AssetService)); 87 server.AddStreamHandler(new AssetServerPostHandler(m_AssetService));
73 server.AddStreamHandler(new AssetServerDeleteHandler(m_AssetService, allowDelete)); 88 server.AddStreamHandler(new AssetServerDeleteHandler(m_AssetService, allowedRemoteDeleteTypes));
74 89
75 MainConsole.Instance.Commands.AddCommand("Assets", false, 90 MainConsole.Instance.Commands.AddCommand("Assets", false,
76 "show asset", 91 "show asset",
@@ -141,6 +156,9 @@ namespace OpenSim.Server.Handlers.Asset
141 } 156 }
142 157
143 string fileName = rawAssetId; 158 string fileName = rawAssetId;
159
160 if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, fileName))
161 return;
144 162
145 using (FileStream fs = new FileStream(fileName, FileMode.CreateNew)) 163 using (FileStream fs = new FileStream(fileName, FileMode.CreateNew))
146 { 164 {
diff --git a/OpenSim/Server/Handlers/Asset/AssetServerDeleteHandler.cs b/OpenSim/Server/Handlers/Asset/AssetServerDeleteHandler.cs
index 0cfe5b1..986394b 100644
--- a/OpenSim/Server/Handlers/Asset/AssetServerDeleteHandler.cs
+++ b/OpenSim/Server/Handlers/Asset/AssetServerDeleteHandler.cs
@@ -42,18 +42,32 @@ 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
45 public class AssetServerDeleteHandler : BaseStreamHandler 55 public class AssetServerDeleteHandler : BaseStreamHandler
46 { 56 {
47 // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 57 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 58
49 private IAssetService m_AssetService; 59 private IAssetService m_AssetService;
50 protected bool m_allowDelete;
51 60
52 public AssetServerDeleteHandler(IAssetService service, bool allowDelete) : 61 /// <summary>
62 /// Asset types that can be deleted remotely.
63 /// </summary>
64 private AllowedRemoteDeleteTypes m_allowedTypes;
65
66 public AssetServerDeleteHandler(IAssetService service, AllowedRemoteDeleteTypes allowedTypes) :
53 base("DELETE", "/assets") 67 base("DELETE", "/assets")
54 { 68 {
55 m_AssetService = service; 69 m_AssetService = service;
56 m_allowDelete = allowDelete; 70 m_allowedTypes = allowedTypes;
57 } 71 }
58 72
59 public override byte[] Handle(string path, Stream request, 73 public override byte[] Handle(string path, Stream request,
@@ -63,13 +77,32 @@ namespace OpenSim.Server.Handlers.Asset
63 77
64 string[] p = SplitParams(path); 78 string[] p = SplitParams(path);
65 79
66 if (p.Length > 0 && m_allowDelete) 80 if (p.Length > 0)
67 { 81 {
68 result = m_AssetService.Delete(p[0]); 82 if (m_allowedTypes != AllowedRemoteDeleteTypes.None)
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 }
69 } 102 }
70 103
71 XmlSerializer xs = new XmlSerializer(typeof(bool)); 104 XmlSerializer xs = new XmlSerializer(typeof(bool));
72 return ServerUtils.SerializeResult(xs, result); 105 return ServerUtils.SerializeResult(xs, result);
73 } 106 }
74 } 107 }
75} 108} \ No newline at end of file
diff --git a/OpenSim/Server/Handlers/Avatar/AvatarServerPostHandler.cs b/OpenSim/Server/Handlers/Avatar/AvatarServerPostHandler.cs
index 393584e..8cd747e 100644
--- a/OpenSim/Server/Handlers/Avatar/AvatarServerPostHandler.cs
+++ b/OpenSim/Server/Handlers/Avatar/AvatarServerPostHandler.cs
@@ -137,6 +137,8 @@ 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
140 AvatarData avatar = new AvatarData(request); 142 AvatarData avatar = new AvatarData(request);
141 if (m_AvatarService.SetAvatar(user, avatar)) 143 if (m_AvatarService.SetAvatar(user, avatar))
142 return SuccessResult(); 144 return SuccessResult();
@@ -153,11 +155,25 @@ namespace OpenSim.Server.Handlers.Avatar
153 if (!UUID.TryParse(request["UserID"].ToString(), out user)) 155 if (!UUID.TryParse(request["UserID"].ToString(), out user))
154 return FailureResult(); 156 return FailureResult();
155 157
158 RemoveRequestParamsNotForStorage(request);
159
156 if (m_AvatarService.ResetAvatar(user)) 160 if (m_AvatarService.ResetAvatar(user))
157 return SuccessResult(); 161 return SuccessResult();
158 162
159 return FailureResult(); 163 return FailureResult();
160 } 164 }
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 }
161 177
162 byte[] SetItems(Dictionary<string, object> request) 178 byte[] SetItems(Dictionary<string, object> request)
163 { 179 {
@@ -173,6 +189,8 @@ namespace OpenSim.Server.Handlers.Avatar
173 if (!(request["Names"] is List<string> || request["Values"] is List<string>)) 189 if (!(request["Names"] is List<string> || request["Values"] is List<string>))
174 return FailureResult(); 190 return FailureResult();
175 191
192 RemoveRequestParamsNotForStorage(request);
193
176 List<string> _names = (List<string>)request["Names"]; 194 List<string> _names = (List<string>)request["Names"];
177 names = _names.ToArray(); 195 names = _names.ToArray();
178 List<string> _values = (List<string>)request["Values"]; 196 List<string> _values = (List<string>)request["Values"];
diff --git a/OpenSim/Server/ServerMain.cs b/OpenSim/Server/ServerMain.cs
index 21fb678..45c13fb 100644
--- a/OpenSim/Server/ServerMain.cs
+++ b/OpenSim/Server/ServerMain.cs
@@ -60,7 +60,25 @@ namespace OpenSim.Server
60 } 60 }
61 61
62 string connList = serverConfig.GetString("ServiceConnectors", String.Empty); 62 string connList = serverConfig.GetString("ServiceConnectors", String.Empty);
63 string[] conns = connList.Split(new char[] {',', ' '}); 63
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'});
64 82
65// int i = 0; 83// int i = 0;
66 foreach (string c in conns) 84 foreach (string c in conns)
@@ -130,4 +148,4 @@ namespace OpenSim.Server
130 return 0; 148 return 0;
131 } 149 }
132 } 150 }
133} \ No newline at end of file 151}
diff --git a/OpenSim/Services/AssetService/AssetService.cs b/OpenSim/Services/AssetService/AssetService.cs
index 96b430d..f1bffa4 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]: Loading default asset set from {0}", loaderArgs); 73 m_log.DebugFormat("[ASSET SERVICE]: Loading default asset set from {0}", loaderArgs);
74 74
75 m_AssetLoader.ForEachDefaultXmlAsset( 75 m_AssetLoader.ForEachDefaultXmlAsset(
76 loaderArgs, 76 loaderArgs,
@@ -200,20 +200,7 @@ 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 AssetBase asset = m_Database.GetAsset(assetID); 203 return m_Database.Delete(id);
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;
217 } 204 }
218 } 205 }
219} \ No newline at end of file 206} \ No newline at end of file
diff --git a/OpenSim/Services/AssetService/AssetServiceBase.cs b/OpenSim/Services/AssetService/AssetServiceBase.cs
index 177c565..58ab052 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("Could not find a storage interface in the given module"); 87 throw new Exception(string.Format("Could not find a storage interface in the module {0}", dllName));
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("Asset loader could not be loaded"); 99 throw new Exception(string.Format("Asset loader could not be loaded from {0}", loaderName));
100 } 100 }
101 } 101 }
102 } 102 }
diff --git a/OpenSim/Services/AssetService/XAssetService.cs b/OpenSim/Services/AssetService/XAssetService.cs
index e62bcb5..a1d10ed 100644
--- a/OpenSim/Services/AssetService/XAssetService.cs
+++ b/OpenSim/Services/AssetService/XAssetService.cs
@@ -194,21 +194,7 @@ 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 AssetBase asset = m_Database.GetAsset(assetID); 197 return m_Database.Delete(id);
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;
211 } 198 }
212 } 199 }
213} 200} \ No newline at end of file
214
diff --git a/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs b/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs
index 7f32ad3..4b502b7 100644
--- a/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs
+++ b/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs
@@ -52,6 +52,8 @@ 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
55 private delegate void AssetRetrievedEx(AssetBase asset); 57 private delegate void AssetRetrievedEx(AssetBase asset);
56 58
57 // Keeps track of concurrent requests for the same asset, so that it's only loaded once. 59 // Keeps track of concurrent requests for the same asset, so that it's only loaded once.
@@ -80,6 +82,10 @@ namespace OpenSim.Services.Connectors
80 82
81 public virtual void Initialise(IConfigSource source) 83 public virtual void Initialise(IConfigSource source)
82 { 84 {
85 IConfig netconfig = source.Configs["Network"];
86 if (netconfig != null)
87 m_maxAssetRequestConcurrency = netconfig.GetInt("MaxRequestConcurrency",m_maxAssetRequestConcurrency);
88
83 IConfig assetConfig = source.Configs["AssetService"]; 89 IConfig assetConfig = source.Configs["AssetService"];
84 if (assetConfig == null) 90 if (assetConfig == null)
85 { 91 {
@@ -204,7 +210,7 @@ namespace OpenSim.Services.Connectors
204 if (asset == null || asset.Data == null || asset.Data.Length == 0) 210 if (asset == null || asset.Data == null || asset.Data.Length == 0)
205 { 211 {
206 asset = SynchronousRestObjectRequester. 212 asset = SynchronousRestObjectRequester.
207 MakeRequest<int, AssetBase>("GET", uri, 0, 30); 213 MakeRequest<int, AssetBase>("GET", uri, 0, m_maxAssetRequestConcurrency);
208 214
209 if (m_Cache != null) 215 if (m_Cache != null)
210 m_Cache.Cache(asset); 216 m_Cache.Cache(asset);
diff --git a/OpenSim/Services/Connectors/Friends/FriendsSimConnector.cs b/OpenSim/Services/Connectors/Friends/FriendsSimConnector.cs
index 6cd21d1..45f4514 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, UUID friendID, bool online) 131 public bool StatusNotify(GridRegion region, UUID userID, string 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.ToString(); 139 sendData["ToID"] = friendID;
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 20d7eaf..94bda82 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 = new GridUserInfo((Dictionary<string, object>)replyData["result"]); 210 guinfo = Create((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 = new GridUserInfo((Dictionary<string, object>)griduser); 276 GridUserInfo pinfo = Create((Dictionary<string, object>)griduser);
277 rinfos.Add(pinfo); 277 rinfos.Add(pinfo);
278 } 278 }
279 else 279 else
@@ -286,5 +286,10 @@ 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 }
289 } 294 }
290} 295}
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs
index 0e4d794..20eaa3a 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, 4096.0); 115 Vector3d maxPosition = minPosition + new Vector3d(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
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, 4096.0); 300 Vector3d maxPosition = new Vector3d(xmax, ymax, Constants.RegionHeight);
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.Data.RegionFlags.RegionOnline : 0; 398 int enabled = response["Enabled"].AsBoolean() ? (int)OpenSim.Framework.RegionFlags.RegionOnline : 0;
399 int hypergrid = extraData["HyperGrid"].AsBoolean() ? (int) OpenSim.Data.RegionFlags.Hyperlink : 0; 399 int hypergrid = extraData["HyperGrid"].AsBoolean() ? (int)OpenSim.Framework.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 aab403a..ee3b858 100644
--- a/OpenSim/Services/GridService/GridService.cs
+++ b/OpenSim/Services/GridService/GridService.cs
@@ -137,20 +137,25 @@ 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?
142 RegionData region = m_Database.Get(regionInfos.RegionLocX, regionInfos.RegionLocY, scopeID); 140 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
143 if (region != null) 148 if (region != null)
144 { 149 {
145 // There is a preexisting record 150 // There is a preexisting record
146 // 151 //
147 // Get it's flags 152 // Get it's flags
148 // 153 //
149 OpenSim.Data.RegionFlags rflags = (OpenSim.Data.RegionFlags)Convert.ToInt32(region.Data["flags"]); 154 OpenSim.Framework.RegionFlags rflags = (OpenSim.Framework.RegionFlags)Convert.ToInt32(region.Data["flags"]);
150 155
151 // Is this a reservation? 156 // Is this a reservation?
152 // 157 //
153 if ((rflags & OpenSim.Data.RegionFlags.Reservation) != 0) 158 if ((rflags & OpenSim.Framework.RegionFlags.Reservation) != 0)
154 { 159 {
155 // Regions reserved for the null key cannot be taken. 160 // Regions reserved for the null key cannot be taken.
156 if ((string)region.Data["PrincipalID"] == UUID.Zero.ToString()) 161 if ((string)region.Data["PrincipalID"] == UUID.Zero.ToString())
@@ -161,10 +166,10 @@ namespace OpenSim.Services.GridService
161 // NOTE: Fudging the flags value here, so these flags 166 // NOTE: Fudging the flags value here, so these flags
162 // should not be used elsewhere. Don't optimize 167 // should not be used elsewhere. Don't optimize
163 // this with the later retrieval of the same flags! 168 // this with the later retrieval of the same flags!
164 rflags |= OpenSim.Data.RegionFlags.Authenticate; 169 rflags |= OpenSim.Framework.RegionFlags.Authenticate;
165 } 170 }
166 171
167 if ((rflags & OpenSim.Data.RegionFlags.Authenticate) != 0) 172 if ((rflags & OpenSim.Framework.RegionFlags.Authenticate) != 0)
168 { 173 {
169 // Can we authenticate at all? 174 // Can we authenticate at all?
170 // 175 //
@@ -176,19 +181,36 @@ namespace OpenSim.Services.GridService
176 } 181 }
177 } 182 }
178 183
179 if ((region != null) && (region.RegionID != regionInfos.RegionID)) 184 // If we get here, the destination is clear. Now for the real check.
185
186 if (!m_AllowDuplicateNames)
180 { 187 {
181 m_log.WarnFormat("[GRID SERVICE]: Region {0} tried to register in coordinates {1}, {2} which are already in use in scope {3}.", 188 List<RegionData> dupe = m_Database.Get(regionInfos.RegionName, scopeID);
182 regionInfos.RegionID, regionInfos.RegionLocX, regionInfos.RegionLocY, scopeID); 189 if (dupe != null && dupe.Count > 0)
183 return "Region overlaps another region"; 190 {
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 }
184 } 201 }
185 202
203 // If there is an old record for us, delete it if it is elsewhere.
204 region = m_Database.Get(regionInfos.RegionID, scopeID);
186 if ((region != null) && (region.RegionID == regionInfos.RegionID) && 205 if ((region != null) && (region.RegionID == regionInfos.RegionID) &&
187 ((region.posX != regionInfos.RegionLocX) || (region.posY != regionInfos.RegionLocY))) 206 ((region.posX != regionInfos.RegionLocX) || (region.posY != regionInfos.RegionLocY)))
188 { 207 {
189 if ((Convert.ToInt32(region.Data["flags"]) & (int)OpenSim.Data.RegionFlags.NoMove) != 0) 208 if ((Convert.ToInt32(region.Data["flags"]) & (int)OpenSim.Framework.RegionFlags.NoMove) != 0)
190 return "Can't move this region"; 209 return "Can't move this region";
191 210
211 if ((Convert.ToInt32(region.Data["flags"]) & (int)OpenSim.Framework.RegionFlags.LockedOut) != 0)
212 return "Region locked out";
213
192 // Region reregistering in other coordinates. Delete the old entry 214 // Region reregistering in other coordinates. Delete the old entry
193 m_log.DebugFormat("[GRID SERVICE]: Region {0} ({1}) was previously registered at {2}-{3}. Deleting old entry.", 215 m_log.DebugFormat("[GRID SERVICE]: Region {0} ({1}) was previously registered at {2}-{3}. Deleting old entry.",
194 regionInfos.RegionName, regionInfos.RegionID, regionInfos.RegionLocX, regionInfos.RegionLocY); 216 regionInfos.RegionName, regionInfos.RegionID, regionInfos.RegionLocX, regionInfos.RegionLocY);
@@ -203,23 +225,6 @@ namespace OpenSim.Services.GridService
203 } 225 }
204 } 226 }
205 227
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
223 // Everything is ok, let's register 228 // Everything is ok, let's register
224 RegionData rdata = RegionInfo2RegionData(regionInfos); 229 RegionData rdata = RegionInfo2RegionData(regionInfos);
225 rdata.ScopeID = scopeID; 230 rdata.ScopeID = scopeID;
@@ -227,10 +232,8 @@ namespace OpenSim.Services.GridService
227 if (region != null) 232 if (region != null)
228 { 233 {
229 int oldFlags = Convert.ToInt32(region.Data["flags"]); 234 int oldFlags = Convert.ToInt32(region.Data["flags"]);
230 if ((oldFlags & (int)OpenSim.Data.RegionFlags.LockedOut) != 0)
231 return "Region locked out";
232 235
233 oldFlags &= ~(int)OpenSim.Data.RegionFlags.Reservation; 236 oldFlags &= ~(int)OpenSim.Framework.RegionFlags.Reservation;
234 237
235 rdata.Data["flags"] = oldFlags.ToString(); // Preserve flags 238 rdata.Data["flags"] = oldFlags.ToString(); // Preserve flags
236 } 239 }
@@ -249,7 +252,7 @@ namespace OpenSim.Services.GridService
249 } 252 }
250 253
251 int flags = Convert.ToInt32(rdata.Data["flags"]); 254 int flags = Convert.ToInt32(rdata.Data["flags"]);
252 flags |= (int)OpenSim.Data.RegionFlags.RegionOnline; 255 flags |= (int)OpenSim.Framework.RegionFlags.RegionOnline;
253 rdata.Data["flags"] = flags.ToString(); 256 rdata.Data["flags"] = flags.ToString();
254 257
255 try 258 try
@@ -280,9 +283,9 @@ namespace OpenSim.Services.GridService
280 283
281 int flags = Convert.ToInt32(region.Data["flags"]); 284 int flags = Convert.ToInt32(region.Data["flags"]);
282 285
283 if (!m_DeleteOnUnregister || (flags & (int)OpenSim.Data.RegionFlags.Persistent) != 0) 286 if (!m_DeleteOnUnregister || (flags & (int)OpenSim.Framework.RegionFlags.Persistent) != 0)
284 { 287 {
285 flags &= ~(int)OpenSim.Data.RegionFlags.RegionOnline; 288 flags &= ~(int)OpenSim.Framework.RegionFlags.RegionOnline;
286 region.Data["flags"] = flags.ToString(); 289 region.Data["flags"] = flags.ToString();
287 region.Data["last_seen"] = Util.UnixTimeSinceEpoch(); 290 region.Data["last_seen"] = Util.UnixTimeSinceEpoch();
288 try 291 try
@@ -317,7 +320,7 @@ namespace OpenSim.Services.GridService
317 if (rdata.RegionID != regionID) 320 if (rdata.RegionID != regionID)
318 { 321 {
319 int flags = Convert.ToInt32(rdata.Data["flags"]); 322 int flags = Convert.ToInt32(rdata.Data["flags"]);
320 if ((flags & (int)Data.RegionFlags.Hyperlink) == 0) // no hyperlinks as neighbours 323 if ((flags & (int)Framework.RegionFlags.Hyperlink) == 0) // no hyperlinks as neighbours
321 rinfos.Add(RegionData2RegionInfo(rdata)); 324 rinfos.Add(RegionData2RegionInfo(rdata));
322 } 325 }
323 } 326 }
@@ -467,7 +470,7 @@ namespace OpenSim.Services.GridService
467 470
468 foreach (RegionData r in regions) 471 foreach (RegionData r in regions)
469 { 472 {
470 if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Data.RegionFlags.RegionOnline) != 0) 473 if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Framework.RegionFlags.RegionOnline) != 0)
471 ret.Add(RegionData2RegionInfo(r)); 474 ret.Add(RegionData2RegionInfo(r));
472 } 475 }
473 476
@@ -483,7 +486,7 @@ namespace OpenSim.Services.GridService
483 486
484 foreach (RegionData r in regions) 487 foreach (RegionData r in regions)
485 { 488 {
486 if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Data.RegionFlags.RegionOnline) != 0) 489 if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Framework.RegionFlags.RegionOnline) != 0)
487 ret.Add(RegionData2RegionInfo(r)); 490 ret.Add(RegionData2RegionInfo(r));
488 } 491 }
489 492
@@ -499,7 +502,7 @@ namespace OpenSim.Services.GridService
499 502
500 foreach (RegionData r in regions) 503 foreach (RegionData r in regions)
501 { 504 {
502 if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Data.RegionFlags.RegionOnline) != 0) 505 if ((Convert.ToInt32(r.Data["flags"]) & (int)OpenSim.Framework.RegionFlags.RegionOnline) != 0)
503 ret.Add(RegionData2RegionInfo(r)); 506 ret.Add(RegionData2RegionInfo(r));
504 } 507 }
505 508
@@ -626,7 +629,7 @@ namespace OpenSim.Services.GridService
626 629
627 private void OutputRegionToConsole(RegionData r) 630 private void OutputRegionToConsole(RegionData r)
628 { 631 {
629 OpenSim.Data.RegionFlags flags = (OpenSim.Data.RegionFlags)Convert.ToInt32(r.Data["flags"]); 632 OpenSim.Framework.RegionFlags flags = (OpenSim.Framework.RegionFlags)Convert.ToInt32(r.Data["flags"]);
630 633
631 ConsoleDisplayList dispList = new ConsoleDisplayList(); 634 ConsoleDisplayList dispList = new ConsoleDisplayList();
632 dispList.AddRow("Region Name", r.RegionName); 635 dispList.AddRow("Region Name", r.RegionName);
@@ -656,7 +659,7 @@ namespace OpenSim.Services.GridService
656 659
657 foreach (RegionData r in regions) 660 foreach (RegionData r in regions)
658 { 661 {
659 OpenSim.Data.RegionFlags flags = (OpenSim.Data.RegionFlags)Convert.ToInt32(r.Data["flags"]); 662 OpenSim.Framework.RegionFlags flags = (OpenSim.Framework.RegionFlags)Convert.ToInt32(r.Data["flags"]);
660 dispTable.AddRow( 663 dispTable.AddRow(
661 r.RegionName, 664 r.RegionName,
662 r.RegionID.ToString(), 665 r.RegionID.ToString(),
@@ -670,7 +673,7 @@ namespace OpenSim.Services.GridService
670 673
671 private int ParseFlags(int prev, string flags) 674 private int ParseFlags(int prev, string flags)
672 { 675 {
673 OpenSim.Data.RegionFlags f = (OpenSim.Data.RegionFlags)prev; 676 OpenSim.Framework.RegionFlags f = (OpenSim.Framework.RegionFlags)prev;
674 677
675 string[] parts = flags.Split(new char[] {',', ' '}, StringSplitOptions.RemoveEmptyEntries); 678 string[] parts = flags.Split(new char[] {',', ' '}, StringSplitOptions.RemoveEmptyEntries);
676 679
@@ -682,18 +685,18 @@ namespace OpenSim.Services.GridService
682 { 685 {
683 if (p.StartsWith("+")) 686 if (p.StartsWith("+"))
684 { 687 {
685 val = (int)Enum.Parse(typeof(OpenSim.Data.RegionFlags), p.Substring(1)); 688 val = (int)Enum.Parse(typeof(OpenSim.Framework.RegionFlags), p.Substring(1));
686 f |= (OpenSim.Data.RegionFlags)val; 689 f |= (OpenSim.Framework.RegionFlags)val;
687 } 690 }
688 else if (p.StartsWith("-")) 691 else if (p.StartsWith("-"))
689 { 692 {
690 val = (int)Enum.Parse(typeof(OpenSim.Data.RegionFlags), p.Substring(1)); 693 val = (int)Enum.Parse(typeof(OpenSim.Framework.RegionFlags), p.Substring(1));
691 f &= ~(OpenSim.Data.RegionFlags)val; 694 f &= ~(OpenSim.Framework.RegionFlags)val;
692 } 695 }
693 else 696 else
694 { 697 {
695 val = (int)Enum.Parse(typeof(OpenSim.Data.RegionFlags), p); 698 val = (int)Enum.Parse(typeof(OpenSim.Framework.RegionFlags), p);
696 f |= (OpenSim.Data.RegionFlags)val; 699 f |= (OpenSim.Framework.RegionFlags)val;
697 } 700 }
698 } 701 }
699 catch (Exception) 702 catch (Exception)
@@ -725,7 +728,7 @@ namespace OpenSim.Services.GridService
725 int flags = Convert.ToInt32(r.Data["flags"]); 728 int flags = Convert.ToInt32(r.Data["flags"]);
726 flags = ParseFlags(flags, cmd[4]); 729 flags = ParseFlags(flags, cmd[4]);
727 r.Data["flags"] = flags.ToString(); 730 r.Data["flags"] = flags.ToString();
728 OpenSim.Data.RegionFlags f = (OpenSim.Data.RegionFlags)flags; 731 OpenSim.Framework.RegionFlags f = (OpenSim.Framework.RegionFlags)flags;
729 732
730 MainConsole.Instance.Output(String.Format("Set region {0} to {1}", r.RegionName, f)); 733 MainConsole.Instance.Output(String.Format("Set region {0} to {1}", r.RegionName, f));
731 m_Database.Store(r); 734 m_Database.Store(r);
diff --git a/OpenSim/Services/GridService/HypergridLinker.cs b/OpenSim/Services/GridService/HypergridLinker.cs
index 78eab3d..743d089 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.Data.RegionFlags rflags = (OpenSim.Data.RegionFlags)Convert.ToInt32(regions[0].Data["flags"]); 393 OpenSim.Framework.RegionFlags rflags = (OpenSim.Framework.RegionFlags)Convert.ToInt32(regions[0].Data["flags"]);
394 if ((rflags & OpenSim.Data.RegionFlags.Hyperlink) != 0) 394 if ((rflags & OpenSim.Framework.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.Data.RegionFlags.Hyperlink + (int)OpenSim.Data.RegionFlags.NoDirectLogin + (int)OpenSim.Data.RegionFlags.RegionOnline; 463 int flags = (int)OpenSim.Framework.RegionFlags.Hyperlink + (int)OpenSim.Framework.RegionFlags.NoDirectLogin + (int)OpenSim.Framework.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 47d22b9..004311f 100644
--- a/OpenSim/Services/HypergridService/GatekeeperService.cs
+++ b/OpenSim/Services/HypergridService/GatekeeperService.cs
@@ -57,10 +57,13 @@ 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;
60 61
61 protected string m_AllowedClients = string.Empty; 62 private static string m_AllowedClients = string.Empty;
62 protected string m_DeniedClients = string.Empty; 63 private static string m_DeniedClients = string.Empty;
63 private static bool m_ForeignAgentsAllowed = true; 64 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>();
64 67
65 private static UUID m_ScopeID; 68 private static UUID m_ScopeID;
66 private static bool m_AllowTeleportsToAnyRegion; 69 private static bool m_AllowTeleportsToAnyRegion;
@@ -82,8 +85,9 @@ namespace OpenSim.Services.HypergridService
82 string gridService = serverConfig.GetString("GridService", String.Empty); 85 string gridService = serverConfig.GetString("GridService", String.Empty);
83 string presenceService = serverConfig.GetString("PresenceService", String.Empty); 86 string presenceService = serverConfig.GetString("PresenceService", String.Empty);
84 string simulationService = serverConfig.GetString("SimulationService", String.Empty); 87 string simulationService = serverConfig.GetString("SimulationService", String.Empty);
88 string gridUserService = serverConfig.GetString("GridUserService", String.Empty);
85 89
86 // These 3 are mandatory, the others aren't 90 // These are mandatory, the others aren't
87 if (gridService == string.Empty || presenceService == string.Empty) 91 if (gridService == string.Empty || presenceService == string.Empty)
88 throw new Exception("Incomplete specifications, Gatekeeper Service cannot function."); 92 throw new Exception("Incomplete specifications, Gatekeeper Service cannot function.");
89 93
@@ -103,6 +107,8 @@ namespace OpenSim.Services.HypergridService
103 m_UserAccountService = ServerUtils.LoadPlugin<IUserAccountService>(accountService, args); 107 m_UserAccountService = ServerUtils.LoadPlugin<IUserAccountService>(accountService, args);
104 if (homeUsersService != string.Empty) 108 if (homeUsersService != string.Empty)
105 m_UserAgentService = ServerUtils.LoadPlugin<IUserAgentService>(homeUsersService, args); 109 m_UserAgentService = ServerUtils.LoadPlugin<IUserAgentService>(homeUsersService, args);
110 if (gridUserService != string.Empty)
111 m_GridUserService = ServerUtils.LoadPlugin<IGridUserService>(gridUserService, args);
106 112
107 if (simService != null) 113 if (simService != null)
108 m_SimulationService = simService; 114 m_SimulationService = simService;
@@ -113,6 +119,9 @@ namespace OpenSim.Services.HypergridService
113 m_DeniedClients = serverConfig.GetString("DeniedClients", string.Empty); 119 m_DeniedClients = serverConfig.GetString("DeniedClients", string.Empty);
114 m_ForeignAgentsAllowed = serverConfig.GetBoolean("ForeignAgentsAllowed", true); 120 m_ForeignAgentsAllowed = serverConfig.GetBoolean("ForeignAgentsAllowed", true);
115 121
122 LoadDomainExceptionsFromConfig(serverConfig, "AllowExcept", m_ForeignsAllowedExceptions);
123 LoadDomainExceptionsFromConfig(serverConfig, "DisallowExcept", m_ForeignsDisallowedExceptions);
124
116 if (m_GridService == null || m_PresenceService == null || m_SimulationService == null) 125 if (m_GridService == null || m_PresenceService == null || m_SimulationService == null)
117 throw new Exception("Unable to load a required plugin, Gatekeeper Service cannot function."); 126 throw new Exception("Unable to load a required plugin, Gatekeeper Service cannot function.");
118 127
@@ -125,6 +134,15 @@ namespace OpenSim.Services.HypergridService
125 { 134 {
126 } 135 }
127 136
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
128 public bool LinkRegion(string regionName, out UUID regionID, out ulong regionHandle, out string externalName, out string imageURL, out string reason) 146 public bool LinkRegion(string regionName, out UUID regionID, out ulong regionHandle, out string externalName, out string imageURL, out string reason)
129 { 147 {
130 regionID = UUID.Zero; 148 regionID = UUID.Zero;
@@ -260,17 +278,26 @@ namespace OpenSim.Services.HypergridService
260 m_log.DebugFormat("[GATEKEEPER SERVICE]: User is ok"); 278 m_log.DebugFormat("[GATEKEEPER SERVICE]: User is ok");
261 279
262 // 280 //
263 // Foreign agents allowed 281 // Foreign agents allowed? Exceptions?
264 // 282 //
265 if (account == null && !m_ForeignAgentsAllowed) 283 if (account == null)
266 { 284 {
267 reason = "Unauthorized"; 285 bool allowed = m_ForeignAgentsAllowed;
268 m_log.InfoFormat("[GATEKEEPER SERVICE]: Foreign agents are not permitted {0} {1}. Refusing service.", 286
269 aCircuit.firstname, aCircuit.lastname); 287 if (m_ForeignAgentsAllowed && IsException(aCircuit, m_ForeignsAllowedExceptions))
270 return false; 288 allowed = false;
271 }
272 289
273 // May want to authorize 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 }
274 301
275 bool isFirstLogin = false; 302 bool isFirstLogin = false;
276 // 303 //
@@ -280,7 +307,8 @@ namespace OpenSim.Services.HypergridService
280 if (presence != null) // it has been placed there by the login service 307 if (presence != null) // it has been placed there by the login service
281 isFirstLogin = true; 308 isFirstLogin = true;
282 309
283 else 310 else
311 {
284 if (!m_PresenceService.LoginAgent(aCircuit.AgentID.ToString(), aCircuit.SessionID, aCircuit.SecureSessionID)) 312 if (!m_PresenceService.LoginAgent(aCircuit.AgentID.ToString(), aCircuit.SessionID, aCircuit.SecureSessionID))
285 { 313 {
286 reason = "Unable to login presence"; 314 reason = "Unable to login presence";
@@ -290,6 +318,26 @@ namespace OpenSim.Services.HypergridService
290 } 318 }
291 m_log.DebugFormat("[GATEKEEPER SERVICE]: Login presence ok"); 319 m_log.DebugFormat("[GATEKEEPER SERVICE]: Login presence ok");
292 320
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
293 // 341 //
294 // Get the region 342 // Get the region
295 // 343 //
@@ -393,6 +441,27 @@ namespace OpenSim.Services.HypergridService
393 441
394 #region Misc 442 #region Misc
395 443
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 }
396 465
397 #endregion 466 #endregion
398 } 467 }
diff --git a/OpenSim/Services/HypergridService/HGAssetService.cs b/OpenSim/Services/HypergridService/HGAssetService.cs
index db98166..84dec8d 100644
--- a/OpenSim/Services/HypergridService/HGAssetService.cs
+++ b/OpenSim/Services/HypergridService/HGAssetService.cs
@@ -58,6 +58,8 @@ namespace OpenSim.Services.HypergridService
58 58
59 private UserAccountCache m_Cache; 59 private UserAccountCache m_Cache;
60 60
61 private AssetPermissions m_AssetPerms;
62
61 public HGAssetService(IConfigSource config, string configName) : base(config, configName) 63 public HGAssetService(IConfigSource config, string configName) : base(config, configName)
62 { 64 {
63 m_log.Debug("[HGAsset Service]: Starting"); 65 m_log.Debug("[HGAsset Service]: Starting");
@@ -80,6 +82,10 @@ namespace OpenSim.Services.HypergridService
80 m_HomeURL = assetConfig.GetString("HomeURI", m_HomeURL); 82 m_HomeURL = assetConfig.GetString("HomeURI", m_HomeURL);
81 83
82 m_Cache = UserAccountCache.CreateUserAccountCache(m_UserAccountService); 84 m_Cache = UserAccountCache.CreateUserAccountCache(m_UserAccountService);
85
86 // Permissions
87 m_AssetPerms = new AssetPermissions(assetConfig);
88
83 } 89 }
84 90
85 #region IAssetService overrides 91 #region IAssetService overrides
@@ -90,6 +96,9 @@ namespace OpenSim.Services.HypergridService
90 if (asset == null) 96 if (asset == null)
91 return null; 97 return null;
92 98
99 if (!m_AssetPerms.AllowedExport(asset.Type))
100 return null;
101
93 if (asset.Metadata.Type == (sbyte)AssetType.Object) 102 if (asset.Metadata.Type == (sbyte)AssetType.Object)
94 asset.Data = AdjustIdentifiers(asset.Data); ; 103 asset.Data = AdjustIdentifiers(asset.Data); ;
95 104
@@ -112,16 +121,27 @@ namespace OpenSim.Services.HypergridService
112 121
113 public override byte[] GetData(string id) 122 public override byte[] GetData(string id)
114 { 123 {
115 byte[] data = base.GetData(id); 124 AssetBase asset = Get(id);
125
126 if (asset == null)
127 return null;
116 128
117 if (data == null) 129 if (!m_AssetPerms.AllowedExport(asset.Type))
118 return null; 130 return null;
119 131
120 return AdjustIdentifiers(data); 132 return asset.Data;
121 } 133 }
122 134
123 //public virtual bool Get(string id, Object sender, AssetRetrieved handler) 135 //public virtual bool Get(string id, Object sender, AssetRetrieved handler)
124 136
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
125 public override bool Delete(string id) 145 public override bool Delete(string id)
126 { 146 {
127 // NOGO 147 // NOGO
diff --git a/OpenSim/Services/HypergridService/HGFriendsService.cs b/OpenSim/Services/HypergridService/HGFriendsService.cs
index 98423d7..a8bcfb2 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, online); 400 m_FriendsSimConnector.StatusNotify(region, foreignUserID, userID.ToString(), online);
401 } 401 }
402 } 402 }
403 } 403 }
diff --git a/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs b/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs
index 6e4b68c..677bd7b 100644
--- a/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs
+++ b/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs
@@ -56,10 +56,12 @@ 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;
59 60
60// private UserAccountCache m_Cache; 61// private UserAccountCache m_Cache;
61 62
62 private ExpiringCache<UUID, List<XInventoryFolder>> m_SuitcaseTrees = new ExpiringCache<UUID, List<XInventoryFolder>>(); 63 private ExpiringCache<UUID, List<XInventoryFolder>> m_SuitcaseTrees = new ExpiringCache<UUID, List<XInventoryFolder>>();
64 private ExpiringCache<UUID, AvatarAppearance> m_Appearances = new ExpiringCache<UUID, AvatarAppearance>();
63 65
64 public HGSuitcaseInventoryService(IConfigSource config, string configName) 66 public HGSuitcaseInventoryService(IConfigSource config, string configName)
65 : base(config, configName) 67 : base(config, configName)
@@ -69,7 +71,7 @@ namespace OpenSim.Services.HypergridService
69 m_ConfigName = configName; 71 m_ConfigName = configName;
70 72
71 if (m_Database == null) 73 if (m_Database == null)
72 m_log.WarnFormat("[XXX]: m_Database is null!"); 74 m_log.ErrorFormat("[HG SUITCASE INVENTORY SERVICE]: m_Database is null!");
73 75
74 // 76 //
75 // Try reading the [InventoryService] section, if it exists 77 // Try reading the [InventoryService] section, if it exists
@@ -77,7 +79,6 @@ namespace OpenSim.Services.HypergridService
77 IConfig invConfig = config.Configs[m_ConfigName]; 79 IConfig invConfig = config.Configs[m_ConfigName];
78 if (invConfig != null) 80 if (invConfig != null)
79 { 81 {
80 // realm = authConfig.GetString("Realm", realm);
81 string userAccountsDll = invConfig.GetString("UserAccountsService", string.Empty); 82 string userAccountsDll = invConfig.GetString("UserAccountsService", string.Empty);
82 if (userAccountsDll == string.Empty) 83 if (userAccountsDll == string.Empty)
83 throw new Exception("Please specify UserAccountsService in HGInventoryService configuration"); 84 throw new Exception("Please specify UserAccountsService in HGInventoryService configuration");
@@ -87,8 +88,14 @@ namespace OpenSim.Services.HypergridService
87 if (m_UserAccountService == null) 88 if (m_UserAccountService == null)
88 throw new Exception(String.Format("Unable to create UserAccountService from {0}", userAccountsDll)); 89 throw new Exception(String.Format("Unable to create UserAccountService from {0}", userAccountsDll));
89 90
90 // legacy configuration [obsolete] 91 string avatarDll = invConfig.GetString("AvatarService", string.Empty);
91 m_HomeURL = invConfig.GetString("ProfileServerURI", string.Empty); 92 if (avatarDll == 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
92 // Preferred 99 // Preferred
93 m_HomeURL = invConfig.GetString("HomeURI", m_HomeURL); 100 m_HomeURL = invConfig.GetString("HomeURI", m_HomeURL);
94 101
@@ -294,7 +301,7 @@ namespace OpenSim.Services.HypergridService
294 301
295 public override bool AddFolder(InventoryFolderBase folder) 302 public override bool AddFolder(InventoryFolderBase folder)
296 { 303 {
297 m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: AddFolder {0} {1}", folder.Name, folder.ParentID); 304 //m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: AddFolder {0} {1}", folder.Name, folder.ParentID);
298 // Let's do a bit of sanity checking, more than the base service does 305 // Let's do a bit of sanity checking, more than the base service does
299 // make sure the given folder's parent folder exists under the suitcase tree of this user 306 // make sure the given folder's parent folder exists under the suitcase tree of this user
300 307
@@ -316,7 +323,7 @@ namespace OpenSim.Services.HypergridService
316 323
317 public override bool UpdateFolder(InventoryFolderBase folder) 324 public override bool UpdateFolder(InventoryFolderBase folder)
318 { 325 {
319 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Update folder {0}, version {1}", folder.ID, folder.Version); 326 //m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Update folder {0}, version {1}", folder.ID, folder.Version);
320 if (!IsWithinSuitcaseTree(folder.Owner, folder.ID)) 327 if (!IsWithinSuitcaseTree(folder.Owner, folder.ID))
321 { 328 {
322 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: folder {0} not within Suitcase tree", folder.Name); 329 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: folder {0} not within Suitcase tree", folder.Name);
@@ -394,7 +401,7 @@ namespace OpenSim.Services.HypergridService
394 return null; 401 return null;
395 } 402 }
396 403
397 if (!IsWithinSuitcaseTree(it.Owner, it.Folder)) 404 if (!IsWithinSuitcaseTree(it.Owner, it.Folder) && !IsPartOfAppearance(it.Owner, it.ID))
398 { 405 {
399 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Item {0} (folder {1}) is not within Suitcase", 406 m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Item {0} (folder {1}) is not within Suitcase",
400 it.Name, it.Folder); 407 it.Name, it.Folder);
@@ -549,6 +556,52 @@ namespace OpenSim.Services.HypergridService
549 else return true; 556 else return true;
550 } 557 }
551 #endregion 558 #endregion
559
560 #region Avatar Appearance
561
562 private AvatarAppearance GetAppearance(UUID principalID)
563 {
564 AvatarAppearance a = null;
565 if (m_Appearances.TryGetValue(principalID, out a))
566 return a;
567
568 a = m_AvatarService.GetAppearance(principalID);
569 m_Appearances.AddOrUpdate(principalID, a, 5 * 60); // 5minutes
570 return a;
571 }
572
573 private bool IsPartOfAppearance(UUID principalID, UUID itemID)
574 {
575 AvatarAppearance a = GetAppearance(principalID);
576
577 if (a == null)
578 return false;
579
580 // Check wearables (body parts and clothes)
581 for (int i = 0; i < a.Wearables.Length; i++)
582 {
583 for (int j = 0; j < a.Wearables[i].Count; j++)
584 {
585 if (a.Wearables[i][j].ItemID == itemID)
586 {
587 //m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: item {0} is a wearable", itemID);
588 return true;
589 }
590 }
591 }
592
593 // Check attachments
594 if (a.GetAttachmentForItem(itemID) != null)
595 {
596 //m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: item {0} is an attachment", itemID);
597 return true;
598 }
599
600 return false;
601 }
602
603 #endregion
604
552 } 605 }
553 606
554} 607}
diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs
index a49993c..416ad16 100644
--- a/OpenSim/Services/HypergridService/UserAgentService.cs
+++ b/OpenSim/Services/HypergridService/UserAgentService.cs
@@ -77,6 +77,10 @@ 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
80 public UserAgentService(IConfigSource config) : this(config, null) 84 public UserAgentService(IConfigSource config) : this(config, null)
81 { 85 {
82 } 86 }
@@ -121,6 +125,12 @@ namespace OpenSim.Services.HypergridService
121 m_PresenceService = ServerUtils.LoadPlugin<IPresenceService>(presenceService, args); 125 m_PresenceService = ServerUtils.LoadPlugin<IPresenceService>(presenceService, args);
122 m_UserAccountService = ServerUtils.LoadPlugin<IUserAccountService>(userAccountService, args); 126 m_UserAccountService = ServerUtils.LoadPlugin<IUserAccountService>(userAccountService, args);
123 127
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
124 m_GridName = serverConfig.GetString("ExternalName", string.Empty); 134 m_GridName = serverConfig.GetString("ExternalName", string.Empty);
125 if (m_GridName == string.Empty) 135 if (m_GridName == string.Empty)
126 { 136 {
@@ -130,10 +140,43 @@ namespace OpenSim.Services.HypergridService
130 if (!m_GridName.EndsWith("/")) 140 if (!m_GridName.EndsWith("/"))
131 m_GridName = m_GridName + "/"; 141 m_GridName = m_GridName + "/";
132 142
133 m_LevelOutsideContacts = serverConfig.GetInt("LevelOutsideContacts", 0);
134 } 143 }
135 } 144 }
136 145
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
137 public GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt) 180 public GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt)
138 { 181 {
139 position = new Vector3(128, 128, 0); lookAt = Vector3.UnitY; 182 position = new Vector3(128, 128, 0); lookAt = Vector3.UnitY;
@@ -166,13 +209,39 @@ namespace OpenSim.Services.HypergridService
166 m_log.DebugFormat("[USER AGENT SERVICE]: Request to login user {0} {1} (@{2}) to grid {3}", 209 m_log.DebugFormat("[USER AGENT SERVICE]: Request to login user {0} {1} (@{2}) to grid {3}",
167 agentCircuit.firstname, agentCircuit.lastname, ((clientIP == null) ? "stored IP" : clientIP.Address.ToString()), gatekeeper.ServerURI); 210 agentCircuit.firstname, agentCircuit.lastname, ((clientIP == null) ? "stored IP" : clientIP.Address.ToString()), gatekeeper.ServerURI);
168 211
169 if (m_UserAccountService.GetUserAccount(UUID.Zero, agentCircuit.AgentID) == null) 212 string gridName = gatekeeper.ServerURI;
213
214 UserAccount account = m_UserAccountService.GetUserAccount(UUID.Zero, agentCircuit.AgentID);
215 if (account == null)
170 { 216 {
171 m_log.WarnFormat("[USER AGENT SERVICE]: Someone attempted to lauch a foreign user from here {0} {1}", agentCircuit.firstname, agentCircuit.lastname); 217 m_log.WarnFormat("[USER AGENT SERVICE]: Someone attempted to lauch a foreign user from here {0} {1}", agentCircuit.firstname, agentCircuit.lastname);
172 reason = "Forbidden to launch your agents from here"; 218 reason = "Forbidden to launch your agents from here";
173 return false; 219 return false;
174 } 220 }
175 221
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
176 // Take the IP address + port of the gatekeeper (reg) plus the info of finalDestination 245 // Take the IP address + port of the gatekeeper (reg) plus the info of finalDestination
177 GridRegion region = new GridRegion(gatekeeper); 246 GridRegion region = new GridRegion(gatekeeper);
178 region.ServerURI = gatekeeper.ServerURI; 247 region.ServerURI = gatekeeper.ServerURI;
@@ -189,7 +258,6 @@ namespace OpenSim.Services.HypergridService
189 258
190 bool success = false; 259 bool success = false;
191 string myExternalIP = string.Empty; 260 string myExternalIP = string.Empty;
192 string gridName = gatekeeper.ServerURI;
193 261
194 m_log.DebugFormat("[USER AGENT SERVICE]: this grid: {0}, desired grid: {1}", m_GridName, gridName); 262 m_log.DebugFormat("[USER AGENT SERVICE]: this grid: {0}, desired grid: {1}", m_GridName, gridName);
195 263
@@ -434,7 +502,7 @@ namespace OpenSim.Services.HypergridService
434 if (region != null) 502 if (region != null)
435 { 503 {
436 m_log.DebugFormat("[USER AGENT SERVICE]: Remote Notify to region {0}, user {1} is {2}", region.RegionName, foreignUserID, (online ? "online" : "offline")); 504 m_log.DebugFormat("[USER AGENT SERVICE]: Remote Notify to region {0}, user {1} is {2}", region.RegionName, foreignUserID, (online ? "online" : "offline"));
437 m_FriendsSimConnector.StatusNotify(region, foreignUserID, userID, online); 505 m_FriendsSimConnector.StatusNotify(region, foreignUserID, userID.ToString(), online);
438 } 506 }
439 } 507 }
440 } 508 }
@@ -586,6 +654,35 @@ namespace OpenSim.Services.HypergridService
586 else 654 else
587 return UUID.Zero; 655 return UUID.Zero;
588 } 656 }
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
589 } 686 }
590 687
591 class TravelingAgentInfo 688 class TravelingAgentInfo
diff --git a/OpenSim/Services/Interfaces/IAssetService.cs b/OpenSim/Services/Interfaces/IAssetService.cs
index 80494f1..3c469c6 100644
--- a/OpenSim/Services/Interfaces/IAssetService.cs
+++ b/OpenSim/Services/Interfaces/IAssetService.cs
@@ -68,7 +68,11 @@ 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">The handler to call back once the asset has been retrieved</param> 71 /// <param name="handler">
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>
72 /// <returns>True if the id was parseable, false otherwise</returns> 76 /// <returns>True if the id was parseable, false otherwise</returns>
73 bool Get(string id, Object sender, AssetRetrieved handler); 77 bool Get(string id, Object sender, AssetRetrieved handler);
74 78
diff --git a/OpenSim/Services/Interfaces/IGridService.cs b/OpenSim/Services/Interfaces/IGridService.cs
index cdcb961..3f4c958 100644
--- a/OpenSim/Services/Interfaces/IGridService.cs
+++ b/OpenSim/Services/Interfaces/IGridService.cs
@@ -100,6 +100,19 @@ 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>
103 int GetRegionFlags(UUID scopeID, UUID regionID); 116 int GetRegionFlags(UUID scopeID, UUID regionID);
104 } 117 }
105 118
diff --git a/OpenSim/Services/Interfaces/IGridUserService.cs b/OpenSim/Services/Interfaces/IGridUserService.cs
index 0a52bfa..2e7237e 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 Dictionary<string, object> ToKeyValuePairs() 83 public virtual 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,7 +96,6 @@ 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
100 99
101 return result; 100 return result;
102 } 101 }
diff --git a/OpenSim/Services/Interfaces/IPresenceService.cs b/OpenSim/Services/Interfaces/IPresenceService.cs
index 8d583ff..90f9842 100644
--- a/OpenSim/Services/Interfaces/IPresenceService.cs
+++ b/OpenSim/Services/Interfaces/IPresenceService.cs
@@ -61,13 +61,49 @@ 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>
64 bool LoginAgent(string userID, UUID sessionID, UUID secureSessionID); 71 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>
65 bool LogoutAgent(UUID sessionID); 78 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>
66 bool LogoutRegionAgents(UUID regionID); 85 bool LogoutRegionAgents(UUID regionID);
67 86
87 /// <summary>
88 /// Update data for an existing session.
89 /// </summary>
90 /// <returns></returns>
91 /// <param name='sessionID'></param>
92 /// <param name='regionID'></param>
68 bool ReportAgent(UUID sessionID, UUID regionID); 93 bool ReportAgent(UUID sessionID, UUID regionID);
69 94
95 /// <summary>
96 /// Get session information for a given session ID.
97 /// </summary>
98 /// <returns></returns>
99 /// <param name='sessionID'></param>
70 PresenceInfo GetAgent(UUID sessionID); 100 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>
71 PresenceInfo[] GetAgents(string[] userIDs); 107 PresenceInfo[] GetAgents(string[] userIDs);
72 } 108 }
73} 109} \ No newline at end of file
diff --git a/OpenSim/Services/InventoryService/XInventoryService.cs b/OpenSim/Services/InventoryService/XInventoryService.cs
index 7518b86..309dab4 100644
--- a/OpenSim/Services/InventoryService/XInventoryService.cs
+++ b/OpenSim/Services/InventoryService/XInventoryService.cs
@@ -94,6 +94,7 @@ 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
97 if (m_Database == null) 98 if (m_Database == null)
98 throw new Exception("Could not find a storage interface in the given module"); 99 throw new Exception("Could not find a storage interface in the given module");
99 } 100 }
@@ -229,10 +230,28 @@ namespace OpenSim.Services.InventoryService
229 public virtual InventoryFolderBase GetFolderForType(UUID principalID, AssetType type) 230 public virtual InventoryFolderBase GetFolderForType(UUID principalID, AssetType type)
230 { 231 {
231// m_log.DebugFormat("[XINVENTORY SERVICE]: Getting folder type {0} for user {1}", type, principalID); 232// 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);
232 251
233 XInventoryFolder[] folders = m_Database.GetFolders( 252 XInventoryFolder[] folders = m_Database.GetFolders(
234 new string[] { "agentID", "type"}, 253 new string[] { "agentID", "parentFolderID", "type"},
235 new string[] { principalID.ToString(), ((int)type).ToString() }); 254 new string[] { rootFolder.Owner.ToString(), rootFolder.ID.ToString(), ((int)type).ToString() });
236 255
237 if (folders.Length == 0) 256 if (folders.Length == 0)
238 { 257 {
@@ -308,22 +327,38 @@ namespace OpenSim.Services.InventoryService
308 if (check != null) 327 if (check != null)
309 return false; 328 return false;
310 329
311 if (folder.Type == (short)AssetType.Folder 330 if (folder.Type != (short)AssetType.Folder && folder.Type != (short)AssetType.Unknown)
312 || folder.Type == (short)AssetType.Unknown
313 || folder.Type == (short)AssetType.OutfitFolder
314 || GetFolderForType(folder.Owner, (AssetType)(folder.Type)) == null)
315 { 331 {
316 XInventoryFolder xFolder = ConvertFromOpenSim(folder); 332 InventoryFolderBase rootFolder = GetRootFolder(folder.Owner);
317 return m_Database.StoreFolder(xFolder); 333
318 } 334 if (rootFolder == null)
319 else 335 {
320 { 336 m_log.WarnFormat(
321 m_log.WarnFormat( 337 "[XINVENTORY]: Found no root folder for {0} in AddFolder() when looking for {1}",
322 "[XINVENTORY]: Folder of type {0} already exists when tried to add {1} to {2} for {3}", 338 folder.Owner, folder.Type);
323 folder.Type, folder.Name, folder.ParentID, folder.Owner); 339
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 }
324 } 358 }
325 359
326 return false; 360 XInventoryFolder xFolder = ConvertFromOpenSim(folder);
361 return m_Database.StoreFolder(xFolder);
327 } 362 }
328 363
329 public virtual bool UpdateFolder(InventoryFolderBase folder) 364 public virtual bool UpdateFolder(InventoryFolderBase folder)
diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs
index 988a9b9..cbb6e6c 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, m_MinLoginLevel, account.UserLevel); 303 firstName, lastName, account.UserLevel, m_MinLoginLevel);
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 ac3d8fd..43fa04b 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 GridUserInfo GetGridUserInfo(string userID) 52 public virtual GridUserInfo GetGridUserInfo(string userID)
53 { 53 {
54 GridUserData d = m_Database.Get(userID); 54 GridUserData d = m_Database.Get(userID);
55 55
@@ -122,17 +122,6 @@ 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
136 public bool SetHome(string userID, UUID homeID, Vector3 homePosition, Vector3 homeLookAt) 125 public bool SetHome(string userID, UUID homeID, Vector3 homePosition, Vector3 homeLookAt)
137 { 126 {
138 GridUserData d = m_Database.Get(userID); 127 GridUserData d = m_Database.Get(userID);
diff --git a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs
index 7598cc3..fc49169 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:InventoryService"); 248 config.Configs["InventoryService"].Set("LocalServiceModule", "OpenSim.Services.InventoryService.dll:XInventoryService");
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 b3a7c9e..87d9410 100644
--- a/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs
+++ b/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs
@@ -199,7 +199,9 @@ 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(UUID.Random(), components[0], parentFolder.Owner, parentFolder.ID); 202 = new InventoryFolderBase(
203 UUID.Random(), components[0], parentFolder.Owner, (short)AssetType.Unknown, parentFolder.ID, 0);
204
203 inventoryService.AddFolder(newFolder); 205 inventoryService.AddFolder(newFolder);
204 206
205 if (components.Length > 1) 207 if (components.Length > 1)
diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs
index 49a8d26..ebdfb4f 100644
--- a/OpenSim/Tests/Common/Mock/TestClient.cs
+++ b/OpenSim/Tests/Common/Mock/TestClient.cs
@@ -531,13 +531,9 @@ namespace OpenSim.Tests.Common.Mock
531 { 531 {
532 } 532 }
533 533
534 public virtual void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, 534 public virtual void SendChatMessage(
535 UUID fromAgentID, byte source, byte audible) 535 string message, byte type, Vector3 fromPos, string fromName,
536 { 536 UUID fromAgentID, UUID ownerID, byte source, byte audible)
537 }
538
539 public virtual void SendChatMessage(byte[] message, byte type, Vector3 fromPos, string fromName,
540 UUID fromAgentID, byte source, byte audible)
541 { 537 {
542 } 538 }
543 539
@@ -939,12 +935,12 @@ namespace OpenSim.Tests.Common.Mock
939 Close(); 935 Close();
940 } 936 }
941 937
942 public void Close(bool c) 938 public void Close()
943 { 939 {
944 Close(); 940 Close(true, false);
945 } 941 }
946 942
947 public void Close() 943 public void Close(bool sendStop, bool force)
948 { 944 {
949 // Fire the callback for this connection closing 945 // Fire the callback for this connection closing
950 // This is necesary to get the presence detector to notice that a client has logged out. 946 // 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
new file mode 100644
index 0000000..bca5979
--- /dev/null
+++ b/OpenSim/Tests/Common/Mock/TestXInventoryDataPlugin.cs
@@ -0,0 +1,131 @@
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 30121fe..57da802 100644
--- a/OpenSim/Tests/Common/TestHelpers.cs
+++ b/OpenSim/Tests/Common/TestHelpers.cs
@@ -95,6 +95,7 @@ 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;
98 } 99 }
99 100
100 /// <summary> 101 /// <summary>
diff --git a/OpenSim/Tests/Torture/NPCTortureTests.cs b/OpenSim/Tests/Performance/NPCPerformanceTests.cs
index 731df68..627765b 100644
--- a/OpenSim/Tests/Torture/NPCTortureTests.cs
+++ b/OpenSim/Tests/Performance/NPCPerformanceTests.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.Torture 50namespace OpenSim.Tests.Performance
51{ 51{
52 /// <summary> 52 /// <summary>
53 /// NPC torture tests 53 /// NPC performance 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.Torture
58 /// earlier tests. 58 /// earlier tests.
59 /// </remarks> 59 /// </remarks>
60 [TestFixture] 60 [TestFixture]
61 public class NPCTortureTests 61 public class NPCPerformanceTests
62 { 62 {
63 private TestScene scene; 63 private TestScene scene;
64 private AvatarFactoryModule afm; 64 private AvatarFactoryModule afm;
diff --git a/OpenSim/Tests/Torture/ObjectTortureTests.cs b/OpenSim/Tests/Performance/ObjectPerformanceTests.cs
index 195d47b..2264d86 100644
--- a/OpenSim/Tests/Torture/ObjectTortureTests.cs
+++ b/OpenSim/Tests/Performance/ObjectPerformanceTests.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.Torture 39namespace OpenSim.Tests.Performance
40{ 40{
41 /// <summary> 41 /// <summary>
42 /// Object torture tests 42 /// Object performance 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.Torture
47 /// earlier tests. 47 /// earlier tests.
48 /// </remarks> 48 /// </remarks>
49 [TestFixture] 49 [TestFixture]
50 public class ObjectTortureTests 50 public class ObjectPerformanceTests
51 { 51 {
52 [TearDown] 52 [TearDown]
53 public void TearDown() 53 public void TearDown()
diff --git a/OpenSim/Tests/Torture/ScriptTortureTests.cs b/OpenSim/Tests/Performance/ScriptPerformanceTests.cs
index 24f278f..d708abd 100644
--- a/OpenSim/Tests/Torture/ScriptTortureTests.cs
+++ b/OpenSim/Tests/Performance/ScriptPerformanceTests.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.Torture 45namespace OpenSim.Tests.Performance
46{ 46{
47 /// <summary> 47 /// <summary>
48 /// Script torture tests 48 /// Script performance 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.Torture
53 /// earlier tests. 53 /// earlier tests.
54 /// </remarks> 54 /// </remarks>
55 [TestFixture] 55 [TestFixture]
56 public class ScriptTortureTests 56 public class ScriptPerformanceTests
57 { 57 {
58 private TestScene m_scene; 58 private TestScene m_scene;
59 private XEngine m_xEngine; 59 private XEngine m_xEngine;
diff --git a/OpenSim/Tests/Stress/VectorRenderModuleStressTests.cs b/OpenSim/Tests/Stress/VectorRenderModuleStressTests.cs
new file mode 100644
index 0000000..1f220c0
--- /dev/null
+++ b/OpenSim/Tests/Stress/VectorRenderModuleStressTests.cs
@@ -0,0 +1,132 @@
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/README.txt b/README.md
index a5dec24..552cdef 100644
--- a/README.txt
+++ b/README.md
@@ -1,8 +1,6 @@
1Welcome to OpenSim! 1Welcome to OpenSim!
2 2
3================== 3# Overview
4==== OVERVIEW ====
5==================
6 4
7OpenSim is a BSD Licensed Open Source project to develop a functioning 5OpenSim is a BSD Licensed Open Source project to develop a functioning
8virtual worlds server platform capable of supporting multiple clients 6virtual worlds server platform capable of supporting multiple clients
@@ -12,16 +10,12 @@ C#, and can run under Mono or the Microsoft .NET runtimes.
12This is considered an alpha release. Some stuff works, a lot doesn't. 10This is considered an alpha release. Some stuff works, a lot doesn't.
13If it breaks, you get to keep *both* pieces. 11If it breaks, you get to keep *both* pieces.
14 12
15========================= 13# Compiling OpenSim
16=== Compiling OpenSim ===
17=========================
18 14
19Please see BUILDING.txt if you downloaded a source distribution and 15Please see BUILDING.md if you downloaded a source distribution and
20need to build OpenSim before running it. 16need to build OpenSim before running it.
21 17
22================================== 18# Running OpenSim on Windows
23=== Running OpenSim on Windows ===
24==================================
25 19
26We recommend that you run OpenSim from a command prompt on Windows in order 20We recommend that you run OpenSim from a command prompt on Windows in order
27to capture any errors. 21to capture any errors.
@@ -33,9 +27,7 @@ To run OpenSim from a command prompt
33 27
34Now see the "Configuring OpenSim" section 28Now see the "Configuring OpenSim" section
35 29
36================================ 30# Running OpenSim on Linux
37=== Running OpenSim on Linux ===
38================================
39 31
40You will need Mono >= 2.4.3 to run OpenSim. On some Linux distributions you 32You will need Mono >= 2.4.3 to run OpenSim. On some Linux distributions you
41may need to install additional packages. See http://opensimulator.org/wiki/Dependencies 33may need to install additional packages. See http://opensimulator.org/wiki/Dependencies
@@ -48,14 +40,12 @@ To run OpenSim, from the unpacked distribution type:
48 40
49Now see the "Configuring OpenSim" section 41Now see the "Configuring OpenSim" section
50 42
51=========================== 43# Configuring OpenSim
52=== Configuring OpenSim ===
53===========================
54 44
55When OpenSim starts for the first time, you will be prompted with a 45When OpenSim starts for the first time, you will be prompted with a
56series of questions that look something like: 46series of questions that look something like:
57 47
58[09-17 03:54:40] DEFAULT REGION CONFIG: Simulator Name [OpenSim Test]: 48 [09-17 03:54:40] DEFAULT REGION CONFIG: Simulator Name [OpenSim Test]:
59 49
60For all the options except simulator name, you can safely hit enter to accept 50For all the options except simulator name, you can safely hit enter to accept
61the default if you want to connect using a client on the same machine or over 51the default if you want to connect using a client on the same machine or over
@@ -72,7 +62,7 @@ in-world. You can also use these details to perform your first login.
72 62
73Once you are presented with a prompt that looks like: 63Once you are presented with a prompt that looks like:
74 64
75 Region (My region name) # 65 Region (My region name) #
76 66
77You have successfully started OpenSim. 67You have successfully started OpenSim.
78 68
@@ -83,9 +73,7 @@ Helpful resources:
83 * http://opensimulator.org/wiki/Configuration 73 * http://opensimulator.org/wiki/Configuration
84 * http://opensimulator.org/wiki/Configuring_Regions 74 * http://opensimulator.org/wiki/Configuring_Regions
85 75
86================================== 76# Connecting to your OpenSim
87=== Connecting to your OpenSim ===
88==================================
89 77
90By default your sim will be available for login on port 9000. You can login by 78By default your sim will be available for login on port 9000. You can login by
91adding -loginuri http://127.0.0.1:9000 to the command that starts Second Life 79adding -loginuri http://127.0.0.1:9000 to the command that starts Second Life
@@ -96,15 +84,11 @@ http://192.168.1.2:9000)
96To login, use the avatar details that you gave for your estate ownership or the 84To login, use the avatar details that you gave for your estate ownership or the
97one you set up using the "create user" command. 85one you set up using the "create user" command.
98 86
99=================== 87# Bug reports
100=== Bug reports ===
101===================
102 88
103In the very likely event of bugs biting you (err, your OpenSim) we 89In the very likely event of bugs biting you (err, your OpenSim) we
104encourage you to see whether the problem has already been reported on 90encourage you to see whether the problem has already been reported on
105the OpenSim mantis system. You can find the OpenSim mantis system at 91the [OpenSim mantis system](http://opensimulator.org/mantis/main_page.php).
106
107 http://opensimulator.org/mantis/main_page.php
108 92
109If your bug has already been reported, you might want to add to the 93If your bug has already been reported, you might want to add to the
110bug description and supply additional information. 94bug description and supply additional information.
@@ -119,9 +103,7 @@ mantis"). Useful information to include:
119 103
120 mono --debug OpenSim.exe 104 mono --debug OpenSim.exe
121 105
122=================================== 106# More Information on OpenSim
123=== More Information on OpenSim ===
124===================================
125 107
126More extensive information on building, running, and configuring 108More extensive information on building, running, and configuring
127OpenSim, as well as how to report bugs, and participate in the OpenSim 109OpenSim, as well as how to report bugs, and participate in the OpenSim
diff --git a/ThirdPartyLicenses/Newtonsoft-JsonDotNet.txt b/ThirdPartyLicenses/Newtonsoft-JsonDotNet.txt
deleted file mode 100644
index 457daca..0000000
--- a/ThirdPartyLicenses/Newtonsoft-JsonDotNet.txt
+++ /dev/null
@@ -1,23 +0,0 @@
1Json.NET
2License: The MIT License
3Copyright (c) 2007 James Newton-King
4
5
6Permission is hereby granted, free of charge, to any person obtaining
7a copy of this software and associated documentation files (the
8"Software"), to deal in the Software without restriction, including
9without limitation the rights to use, copy, modify, merge, publish,
10distribute, sublicense, and/or sell copies of the Software, and to
11permit persons to whom the Software is furnished to do so, subject to
12the following conditions:
13
14The above copyright notice and this permission notice shall be
15included in all copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file
diff --git a/bin/Newtonsoft.Json.Net20.dll b/bin/Newtonsoft.Json.Net20.dll
deleted file mode 100755
index 177d9b5..0000000
--- a/bin/Newtonsoft.Json.Net20.dll
+++ /dev/null
Binary files differ
diff --git a/bin/Newtonsoft.Json.XML b/bin/Newtonsoft.Json.XML
deleted file mode 100644
index 1a1e56c..0000000
--- a/bin/Newtonsoft.Json.XML
+++ /dev/null
@@ -1,5827 +0,0 @@
1<?xml version="1.0"?>
2<doc>
3 <assembly>
4 <name>Newtonsoft.Json.Net20</name>
5 </assembly>
6 <members>
7 <member name="T:Newtonsoft.Json.Bson.BsonReader">
8 <summary>
9 Represents a reader that provides fast, non-cached, forward-only access to serialized Json data.
10 </summary>
11 </member>
12 <member name="T:Newtonsoft.Json.JsonReader">
13 <summary>
14 Represents a reader that provides fast, non-cached, forward-only access to serialized Json data.
15 </summary>
16 </member>
17 <member name="M:Newtonsoft.Json.JsonReader.#ctor">
18 <summary>
19 Initializes a new instance of the <see cref="T:Newtonsoft.Json.JsonReader"/> class with the specified <see cref="T:System.IO.TextReader"/>.
20 </summary>
21 </member>
22 <member name="M:Newtonsoft.Json.JsonReader.Read">
23 <summary>
24 Reads the next JSON token from the stream.
25 </summary>
26 <returns>true if the next token was read successfully; false if there are no more tokens to read.</returns>
27 </member>
28 <member name="M:Newtonsoft.Json.JsonReader.ReadAsBytes">
29 <summary>
30 Reads the next JSON token from the stream as a <see cref="T:Byte[]"/>.
31 </summary>
32 <returns>A <see cref="T:Byte[]"/> or a null reference if the next JSON token is null.</returns>
33 </member>
34 <member name="M:Newtonsoft.Json.JsonReader.Skip">
35 <summary>
36 Skips the children of the current token.
37 </summary>
38 </member>
39 <member name="M:Newtonsoft.Json.JsonReader.SetToken(Newtonsoft.Json.JsonToken)">
40 <summary>
41 Sets the current token.
42 </summary>
43 <param name="newToken">The new token.</param>
44 </member>
45 <member name="M:Newtonsoft.Json.JsonReader.SetToken(Newtonsoft.Json.JsonToken,System.Object)">
46 <summary>
47 Sets the current token and value.
48 </summary>
49 <param name="newToken">The new token.</param>
50 <param name="value">The value.</param>
51 </member>
52 <member name="M:Newtonsoft.Json.JsonReader.SetStateBasedOnCurrent">
53 <summary>
54 Sets the state based on current token type.
55 </summary>
56 </member>
57 <member name="M:Newtonsoft.Json.JsonReader.System#IDisposable#Dispose">
58 <summary>
59 Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
60 </summary>
61 </member>
62 <member name="M:Newtonsoft.Json.JsonReader.Dispose(System.Boolean)">
63 <summary>
64 Releases unmanaged and - optionally - managed resources
65 </summary>
66 <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
67 </member>
68 <member name="M:Newtonsoft.Json.JsonReader.Close">
69 <summary>
70 Changes the <see cref="T:Newtonsoft.Json.JsonReader.State"/> to Closed.
71 </summary>
72 </member>
73 <member name="P:Newtonsoft.Json.JsonReader.CurrentState">
74 <summary>
75 Gets the current reader state.
76 </summary>
77 <value>The current reader state.</value>
78 </member>
79 <member name="P:Newtonsoft.Json.JsonReader.QuoteChar">
80 <summary>
81 Gets the quotation mark character used to enclose the value of a string.
82 </summary>
83 </member>
84 <member name="P:Newtonsoft.Json.JsonReader.TokenType">
85 <summary>
86 Gets the type of the current Json token.
87 </summary>
88 </member>
89 <member name="P:Newtonsoft.Json.JsonReader.Value">
90 <summary>
91 Gets the text value of the current Json token.
92 </summary>
93 </member>
94 <member name="P:Newtonsoft.Json.JsonReader.ValueType">
95 <summary>
96 Gets The Common Language Runtime (CLR) type for the current Json token.
97 </summary>
98 </member>
99 <member name="P:Newtonsoft.Json.JsonReader.Depth">
100 <summary>
101 Gets the depth of the current token in the JSON document.
102 </summary>
103 <value>The depth of the current token in the JSON document.</value>
104 </member>
105 <member name="T:Newtonsoft.Json.JsonReader.State">
106 <summary>
107 Specifies the state of the reader.
108 </summary>
109 </member>
110 <member name="F:Newtonsoft.Json.JsonReader.State.Start">
111 <summary>
112 The Read method has not been called.
113 </summary>
114 </member>
115 <member name="F:Newtonsoft.Json.JsonReader.State.Complete">
116 <summary>
117 The end of the file has been reached successfully.
118 </summary>
119 </member>
120 <member name="F:Newtonsoft.Json.JsonReader.State.Property">
121 <summary>
122 Reader is at a property.
123 </summary>
124 </member>
125 <member name="F:Newtonsoft.Json.JsonReader.State.ObjectStart">
126 <summary>
127 Reader is at the start of an object.
128 </summary>
129 </member>
130 <member name="F:Newtonsoft.Json.JsonReader.State.Object">
131 <summary>
132 Reader is in an object.
133 </summary>
134 </member>
135 <member name="F:Newtonsoft.Json.JsonReader.State.ArrayStart">
136 <summary>
137 Reader is at the start of an array.
138 </summary>
139 </member>
140 <member name="F:Newtonsoft.Json.JsonReader.State.Array">
141 <summary>
142 Reader is in an array.
143 </summary>
144 </member>
145 <member name="F:Newtonsoft.Json.JsonReader.State.Closed">
146 <summary>
147 The Close method has been called.
148 </summary>
149 </member>
150 <member name="F:Newtonsoft.Json.JsonReader.State.PostValue">
151 <summary>
152 Reader has just read a value.
153 </summary>
154 </member>
155 <member name="F:Newtonsoft.Json.JsonReader.State.ConstructorStart">
156 <summary>
157 Reader is at the start of a constructor.
158 </summary>
159 </member>
160 <member name="F:Newtonsoft.Json.JsonReader.State.Constructor">
161 <summary>
162 Reader in a constructor.
163 </summary>
164 </member>
165 <member name="F:Newtonsoft.Json.JsonReader.State.Error">
166 <summary>
167 An error occurred that prevents the read operation from continuing.
168 </summary>
169 </member>
170 <member name="F:Newtonsoft.Json.JsonReader.State.Finished">
171 <summary>
172 The end of the file has been reached successfully.
173 </summary>
174 </member>
175 <member name="M:Newtonsoft.Json.Bson.BsonReader.#ctor(System.IO.Stream)">
176 <summary>
177 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Bson.BsonReader"/> class.
178 </summary>
179 <param name="stream">The stream.</param>
180 </member>
181 <member name="M:Newtonsoft.Json.Bson.BsonReader.#ctor(System.IO.Stream,System.Boolean,System.DateTimeKind)">
182 <summary>
183 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Bson.BsonReader"/> class.
184 </summary>
185 <param name="stream">The stream.</param>
186 <param name="readRootValueAsArray">if set to <c>true</c> the root object will be read as a JSON array.</param>
187 <param name="dateTimeKindHandling">The <see cref="T:System.DateTimeKind"/> used when reading <see cref="T:System.DateTime"/> values from BSON.</param>
188 </member>
189 <member name="M:Newtonsoft.Json.Bson.BsonReader.ReadAsBytes">
190 <summary>
191 Reads the next JSON token from the stream as a <see cref="T:Byte[]"/>.
192 </summary>
193 <returns>
194 A <see cref="T:Byte[]"/> or a null reference if the next JSON token is null.
195 </returns>
196 </member>
197 <member name="M:Newtonsoft.Json.Bson.BsonReader.Read">
198 <summary>
199 Reads the next JSON token from the stream.
200 </summary>
201 <returns>
202 true if the next token was read successfully; false if there are no more tokens to read.
203 </returns>
204 </member>
205 <member name="P:Newtonsoft.Json.Bson.BsonReader.ReadRootValueAsArray">
206 <summary>
207 Gets or sets a value indicating whether the root object will be read as a JSON array.
208 </summary>
209 <value>
210 <c>true</c> if the root object will be read as a JSON array; otherwise, <c>false</c>.
211 </value>
212 </member>
213 <member name="P:Newtonsoft.Json.Bson.BsonReader.DateTimeKindHandling">
214 <summary>
215 Gets or sets the <see cref="T:System.DateTimeKind"/> used when reading <see cref="T:System.DateTime"/> values from BSON.
216 </summary>
217 <value>The <see cref="T:System.DateTimeKind"/> used when reading <see cref="T:System.DateTime"/> values from BSON.</value>
218 </member>
219 <member name="T:Newtonsoft.Json.Bson.BsonWriter">
220 <summary>
221 Represents a writer that provides a fast, non-cached, forward-only way of generating Json data.
222 </summary>
223 </member>
224 <member name="T:Newtonsoft.Json.Linq.JTokenWriter">
225 <summary>
226 Represents a writer that provides a fast, non-cached, forward-only way of generating Json data.
227 </summary>
228 </member>
229 <member name="T:Newtonsoft.Json.JsonWriter">
230 <summary>
231 Represents a writer that provides a fast, non-cached, forward-only way of generating Json data.
232 </summary>
233 </member>
234 <member name="M:Newtonsoft.Json.JsonWriter.#ctor">
235 <summary>
236 Creates an instance of the <c>JsonWriter</c> class.
237 </summary>
238 </member>
239 <member name="M:Newtonsoft.Json.JsonWriter.Flush">
240 <summary>
241 Flushes whatever is in the buffer to the underlying streams and also flushes the underlying stream.
242 </summary>
243 </member>
244 <member name="M:Newtonsoft.Json.JsonWriter.Close">
245 <summary>
246 Closes this stream and the underlying stream.
247 </summary>
248 </member>
249 <member name="M:Newtonsoft.Json.JsonWriter.WriteStartObject">
250 <summary>
251 Writes the beginning of a Json object.
252 </summary>
253 </member>
254 <member name="M:Newtonsoft.Json.JsonWriter.WriteEndObject">
255 <summary>
256 Writes the end of a Json object.
257 </summary>
258 </member>
259 <member name="M:Newtonsoft.Json.JsonWriter.WriteStartArray">
260 <summary>
261 Writes the beginning of a Json array.
262 </summary>
263 </member>
264 <member name="M:Newtonsoft.Json.JsonWriter.WriteEndArray">
265 <summary>
266 Writes the end of an array.
267 </summary>
268 </member>
269 <member name="M:Newtonsoft.Json.JsonWriter.WriteStartConstructor(System.String)">
270 <summary>
271 Writes the start of a constructor with the given name.
272 </summary>
273 <param name="name">The name of the constructor.</param>
274 </member>
275 <member name="M:Newtonsoft.Json.JsonWriter.WriteEndConstructor">
276 <summary>
277 Writes the end constructor.
278 </summary>
279 </member>
280 <member name="M:Newtonsoft.Json.JsonWriter.WritePropertyName(System.String)">
281 <summary>
282 Writes the property name of a name/value pair on a Json object.
283 </summary>
284 <param name="name">The name of the property.</param>
285 </member>
286 <member name="M:Newtonsoft.Json.JsonWriter.WriteEnd">
287 <summary>
288 Writes the end of the current Json object or array.
289 </summary>
290 </member>
291 <member name="M:Newtonsoft.Json.JsonWriter.WriteToken(Newtonsoft.Json.JsonReader)">
292 <summary>
293 Writes the current <see cref="T:Newtonsoft.Json.JsonReader"/> token.
294 </summary>
295 <param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader"/> to read the token from.</param>
296 </member>
297 <member name="M:Newtonsoft.Json.JsonWriter.WriteEnd(Newtonsoft.Json.JsonToken)">
298 <summary>
299 Writes the specified end token.
300 </summary>
301 <param name="token">The end token to write.</param>
302 </member>
303 <member name="M:Newtonsoft.Json.JsonWriter.WriteIndent">
304 <summary>
305 Writes indent characters.
306 </summary>
307 </member>
308 <member name="M:Newtonsoft.Json.JsonWriter.WriteValueDelimiter">
309 <summary>
310 Writes the JSON value delimiter.
311 </summary>
312 </member>
313 <member name="M:Newtonsoft.Json.JsonWriter.WriteIndentSpace">
314 <summary>
315 Writes an indent space.
316 </summary>
317 </member>
318 <member name="M:Newtonsoft.Json.JsonWriter.WriteNull">
319 <summary>
320 Writes a null value.
321 </summary>
322 </member>
323 <member name="M:Newtonsoft.Json.JsonWriter.WriteUndefined">
324 <summary>
325 Writes an undefined value.
326 </summary>
327 </member>
328 <member name="M:Newtonsoft.Json.JsonWriter.WriteRaw(System.String)">
329 <summary>
330 Writes raw JSON without changing the writer's state.
331 </summary>
332 <param name="json">The raw JSON to write.</param>
333 </member>
334 <member name="M:Newtonsoft.Json.JsonWriter.WriteRawValue(System.String)">
335 <summary>
336 Writes raw JSON where a value is expected and updates the writer's state.
337 </summary>
338 <param name="json">The raw JSON to write.</param>
339 </member>
340 <member name="M:Newtonsoft.Json.JsonWriter.WriteValue(System.String)">
341 <summary>
342 Writes a <see cref="T:System.String"/> value.
343 </summary>
344 <param name="value">The <see cref="T:System.String"/> value to write.</param>
345 </member>
346 <member name="M:Newtonsoft.Json.JsonWriter.WriteValue(System.Int32)">
347 <summary>
348 Writes a <see cref="T:System.Int32"/> value.
349 </summary>
350 <param name="value">The <see cref="T:System.Int32"/> value to write.</param>
351 </member>
352 <member name="M:Newtonsoft.Json.JsonWriter.WriteValue(System.UInt32)">
353 <summary>
354 Writes a <see cref="T:System.UInt32"/> value.
355 </summary>
356 <param name="value">The <see cref="T:System.UInt32"/> value to write.</param>
357 </member>
358 <member name="M:Newtonsoft.Json.JsonWriter.WriteValue(System.Int64)">
359 <summary>
360 Writes a <see cref="T:System.Int64"/> value.
361 </summary>
362 <param name="value">The <see cref="T:System.Int64"/> value to write.</param>
363 </member>
364 <member name="M:Newtonsoft.Json.JsonWriter.WriteValue(System.UInt64)">
365 <summary>
366 Writes a <see cref="T:System.UInt64"/> value.
367 </summary>
368 <param name="value">The <see cref="T:System.UInt64"/> value to write.</param>
369 </member>
370 <member name="M:Newtonsoft.Json.JsonWriter.WriteValue(System.Single)">
371 <summary>
372 Writes a <see cref="T:System.Single"/> value.
373 </summary>
374 <param name="value">The <see cref="T:System.Single"/> value to write.</param>
375 </member>
376 <member name="M:Newtonsoft.Json.JsonWriter.WriteValue(System.Double)">
377 <summary>
378 Writes a <see cref="T:System.Double"/> value.
379 </summary>
380 <param name="value">The <see cref="T:System.Double"/> value to write.</param>
381 </member>
382 <member name="M:Newtonsoft.Json.JsonWriter.WriteValue(System.Boolean)">
383 <summary>
384 Writes a <see cref="T:System.Boolean"/> value.
385 </summary>
386 <param name="value">The <see cref="T:System.Boolean"/> value to write.</param>
387 </member>
388 <member name="M:Newtonsoft.Json.JsonWriter.WriteValue(System.Int16)">
389 <summary>
390 Writes a <see cref="T:System.Int16"/> value.
391 </summary>
392 <param name="value">The <see cref="T:System.Int16"/> value to write.</param>
393 </member>
394 <member name="M:Newtonsoft.Json.JsonWriter.WriteValue(System.UInt16)">
395 <summary>
396 Writes a <see cref="T:System.UInt16"/> value.
397 </summary>
398 <param name="value">The <see cref="T:System.UInt16"/> value to write.</param>
399 </member>
400 <member name="M:Newtonsoft.Json.JsonWriter.WriteValue(System.Char)">
401 <summary>
402 Writes a <see cref="T:System.Char"/> value.
403 </summary>
404 <param name="value">The <see cref="T:System.Char"/> value to write.</param>
405 </member>
406 <member name="M:Newtonsoft.Json.JsonWriter.WriteValue(System.Byte)">
407 <summary>
408 Writes a <see cref="T:System.Byte"/> value.
409 </summary>
410 <param name="value">The <see cref="T:System.Byte"/> value to write.</param>
411 </member>
412 <member name="M:Newtonsoft.Json.JsonWriter.WriteValue(System.SByte)">
413 <summary>
414 Writes a <see cref="T:System.SByte"/> value.
415 </summary>
416 <param name="value">The <see cref="T:System.SByte"/> value to write.</param>
417 </member>
418 <member name="M:Newtonsoft.Json.JsonWriter.WriteValue(System.Decimal)">
419 <summary>
420 Writes a <see cref="T:System.Decimal"/> value.
421 </summary>
422 <param name="value">The <see cref="T:System.Decimal"/> value to write.</param>
423 </member>
424 <member name="M:Newtonsoft.Json.JsonWriter.WriteValue(System.DateTime)">
425 <summary>
426 Writes a <see cref="T:System.DateTime"/> value.
427 </summary>
428 <param name="value">The <see cref="T:System.DateTime"/> value to write.</param>
429 </member>
430 <member name="M:Newtonsoft.Json.JsonWriter.WriteValue(System.Nullable{System.Int32})">
431 <summary>
432 Writes a <see cref="T:System.Nullable`1"/> value.
433 </summary>
434 <param name="value">The <see cref="T:System.Nullable`1"/> value to write.</param>
435 </member>
436 <member name="M:Newtonsoft.Json.JsonWriter.WriteValue(System.Nullable{System.UInt32})">
437 <summary>
438 Writes a <see cref="T:System.Nullable`1"/> value.
439 </summary>
440 <param name="value">The <see cref="T:System.Nullable`1"/> value to write.</param>
441 </member>
442 <member name="M:Newtonsoft.Json.JsonWriter.WriteValue(System.Nullable{System.Int64})">
443 <summary>
444 Writes a <see cref="T:System.Nullable`1"/> value.
445 </summary>
446 <param name="value">The <see cref="T:System.Nullable`1"/> value to write.</param>
447 </member>
448 <member name="M:Newtonsoft.Json.JsonWriter.WriteValue(System.Nullable{System.UInt64})">
449 <summary>
450 Writes a <see cref="T:System.Nullable`1"/> value.
451 </summary>
452 <param name="value">The <see cref="T:System.Nullable`1"/> value to write.</param>
453 </member>
454 <member name="M:Newtonsoft.Json.JsonWriter.WriteValue(System.Nullable{System.Single})">
455 <summary>
456 Writes a <see cref="T:System.Nullable`1"/> value.
457 </summary>
458 <param name="value">The <see cref="T:System.Nullable`1"/> value to write.</param>
459 </member>
460 <member name="M:Newtonsoft.Json.JsonWriter.WriteValue(System.Nullable{System.Double})">
461 <summary>
462 Writes a <see cref="T:System.Nullable`1"/> value.
463 </summary>
464 <param name="value">The <see cref="T:System.Nullable`1"/> value to write.</param>
465 </member>
466 <member name="M:Newtonsoft.Json.JsonWriter.WriteValue(System.Nullable{System.Boolean})">
467 <summary>
468 Writes a <see cref="T:System.Nullable`1"/> value.
469 </summary>
470 <param name="value">The <see cref="T:System.Nullable`1"/> value to write.</param>
471 </member>
472 <member name="M:Newtonsoft.Json.JsonWriter.WriteValue(System.Nullable{System.Int16})">
473 <summary>
474 Writes a <see cref="T:System.Nullable`1"/> value.
475 </summary>
476 <param name="value">The <see cref="T:System.Nullable`1"/> value to write.</param>
477 </member>
478 <member name="M:Newtonsoft.Json.JsonWriter.WriteValue(System.Nullable{System.UInt16})">
479 <summary>
480 Writes a <see cref="T:System.Nullable`1"/> value.
481 </summary>
482 <param name="value">The <see cref="T:System.Nullable`1"/> value to write.</param>
483 </member>
484 <member name="M:Newtonsoft.Json.JsonWriter.WriteValue(System.Nullable{System.Char})">
485 <summary>
486 Writes a <see cref="T:System.Nullable`1"/> value.
487 </summary>
488 <param name="value">The <see cref="T:System.Nullable`1"/> value to write.</param>
489 </member>
490 <member name="M:Newtonsoft.Json.JsonWriter.WriteValue(System.Nullable{System.Byte})">
491 <summary>
492 Writes a <see cref="T:System.Nullable`1"/> value.
493 </summary>
494 <param name="value">The <see cref="T:System.Nullable`1"/> value to write.</param>
495 </member>
496 <member name="M:Newtonsoft.Json.JsonWriter.WriteValue(System.Nullable{System.SByte})">
497 <summary>
498 Writes a <see cref="T:System.Nullable`1"/> value.
499 </summary>
500 <param name="value">The <see cref="T:System.Nullable`1"/> value to write.</param>
501 </member>
502 <member name="M:Newtonsoft.Json.JsonWriter.WriteValue(System.Nullable{System.Decimal})">
503 <summary>
504 Writes a <see cref="T:System.Nullable`1"/> value.
505 </summary>
506 <param name="value">The <see cref="T:System.Nullable`1"/> value to write.</param>
507 </member>
508 <member name="M:Newtonsoft.Json.JsonWriter.WriteValue(System.Nullable{System.DateTime})">
509 <summary>
510 Writes a <see cref="T:System.Nullable`1"/> value.
511 </summary>
512 <param name="value">The <see cref="T:System.Nullable`1"/> value to write.</param>
513 </member>
514 <member name="M:Newtonsoft.Json.JsonWriter.WriteValue(System.Byte[])">
515 <summary>
516 Writes a <see cref="T:Byte[]"/> value.
517 </summary>
518 <param name="value">The <see cref="T:Byte[]"/> value to write.</param>
519 </member>
520 <member name="M:Newtonsoft.Json.JsonWriter.WriteValue(System.Object)">
521 <summary>
522 Writes a <see cref="T:System.Object"/> value.
523 An error will raised if the value cannot be written as a single JSON token.
524 </summary>
525 <param name="value">The <see cref="T:System.Object"/> value to write.</param>
526 </member>
527 <member name="M:Newtonsoft.Json.JsonWriter.WriteComment(System.String)">
528 <summary>
529 Writes out a comment <code>/*...*/</code> containing the specified text.
530 </summary>
531 <param name="text">Text to place inside the comment.</param>
532 </member>
533 <member name="M:Newtonsoft.Json.JsonWriter.WriteWhitespace(System.String)">
534 <summary>
535 Writes out the given white space.
536 </summary>
537 <param name="ws">The string of white space characters.</param>
538 </member>
539 <member name="P:Newtonsoft.Json.JsonWriter.Top">
540 <summary>
541 Gets the top.
542 </summary>
543 <value>The top.</value>
544 </member>
545 <member name="P:Newtonsoft.Json.JsonWriter.WriteState">
546 <summary>
547 Gets the state of the writer.
548 </summary>
549 </member>
550 <member name="P:Newtonsoft.Json.JsonWriter.Formatting">
551 <summary>
552 Indicates how the output is formatted.
553 </summary>
554 </member>
555 <member name="M:Newtonsoft.Json.Linq.JTokenWriter.#ctor(Newtonsoft.Json.Linq.JContainer)">
556 <summary>
557 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Linq.JTokenWriter"/> class writing to the given <see cref="T:Newtonsoft.Json.Linq.JContainer"/>.
558 </summary>
559 <param name="container">The container being written to.</param>
560 </member>
561 <member name="M:Newtonsoft.Json.Linq.JTokenWriter.#ctor">
562 <summary>
563 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Linq.JTokenWriter"/> class.
564 </summary>
565 </member>
566 <member name="M:Newtonsoft.Json.Linq.JTokenWriter.Flush">
567 <summary>
568 Flushes whatever is in the buffer to the underlying streams and also flushes the underlying stream.
569 </summary>
570 </member>
571 <member name="M:Newtonsoft.Json.Linq.JTokenWriter.Close">
572 <summary>
573 Closes this stream and the underlying stream.
574 </summary>
575 </member>
576 <member name="M:Newtonsoft.Json.Linq.JTokenWriter.WriteStartObject">
577 <summary>
578 Writes the beginning of a Json object.
579 </summary>
580 </member>
581 <member name="M:Newtonsoft.Json.Linq.JTokenWriter.WriteStartArray">
582 <summary>
583 Writes the beginning of a Json array.
584 </summary>
585 </member>
586 <member name="M:Newtonsoft.Json.Linq.JTokenWriter.WriteStartConstructor(System.String)">
587 <summary>
588 Writes the start of a constructor with the given name.
589 </summary>
590 <param name="name">The name of the constructor.</param>
591 </member>
592 <member name="M:Newtonsoft.Json.Linq.JTokenWriter.WriteEnd(Newtonsoft.Json.JsonToken)">
593 <summary>
594 Writes the end.
595 </summary>
596 <param name="token">The token.</param>
597 </member>
598 <member name="M:Newtonsoft.Json.Linq.JTokenWriter.WritePropertyName(System.String)">
599 <summary>
600 Writes the property name of a name/value pair on a Json object.
601 </summary>
602 <param name="name">The name of the property.</param>
603 </member>
604 <member name="M:Newtonsoft.Json.Linq.JTokenWriter.WriteNull">
605 <summary>
606 Writes a null value.
607 </summary>
608 </member>
609 <member name="M:Newtonsoft.Json.Linq.JTokenWriter.WriteUndefined">
610 <summary>
611 Writes an undefined value.
612 </summary>
613 </member>
614 <member name="M:Newtonsoft.Json.Linq.JTokenWriter.WriteRaw(System.String)">
615 <summary>
616 Writes raw JSON.
617 </summary>
618 <param name="json">The raw JSON to write.</param>
619 </member>
620 <member name="M:Newtonsoft.Json.Linq.JTokenWriter.WriteComment(System.String)">
621 <summary>
622 Writes out a comment <code>/*...*/</code> containing the specified text.
623 </summary>
624 <param name="text">Text to place inside the comment.</param>
625 </member>
626 <member name="M:Newtonsoft.Json.Linq.JTokenWriter.WriteValue(System.String)">
627 <summary>
628 Writes a <see cref="T:System.String"/> value.
629 </summary>
630 <param name="value">The <see cref="T:System.String"/> value to write.</param>
631 </member>
632 <member name="M:Newtonsoft.Json.Linq.JTokenWriter.WriteValue(System.Int32)">
633 <summary>
634 Writes a <see cref="T:System.Int32"/> value.
635 </summary>
636 <param name="value">The <see cref="T:System.Int32"/> value to write.</param>
637 </member>
638 <member name="M:Newtonsoft.Json.Linq.JTokenWriter.WriteValue(System.UInt32)">
639 <summary>
640 Writes a <see cref="T:System.UInt32"/> value.
641 </summary>
642 <param name="value">The <see cref="T:System.UInt32"/> value to write.</param>
643 </member>
644 <member name="M:Newtonsoft.Json.Linq.JTokenWriter.WriteValue(System.Int64)">
645 <summary>
646 Writes a <see cref="T:System.Int64"/> value.
647 </summary>
648 <param name="value">The <see cref="T:System.Int64"/> value to write.</param>
649 </member>
650 <member name="M:Newtonsoft.Json.Linq.JTokenWriter.WriteValue(System.UInt64)">
651 <summary>
652 Writes a <see cref="T:System.UInt64"/> value.
653 </summary>
654 <param name="value">The <see cref="T:System.UInt64"/> value to write.</param>
655 </member>
656 <member name="M:Newtonsoft.Json.Linq.JTokenWriter.WriteValue(System.Single)">
657 <summary>
658 Writes a <see cref="T:System.Single"/> value.
659 </summary>
660 <param name="value">The <see cref="T:System.Single"/> value to write.</param>
661 </member>
662 <member name="M:Newtonsoft.Json.Linq.JTokenWriter.WriteValue(System.Double)">
663 <summary>
664 Writes a <see cref="T:System.Double"/> value.
665 </summary>
666 <param name="value">The <see cref="T:System.Double"/> value to write.</param>
667 </member>
668 <member name="M:Newtonsoft.Json.Linq.JTokenWriter.WriteValue(System.Boolean)">
669 <summary>
670 Writes a <see cref="T:System.Boolean"/> value.
671 </summary>
672 <param name="value">The <see cref="T:System.Boolean"/> value to write.</param>
673 </member>
674 <member name="M:Newtonsoft.Json.Linq.JTokenWriter.WriteValue(System.Int16)">
675 <summary>
676 Writes a <see cref="T:System.Int16"/> value.
677 </summary>
678 <param name="value">The <see cref="T:System.Int16"/> value to write.</param>
679 </member>
680 <member name="M:Newtonsoft.Json.Linq.JTokenWriter.WriteValue(System.UInt16)">
681 <summary>
682 Writes a <see cref="T:System.UInt16"/> value.
683 </summary>
684 <param name="value">The <see cref="T:System.UInt16"/> value to write.</param>
685 </member>
686 <member name="M:Newtonsoft.Json.Linq.JTokenWriter.WriteValue(System.Char)">
687 <summary>
688 Writes a <see cref="T:System.Char"/> value.
689 </summary>
690 <param name="value">The <see cref="T:System.Char"/> value to write.</param>
691 </member>
692 <member name="M:Newtonsoft.Json.Linq.JTokenWriter.WriteValue(System.Byte)">
693 <summary>
694 Writes a <see cref="T:System.Byte"/> value.
695 </summary>
696 <param name="value">The <see cref="T:System.Byte"/> value to write.</param>
697 </member>
698 <member name="M:Newtonsoft.Json.Linq.JTokenWriter.WriteValue(System.SByte)">
699 <summary>
700 Writes a <see cref="T:System.SByte"/> value.
701 </summary>
702 <param name="value">The <see cref="T:System.SByte"/> value to write.</param>
703 </member>
704 <member name="M:Newtonsoft.Json.Linq.JTokenWriter.WriteValue(System.Decimal)">
705 <summary>
706 Writes a <see cref="T:System.Decimal"/> value.
707 </summary>
708 <param name="value">The <see cref="T:System.Decimal"/> value to write.</param>
709 </member>
710 <member name="M:Newtonsoft.Json.Linq.JTokenWriter.WriteValue(System.DateTime)">
711 <summary>
712 Writes a <see cref="T:System.DateTime"/> value.
713 </summary>
714 <param name="value">The <see cref="T:System.DateTime"/> value to write.</param>
715 </member>
716 <member name="M:Newtonsoft.Json.Linq.JTokenWriter.WriteValue(System.Byte[])">
717 <summary>
718 Writes a <see cref="T:Byte[]"/> value.
719 </summary>
720 <param name="value">The <see cref="T:Byte[]"/> value to write.</param>
721 </member>
722 <member name="P:Newtonsoft.Json.Linq.JTokenWriter.Token">
723 <summary>
724 Gets the token being writen.
725 </summary>
726 <value>The token being writen.</value>
727 </member>
728 <member name="M:Newtonsoft.Json.Bson.BsonWriter.#ctor(System.IO.Stream)">
729 <summary>
730 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Bson.BsonWriter"/> class.
731 </summary>
732 <param name="stream">The stream.</param>
733 </member>
734 <member name="M:Newtonsoft.Json.Bson.BsonWriter.Flush">
735 <summary>
736 Flushes whatever is in the buffer to the underlying streams and also flushes the underlying stream.
737 </summary>
738 </member>
739 <member name="M:Newtonsoft.Json.Bson.BsonWriter.WriteEnd(Newtonsoft.Json.JsonToken)">
740 <summary>
741 Writes the end.
742 </summary>
743 <param name="token">The token.</param>
744 </member>
745 <member name="M:Newtonsoft.Json.Bson.BsonWriter.WriteComment(System.String)">
746 <summary>
747 Writes out a comment <code>/*...*/</code> containing the specified text.
748 </summary>
749 <param name="text">Text to place inside the comment.</param>
750 </member>
751 <member name="M:Newtonsoft.Json.Bson.BsonWriter.WriteStartConstructor(System.String)">
752 <summary>
753 Writes the start of a constructor with the given name.
754 </summary>
755 <param name="name">The name of the constructor.</param>
756 </member>
757 <member name="M:Newtonsoft.Json.Bson.BsonWriter.WriteRaw(System.String)">
758 <summary>
759 Writes raw JSON.
760 </summary>
761 <param name="json">The raw JSON to write.</param>
762 </member>
763 <member name="M:Newtonsoft.Json.Bson.BsonWriter.WriteRawValue(System.String)">
764 <summary>
765 Writes raw JSON where a value is expected and updates the writer's state.
766 </summary>
767 <param name="json">The raw JSON to write.</param>
768 </member>
769 <member name="T:Newtonsoft.Json.ConstructorHandling">
770 <summary>
771 Specifies how constructors are used when initializing objects during deserialization by the <see cref="T:Newtonsoft.Json.JsonSerializer"/>.
772 </summary>
773 </member>
774 <member name="F:Newtonsoft.Json.ConstructorHandling.Default">
775 <summary>
776 First attempt to use the public default constructor then fall back to single paramatized constructor.
777 </summary>
778 </member>
779 <member name="F:Newtonsoft.Json.ConstructorHandling.AllowNonPublicDefaultConstructor">
780 <summary>
781 Allow Json.NET to use a non-public default constructor.
782 </summary>
783 </member>
784 <member name="T:Newtonsoft.Json.Converters.BinaryConverter">
785 <summary>
786 Converts a binary value to and from a base 64 string value.
787 </summary>
788 </member>
789 <member name="T:Newtonsoft.Json.JsonConverter">
790 <summary>
791 Converts an object to and from JSON.
792 </summary>
793 </member>
794 <member name="M:Newtonsoft.Json.JsonConverter.WriteJson(Newtonsoft.Json.JsonWriter,System.Object,Newtonsoft.Json.JsonSerializer)">
795 <summary>
796 Writes the JSON representation of the object.
797 </summary>
798 <param name="writer">The <see cref="T:Newtonsoft.Json.JsonWriter"/> to write to.</param>
799 <param name="value">The value.</param>
800 <param name="serializer">The calling serializer.</param>
801 </member>
802 <member name="M:Newtonsoft.Json.JsonConverter.ReadJson(Newtonsoft.Json.JsonReader,System.Type,Newtonsoft.Json.JsonSerializer)">
803 <summary>
804 Reads the JSON representation of the object.
805 </summary>
806 <param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader"/> to read from.</param>
807 <param name="objectType">Type of the object.</param>
808 <param name="serializer">The calling serializer.</param>
809 <returns>The object value.</returns>
810 </member>
811 <member name="M:Newtonsoft.Json.JsonConverter.CanConvert(System.Type)">
812 <summary>
813 Determines whether this instance can convert the specified object type.
814 </summary>
815 <param name="objectType">Type of the object.</param>
816 <returns>
817 <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
818 </returns>
819 </member>
820 <member name="M:Newtonsoft.Json.Converters.BinaryConverter.WriteJson(Newtonsoft.Json.JsonWriter,System.Object,Newtonsoft.Json.JsonSerializer)">
821 <summary>
822 Writes the JSON representation of the object.
823 </summary>
824 <param name="writer">The <see cref="T:Newtonsoft.Json.JsonWriter"/> to write to.</param>
825 <param name="value">The value.</param>
826 <param name="serializer">The calling serializer.</param>
827 </member>
828 <member name="M:Newtonsoft.Json.Converters.BinaryConverter.ReadJson(Newtonsoft.Json.JsonReader,System.Type,Newtonsoft.Json.JsonSerializer)">
829 <summary>
830 Reads the JSON representation of the object.
831 </summary>
832 <param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader"/> to read from.</param>
833 <param name="objectType">Type of the object.</param>
834 <param name="serializer">The calling serializer.</param>
835 <returns>The object value.</returns>
836 </member>
837 <member name="M:Newtonsoft.Json.Converters.BinaryConverter.CanConvert(System.Type)">
838 <summary>
839 Determines whether this instance can convert the specified object type.
840 </summary>
841 <param name="objectType">Type of the object.</param>
842 <returns>
843 <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
844 </returns>
845 </member>
846 <member name="T:Newtonsoft.Json.Converters.CustomCreationConverter`1">
847 <summary>
848 Create a custom object
849 </summary>
850 <typeparam name="T"></typeparam>
851 </member>
852 <member name="M:Newtonsoft.Json.Converters.CustomCreationConverter`1.WriteJson(Newtonsoft.Json.JsonWriter,System.Object,Newtonsoft.Json.JsonSerializer)">
853 <summary>
854 Writes the JSON representation of the object.
855 </summary>
856 <param name="writer">The <see cref="T:Newtonsoft.Json.JsonWriter"/> to write to.</param>
857 <param name="value">The value.</param>
858 <param name="serializer">The calling serializer.</param>
859 </member>
860 <member name="M:Newtonsoft.Json.Converters.CustomCreationConverter`1.ReadJson(Newtonsoft.Json.JsonReader,System.Type,Newtonsoft.Json.JsonSerializer)">
861 <summary>
862 Reads the JSON representation of the object.
863 </summary>
864 <param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader"/> to read from.</param>
865 <param name="objectType">Type of the object.</param>
866 <param name="serializer">The calling serializer.</param>
867 <returns>The object value.</returns>
868 </member>
869 <member name="M:Newtonsoft.Json.Converters.CustomCreationConverter`1.Create(System.Type)">
870 <summary>
871 Creates an object which will then be populated by the serializer.
872 </summary>
873 <param name="objectType">Type of the object.</param>
874 <returns></returns>
875 </member>
876 <member name="M:Newtonsoft.Json.Converters.CustomCreationConverter`1.CanConvert(System.Type)">
877 <summary>
878 Determines whether this instance can convert the specified object type.
879 </summary>
880 <param name="objectType">Type of the object.</param>
881 <returns>
882 <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
883 </returns>
884 </member>
885 <member name="T:Newtonsoft.Json.Converters.DataSetConverter">
886 <summary>
887 Converts a <see cref="T:System.Data.DataSet"/> to and from JSON.
888 </summary>
889 </member>
890 <member name="M:Newtonsoft.Json.Converters.DataSetConverter.WriteJson(Newtonsoft.Json.JsonWriter,System.Object,Newtonsoft.Json.JsonSerializer)">
891 <summary>
892 Writes the JSON representation of the object.
893 </summary>
894 <param name="writer">The <see cref="T:Newtonsoft.Json.JsonWriter"/> to write to.</param>
895 <param name="value">The value.</param>
896 <param name="serializer">The calling serializer.</param>
897 </member>
898 <member name="M:Newtonsoft.Json.Converters.DataSetConverter.ReadJson(Newtonsoft.Json.JsonReader,System.Type,Newtonsoft.Json.JsonSerializer)">
899 <summary>
900 Reads the JSON representation of the object.
901 </summary>
902 <param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader"/> to read from.</param>
903 <param name="objectType">Type of the object.</param>
904 <param name="serializer">The calling serializer.</param>
905 <returns>The object value.</returns>
906 </member>
907 <member name="M:Newtonsoft.Json.Converters.DataSetConverter.CanConvert(System.Type)">
908 <summary>
909 Determines whether this instance can convert the specified value type.
910 </summary>
911 <param name="valueType">Type of the value.</param>
912 <returns>
913 <c>true</c> if this instance can convert the specified value type; otherwise, <c>false</c>.
914 </returns>
915 </member>
916 <member name="T:Newtonsoft.Json.Converters.DataTableConverter">
917 <summary>
918 Converts a <see cref="T:System.Data.DataTable"/> to and from JSON.
919 </summary>
920 </member>
921 <member name="M:Newtonsoft.Json.Converters.DataTableConverter.WriteJson(Newtonsoft.Json.JsonWriter,System.Object,Newtonsoft.Json.JsonSerializer)">
922 <summary>
923 Writes the JSON representation of the object.
924 </summary>
925 <param name="writer">The <see cref="T:Newtonsoft.Json.JsonWriter"/> to write to.</param>
926 <param name="value">The value.</param>
927 <param name="serializer">The calling serializer.</param>
928 </member>
929 <member name="M:Newtonsoft.Json.Converters.DataTableConverter.ReadJson(Newtonsoft.Json.JsonReader,System.Type,Newtonsoft.Json.JsonSerializer)">
930 <summary>
931 Reads the JSON representation of the object.
932 </summary>
933 <param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader"/> to read from.</param>
934 <param name="objectType">Type of the object.</param>
935 <param name="serializer">The calling serializer.</param>
936 <returns>The object value.</returns>
937 </member>
938 <member name="M:Newtonsoft.Json.Converters.DataTableConverter.CanConvert(System.Type)">
939 <summary>
940 Determines whether this instance can convert the specified value type.
941 </summary>
942 <param name="valueType">Type of the value.</param>
943 <returns>
944 <c>true</c> if this instance can convert the specified value type; otherwise, <c>false</c>.
945 </returns>
946 </member>
947 <member name="T:Newtonsoft.Json.Converters.DateTimeConverterBase">
948 <summary>
949 Provides a base class for converting a <see cref="T:System.DateTime"/> to and from JSON.
950 </summary>
951 </member>
952 <member name="M:Newtonsoft.Json.Converters.DateTimeConverterBase.CanConvert(System.Type)">
953 <summary>
954 Determines whether this instance can convert the specified object type.
955 </summary>
956 <param name="objectType">Type of the object.</param>
957 <returns>
958 <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
959 </returns>
960 </member>
961 <member name="T:Newtonsoft.Json.Converters.StringEnumConverter">
962 <summary>
963 Converts an <see cref="T:System.Enum"/> to and from its name string value.
964 </summary>
965 </member>
966 <member name="M:Newtonsoft.Json.Converters.StringEnumConverter.WriteJson(Newtonsoft.Json.JsonWriter,System.Object,Newtonsoft.Json.JsonSerializer)">
967 <summary>
968 Writes the JSON representation of the object.
969 </summary>
970 <param name="writer">The <see cref="T:Newtonsoft.Json.JsonWriter"/> to write to.</param>
971 <param name="value">The value.</param>
972 <param name="serializer">The calling serializer.</param>
973 </member>
974 <member name="M:Newtonsoft.Json.Converters.StringEnumConverter.ReadJson(Newtonsoft.Json.JsonReader,System.Type,Newtonsoft.Json.JsonSerializer)">
975 <summary>
976 Reads the JSON representation of the object.
977 </summary>
978 <param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader"/> to read from.</param>
979 <param name="objectType">Type of the object.</param>
980 <param name="serializer">The calling serializer.</param>
981 <returns>The object value.</returns>
982 </member>
983 <member name="M:Newtonsoft.Json.Converters.StringEnumConverter.CanConvert(System.Type)">
984 <summary>
985 Determines whether this instance can convert the specified object type.
986 </summary>
987 <param name="objectType">Type of the object.</param>
988 <returns>
989 <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
990 </returns>
991 </member>
992 <member name="T:Newtonsoft.Json.Linq.ComponentModel.JPropertyDescriptor">
993 <summary>
994 Represents a view of a <see cref="T:Newtonsoft.Json.Linq.JProperty"/>.
995 </summary>
996 </member>
997 <member name="M:Newtonsoft.Json.Linq.ComponentModel.JPropertyDescriptor.#ctor(System.String,System.Type)">
998 <summary>
999 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Linq.ComponentModel.JPropertyDescriptor"/> class.
1000 </summary>
1001 <param name="name">The name.</param>
1002 <param name="propertyType">Type of the property.</param>
1003 </member>
1004 <member name="M:Newtonsoft.Json.Linq.ComponentModel.JPropertyDescriptor.CanResetValue(System.Object)">
1005 <summary>
1006 When overridden in a derived class, returns whether resetting an object changes its value.
1007 </summary>
1008 <returns>
1009 true if resetting the component changes its value; otherwise, false.
1010 </returns>
1011 <param name="component">The component to test for reset capability.
1012 </param>
1013 </member>
1014 <member name="M:Newtonsoft.Json.Linq.ComponentModel.JPropertyDescriptor.GetValue(System.Object)">
1015 <summary>
1016 When overridden in a derived class, gets the current value of the property on a component.
1017 </summary>
1018 <returns>
1019 The value of a property for a given component.
1020 </returns>
1021 <param name="component">The component with the property for which to retrieve the value.
1022 </param>
1023 </member>
1024 <member name="M:Newtonsoft.Json.Linq.ComponentModel.JPropertyDescriptor.ResetValue(System.Object)">
1025 <summary>
1026 When overridden in a derived class, resets the value for this property of the component to the default value.
1027 </summary>
1028 <param name="component">The component with the property value that is to be reset to the default value.
1029 </param>
1030 </member>
1031 <member name="M:Newtonsoft.Json.Linq.ComponentModel.JPropertyDescriptor.SetValue(System.Object,System.Object)">
1032 <summary>
1033 When overridden in a derived class, sets the value of the component to a different value.
1034 </summary>
1035 <param name="component">The component with the property value that is to be set.
1036 </param><param name="value">The new value.
1037 </param>
1038 </member>
1039 <member name="M:Newtonsoft.Json.Linq.ComponentModel.JPropertyDescriptor.ShouldSerializeValue(System.Object)">
1040 <summary>
1041 When overridden in a derived class, determines a value indicating whether the value of this property needs to be persisted.
1042 </summary>
1043 <returns>
1044 true if the property should be persisted; otherwise, false.
1045 </returns>
1046 <param name="component">The component with the property to be examined for persistence.
1047 </param>
1048 </member>
1049 <member name="P:Newtonsoft.Json.Linq.ComponentModel.JPropertyDescriptor.ComponentType">
1050 <summary>
1051 When overridden in a derived class, gets the type of the component this property is bound to.
1052 </summary>
1053 <returns>
1054 A <see cref="T:System.Type"/> that represents the type of component this property is bound to. When the <see cref="M:System.ComponentModel.PropertyDescriptor.GetValue(System.Object)"/> or <see cref="M:System.ComponentModel.PropertyDescriptor.SetValue(System.Object,System.Object)"/> methods are invoked, the object specified might be an instance of this type.
1055 </returns>
1056 </member>
1057 <member name="P:Newtonsoft.Json.Linq.ComponentModel.JPropertyDescriptor.IsReadOnly">
1058 <summary>
1059 When overridden in a derived class, gets a value indicating whether this property is read-only.
1060 </summary>
1061 <returns>
1062 true if the property is read-only; otherwise, false.
1063 </returns>
1064 </member>
1065 <member name="P:Newtonsoft.Json.Linq.ComponentModel.JPropertyDescriptor.PropertyType">
1066 <summary>
1067 When overridden in a derived class, gets the type of the property.
1068 </summary>
1069 <returns>
1070 A <see cref="T:System.Type"/> that represents the type of the property.
1071 </returns>
1072 </member>
1073 <member name="P:Newtonsoft.Json.Linq.ComponentModel.JPropertyDescriptor.NameHashCode">
1074 <summary>
1075 Gets the hash code for the name of the member.
1076 </summary>
1077 <value></value>
1078 <returns>
1079 The hash code for the name of the member.
1080 </returns>
1081 </member>
1082 <member name="T:Newtonsoft.Json.Linq.ComponentModel.JTypeDescriptor">
1083 <summary>
1084 Represents a view of a <see cref="T:Newtonsoft.Json.Linq.JObject"/>.
1085 </summary>
1086 </member>
1087 <member name="M:Newtonsoft.Json.Linq.ComponentModel.JTypeDescriptor.#ctor(Newtonsoft.Json.Linq.JObject)">
1088 <summary>
1089 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Linq.ComponentModel.JTypeDescriptor"/> class.
1090 </summary>
1091 <param name="value">The value.</param>
1092 </member>
1093 <member name="M:Newtonsoft.Json.Linq.ComponentModel.JTypeDescriptor.GetProperties">
1094 <summary>
1095 Returns the properties for this instance of a component.
1096 </summary>
1097 <returns>
1098 A <see cref="T:System.ComponentModel.PropertyDescriptorCollection"/> that represents the properties for this component instance.
1099 </returns>
1100 </member>
1101 <member name="M:Newtonsoft.Json.Linq.ComponentModel.JTypeDescriptor.GetProperties(System.Attribute[])">
1102 <summary>
1103 Returns the properties for this instance of a component using the attribute array as a filter.
1104 </summary>
1105 <param name="attributes">An array of type <see cref="T:System.Attribute"/> that is used as a filter.</param>
1106 <returns>
1107 A <see cref="T:System.ComponentModel.PropertyDescriptorCollection"/> that represents the filtered properties for this component instance.
1108 </returns>
1109 </member>
1110 <member name="M:Newtonsoft.Json.Linq.ComponentModel.JTypeDescriptor.GetAttributes">
1111 <summary>
1112 Returns a collection of custom attributes for this instance of a component.
1113 </summary>
1114 <returns>
1115 An <see cref="T:System.ComponentModel.AttributeCollection"/> containing the attributes for this object.
1116 </returns>
1117 </member>
1118 <member name="M:Newtonsoft.Json.Linq.ComponentModel.JTypeDescriptor.GetClassName">
1119 <summary>
1120 Returns the class name of this instance of a component.
1121 </summary>
1122 <returns>
1123 The class name of the object, or null if the class does not have a name.
1124 </returns>
1125 </member>
1126 <member name="M:Newtonsoft.Json.Linq.ComponentModel.JTypeDescriptor.GetComponentName">
1127 <summary>
1128 Returns the name of this instance of a component.
1129 </summary>
1130 <returns>
1131 The name of the object, or null if the object does not have a name.
1132 </returns>
1133 </member>
1134 <member name="M:Newtonsoft.Json.Linq.ComponentModel.JTypeDescriptor.GetConverter">
1135 <summary>
1136 Returns a type converter for this instance of a component.
1137 </summary>
1138 <returns>
1139 A <see cref="T:System.ComponentModel.TypeConverter"/> that is the converter for this object, or null if there is no <see cref="T:System.ComponentModel.TypeConverter"/> for this object.
1140 </returns>
1141 </member>
1142 <member name="M:Newtonsoft.Json.Linq.ComponentModel.JTypeDescriptor.GetDefaultEvent">
1143 <summary>
1144 Returns the default event for this instance of a component.
1145 </summary>
1146 <returns>
1147 An <see cref="T:System.ComponentModel.EventDescriptor"/> that represents the default event for this object, or null if this object does not have events.
1148 </returns>
1149 </member>
1150 <member name="M:Newtonsoft.Json.Linq.ComponentModel.JTypeDescriptor.GetDefaultProperty">
1151 <summary>
1152 Returns the default property for this instance of a component.
1153 </summary>
1154 <returns>
1155 A <see cref="T:System.ComponentModel.PropertyDescriptor"/> that represents the default property for this object, or null if this object does not have properties.
1156 </returns>
1157 </member>
1158 <member name="M:Newtonsoft.Json.Linq.ComponentModel.JTypeDescriptor.GetEditor(System.Type)">
1159 <summary>
1160 Returns an editor of the specified type for this instance of a component.
1161 </summary>
1162 <param name="editorBaseType">A <see cref="T:System.Type"/> that represents the editor for this object.</param>
1163 <returns>
1164 An <see cref="T:System.Object"/> of the specified type that is the editor for this object, or null if the editor cannot be found.
1165 </returns>
1166 </member>
1167 <member name="M:Newtonsoft.Json.Linq.ComponentModel.JTypeDescriptor.GetEvents(System.Attribute[])">
1168 <summary>
1169 Returns the events for this instance of a component using the specified attribute array as a filter.
1170 </summary>
1171 <param name="attributes">An array of type <see cref="T:System.Attribute"/> that is used as a filter.</param>
1172 <returns>
1173 An <see cref="T:System.ComponentModel.EventDescriptorCollection"/> that represents the filtered events for this component instance.
1174 </returns>
1175 </member>
1176 <member name="M:Newtonsoft.Json.Linq.ComponentModel.JTypeDescriptor.GetEvents">
1177 <summary>
1178 Returns the events for this instance of a component.
1179 </summary>
1180 <returns>
1181 An <see cref="T:System.ComponentModel.EventDescriptorCollection"/> that represents the events for this component instance.
1182 </returns>
1183 </member>
1184 <member name="M:Newtonsoft.Json.Linq.ComponentModel.JTypeDescriptor.GetPropertyOwner(System.ComponentModel.PropertyDescriptor)">
1185 <summary>
1186 Returns an object that contains the property described by the specified property descriptor.
1187 </summary>
1188 <param name="pd">A <see cref="T:System.ComponentModel.PropertyDescriptor"/> that represents the property whose owner is to be found.</param>
1189 <returns>
1190 An <see cref="T:System.Object"/> that represents the owner of the specified property.
1191 </returns>
1192 </member>
1193 <member name="T:Newtonsoft.Json.Linq.JRaw">
1194 <summary>
1195 Represents a raw JSON string.
1196 </summary>
1197 </member>
1198 <member name="T:Newtonsoft.Json.Linq.JValue">
1199 <summary>
1200 Represents a value in JSON (string, integer, date, etc).
1201 </summary>
1202 </member>
1203 <member name="T:Newtonsoft.Json.Linq.JToken">
1204 <summary>
1205 Represents an abstract JSON token.
1206 </summary>
1207 </member>
1208 <member name="T:Newtonsoft.Json.Linq.IJEnumerable`1">
1209 <summary>
1210 Represents a collection of <see cref="T:Newtonsoft.Json.Linq.JToken"/> objects.
1211 </summary>
1212 <typeparam name="T">The type of token</typeparam>
1213 </member>
1214 <member name="P:Newtonsoft.Json.Linq.IJEnumerable`1.Item(System.Object)">
1215 <summary>
1216 Gets the <see cref="T:Newtonsoft.Json.Linq.IJEnumerable`1"/> with the specified key.
1217 </summary>
1218 <value></value>
1219 </member>
1220 <member name="T:Newtonsoft.Json.IJsonLineInfo">
1221 <summary>
1222 Provides an interface to enable a class to return line and position information.
1223 </summary>
1224 </member>
1225 <member name="M:Newtonsoft.Json.IJsonLineInfo.HasLineInfo">
1226 <summary>
1227 Gets a value indicating whether the class can return line information.
1228 </summary>
1229 <returns>
1230 <c>true</c> if LineNumber and LinePosition can be provided; otherwise, <c>false</c>.
1231 </returns>
1232 </member>
1233 <member name="P:Newtonsoft.Json.IJsonLineInfo.LineNumber">
1234 <summary>
1235 Gets the current line number.
1236 </summary>
1237 <value>The current line number or 0 if no line information is available (for example, HasLineInfo returns false).</value>
1238 </member>
1239 <member name="P:Newtonsoft.Json.IJsonLineInfo.LinePosition">
1240 <summary>
1241 Gets the current line position.
1242 </summary>
1243 <value>The current line position or 0 if no line information is available (for example, HasLineInfo returns false).</value>
1244 </member>
1245 <member name="M:Newtonsoft.Json.Linq.JToken.DeepEquals(Newtonsoft.Json.Linq.JToken,Newtonsoft.Json.Linq.JToken)">
1246 <summary>
1247 Compares the values of two tokens, including the values of all descendant tokens.
1248 </summary>
1249 <param name="t1">The first <see cref="T:Newtonsoft.Json.Linq.JToken"/> to compare.</param>
1250 <param name="t2">The second <see cref="T:Newtonsoft.Json.Linq.JToken"/> to compare.</param>
1251 <returns>true if the tokens are equal; otherwise false.</returns>
1252 </member>
1253 <member name="M:Newtonsoft.Json.Linq.JToken.AddAfterSelf(System.Object)">
1254 <summary>
1255 Adds the specified content immediately after this token.
1256 </summary>
1257 <param name="content">A content object that contains simple content or a collection of content objects to be added after this token.</param>
1258 </member>
1259 <member name="M:Newtonsoft.Json.Linq.JToken.AddBeforeSelf(System.Object)">
1260 <summary>
1261 Adds the specified content immediately before this token.
1262 </summary>
1263 <param name="content">A content object that contains simple content or a collection of content objects to be added before this token.</param>
1264 </member>
1265 <member name="M:Newtonsoft.Json.Linq.JToken.Ancestors">
1266 <summary>
1267 Returns a collection of the ancestor tokens of this token.
1268 </summary>
1269 <returns>A collection of the ancestor tokens of this token.</returns>
1270 </member>
1271 <member name="M:Newtonsoft.Json.Linq.JToken.AfterSelf">
1272 <summary>
1273 Returns a collection of the sibling tokens after this token, in document order.
1274 </summary>
1275 <returns>A collection of the sibling tokens after this tokens, in document order.</returns>
1276 </member>
1277 <member name="M:Newtonsoft.Json.Linq.JToken.BeforeSelf">
1278 <summary>
1279 Returns a collection of the sibling tokens before this token, in document order.
1280 </summary>
1281 <returns>A collection of the sibling tokens before this token, in document order.</returns>
1282 </member>
1283 <member name="M:Newtonsoft.Json.Linq.JToken.Value``1(System.Object)">
1284 <summary>
1285 Gets the <see cref="T:Newtonsoft.Json.Linq.JToken"/> with the specified key converted to the specified type.
1286 </summary>
1287 <typeparam name="T">The type to convert the token to.</typeparam>
1288 <param name="key">The token key.</param>
1289 <returns>The converted token value.</returns>
1290 </member>
1291 <member name="M:Newtonsoft.Json.Linq.JToken.Children">
1292 <summary>
1293 Returns a collection of the child tokens of this token, in document order.
1294 </summary>
1295 <returns>An <see cref="T:System.Collections.Generic.IEnumerable`1"/> of <see cref="T:Newtonsoft.Json.Linq.JToken"/> containing the child tokens of this <see cref="T:Newtonsoft.Json.Linq.JToken"/>, in document order.</returns>
1296 </member>
1297 <member name="M:Newtonsoft.Json.Linq.JToken.Children``1">
1298 <summary>
1299 Returns a collection of the child tokens of this token, in document order, filtered by the specified type.
1300 </summary>
1301 <typeparam name="T">The type to filter the child tokens on.</typeparam>
1302 <returns>A <see cref="T:Newtonsoft.Json.Linq.JEnumerable`1"/> containing the child tokens of this <see cref="T:Newtonsoft.Json.Linq.JToken"/>, in document order.</returns>
1303 </member>
1304 <member name="M:Newtonsoft.Json.Linq.JToken.Values``1">
1305 <summary>
1306 Returns a collection of the child values of this token, in document order.
1307 </summary>
1308 <typeparam name="T">The type to convert the values to.</typeparam>
1309 <returns>A <see cref="T:System.Collections.Generic.IEnumerable`1"/> containing the child values of this <see cref="T:Newtonsoft.Json.Linq.JToken"/>, in document order.</returns>
1310 </member>
1311 <member name="M:Newtonsoft.Json.Linq.JToken.Remove">
1312 <summary>
1313 Removes this token from its parent.
1314 </summary>
1315 </member>
1316 <member name="M:Newtonsoft.Json.Linq.JToken.Replace(Newtonsoft.Json.Linq.JToken)">
1317 <summary>
1318 Replaces this token with the specified token.
1319 </summary>
1320 <param name="value">The value.</param>
1321 </member>
1322 <member name="M:Newtonsoft.Json.Linq.JToken.WriteTo(Newtonsoft.Json.JsonWriter,Newtonsoft.Json.JsonConverter[])">
1323 <summary>
1324 Writes this token to a <see cref="T:Newtonsoft.Json.JsonWriter"/>.
1325 </summary>
1326 <param name="writer">A <see cref="T:Newtonsoft.Json.JsonWriter"/> into which this method will write.</param>
1327 <param name="converters">A collection of <see cref="T:Newtonsoft.Json.JsonConverter"/> which will be used when writing the token.</param>
1328 </member>
1329 <member name="M:Newtonsoft.Json.Linq.JToken.ToString">
1330 <summary>
1331 Returns the indented JSON for this token.
1332 </summary>
1333 <returns>
1334 The indented JSON for this token.
1335 </returns>
1336 </member>
1337 <member name="M:Newtonsoft.Json.Linq.JToken.ToString(Newtonsoft.Json.Formatting,Newtonsoft.Json.JsonConverter[])">
1338 <summary>
1339 Returns the JSON for this token using the given formatting and converters.
1340 </summary>
1341 <param name="formatting">Indicates how the output is formatted.</param>
1342 <param name="converters">A collection of <see cref="T:Newtonsoft.Json.JsonConverter"/> which will be used when writing the token.</param>
1343 <returns>The JSON for this token using the given formatting and converters.</returns>
1344 </member>
1345 <member name="M:Newtonsoft.Json.Linq.JToken.op_Explicit(Newtonsoft.Json.Linq.JToken)~System.Boolean">
1346 <summary>
1347 Performs an explicit conversion from <see cref="T:Newtonsoft.Json.Linq.JToken"/> to <see cref="T:System.Boolean"/>.
1348 </summary>
1349 <param name="value">The value.</param>
1350 <returns>The result of the conversion.</returns>
1351 </member>
1352 <member name="M:Newtonsoft.Json.Linq.JToken.op_Explicit(Newtonsoft.Json.Linq.JToken)~System.Nullable{System.Boolean}">
1353 <summary>
1354 Performs an explicit conversion from <see cref="T:Newtonsoft.Json.Linq.JToken"/> to <see cref="T:System.Nullable`1"/>.
1355 </summary>
1356 <param name="value">The value.</param>
1357 <returns>The result of the conversion.</returns>
1358 </member>
1359 <member name="M:Newtonsoft.Json.Linq.JToken.op_Explicit(Newtonsoft.Json.Linq.JToken)~System.Int64">
1360 <summary>
1361 Performs an explicit conversion from <see cref="T:Newtonsoft.Json.Linq.JToken"/> to <see cref="T:System.Int64"/>.
1362 </summary>
1363 <param name="value">The value.</param>
1364 <returns>The result of the conversion.</returns>
1365 </member>
1366 <member name="M:Newtonsoft.Json.Linq.JToken.op_Explicit(Newtonsoft.Json.Linq.JToken)~System.Nullable{System.DateTime}">
1367 <summary>
1368 Performs an explicit conversion from <see cref="T:Newtonsoft.Json.Linq.JToken"/> to <see cref="T:System.Nullable`1"/>.
1369 </summary>
1370 <param name="value">The value.</param>
1371 <returns>The result of the conversion.</returns>
1372 </member>
1373 <member name="M:Newtonsoft.Json.Linq.JToken.op_Explicit(Newtonsoft.Json.Linq.JToken)~System.Nullable{System.Decimal}">
1374 <summary>
1375 Performs an explicit conversion from <see cref="T:Newtonsoft.Json.Linq.JToken"/> to <see cref="T:System.Nullable`1"/>.
1376 </summary>
1377 <param name="value">The value.</param>
1378 <returns>The result of the conversion.</returns>
1379 </member>
1380 <member name="M:Newtonsoft.Json.Linq.JToken.op_Explicit(Newtonsoft.Json.Linq.JToken)~System.Nullable{System.Double}">
1381 <summary>
1382 Performs an explicit conversion from <see cref="T:Newtonsoft.Json.Linq.JToken"/> to <see cref="T:System.Nullable`1"/>.
1383 </summary>
1384 <param name="value">The value.</param>
1385 <returns>The result of the conversion.</returns>
1386 </member>
1387 <member name="M:Newtonsoft.Json.Linq.JToken.op_Explicit(Newtonsoft.Json.Linq.JToken)~System.Int32">
1388 <summary>
1389 Performs an explicit conversion from <see cref="T:Newtonsoft.Json.Linq.JToken"/> to <see cref="T:System.Int32"/>.
1390 </summary>
1391 <param name="value">The value.</param>
1392 <returns>The result of the conversion.</returns>
1393 </member>
1394 <member name="M:Newtonsoft.Json.Linq.JToken.op_Explicit(Newtonsoft.Json.Linq.JToken)~System.Nullable{System.Int32}">
1395 <summary>
1396 Performs an explicit conversion from <see cref="T:Newtonsoft.Json.Linq.JToken"/> to <see cref="T:System.Nullable`1"/>.
1397 </summary>
1398 <param name="value">The value.</param>
1399 <returns>The result of the conversion.</returns>
1400 </member>
1401 <member name="M:Newtonsoft.Json.Linq.JToken.op_Explicit(Newtonsoft.Json.Linq.JToken)~System.DateTime">
1402 <summary>
1403 Performs an explicit conversion from <see cref="T:Newtonsoft.Json.Linq.JToken"/> to <see cref="T:System.DateTime"/>.
1404 </summary>
1405 <param name="value">The value.</param>
1406 <returns>The result of the conversion.</returns>
1407 </member>
1408 <member name="M:Newtonsoft.Json.Linq.JToken.op_Explicit(Newtonsoft.Json.Linq.JToken)~System.Nullable{System.Int64}">
1409 <summary>
1410 Performs an explicit conversion from <see cref="T:Newtonsoft.Json.Linq.JToken"/> to <see cref="T:System.Nullable`1"/>.
1411 </summary>
1412 <param name="value">The value.</param>
1413 <returns>The result of the conversion.</returns>
1414 </member>
1415 <member name="M:Newtonsoft.Json.Linq.JToken.op_Explicit(Newtonsoft.Json.Linq.JToken)~System.Nullable{System.Single}">
1416 <summary>
1417 Performs an explicit conversion from <see cref="T:Newtonsoft.Json.Linq.JToken"/> to <see cref="T:System.Nullable`1"/>.
1418 </summary>
1419 <param name="value">The value.</param>
1420 <returns>The result of the conversion.</returns>
1421 </member>
1422 <member name="M:Newtonsoft.Json.Linq.JToken.op_Explicit(Newtonsoft.Json.Linq.JToken)~System.Decimal">
1423 <summary>
1424 Performs an explicit conversion from <see cref="T:Newtonsoft.Json.Linq.JToken"/> to <see cref="T:System.Decimal"/>.
1425 </summary>
1426 <param name="value">The value.</param>
1427 <returns>The result of the conversion.</returns>
1428 </member>
1429 <member name="M:Newtonsoft.Json.Linq.JToken.op_Explicit(Newtonsoft.Json.Linq.JToken)~System.Nullable{System.UInt32}">
1430 <summary>
1431 Performs an explicit conversion from <see cref="T:Newtonsoft.Json.Linq.JToken"/> to <see cref="T:System.Nullable`1"/>.
1432 </summary>
1433 <param name="value">The value.</param>
1434 <returns>The result of the conversion.</returns>
1435 </member>
1436 <member name="M:Newtonsoft.Json.Linq.JToken.op_Explicit(Newtonsoft.Json.Linq.JToken)~System.Nullable{System.UInt64}">
1437 <summary>
1438 Performs an explicit conversion from <see cref="T:Newtonsoft.Json.Linq.JToken"/> to <see cref="T:System.Nullable`1"/>.
1439 </summary>
1440 <param name="value">The value.</param>
1441 <returns>The result of the conversion.</returns>
1442 </member>
1443 <member name="M:Newtonsoft.Json.Linq.JToken.op_Explicit(Newtonsoft.Json.Linq.JToken)~System.Double">
1444 <summary>
1445 Performs an explicit conversion from <see cref="T:Newtonsoft.Json.Linq.JToken"/> to <see cref="T:System.Double"/>.
1446 </summary>
1447 <param name="value">The value.</param>
1448 <returns>The result of the conversion.</returns>
1449 </member>
1450 <member name="M:Newtonsoft.Json.Linq.JToken.op_Explicit(Newtonsoft.Json.Linq.JToken)~System.Single">
1451 <summary>
1452 Performs an explicit conversion from <see cref="T:Newtonsoft.Json.Linq.JToken"/> to <see cref="T:System.Single"/>.
1453 </summary>
1454 <param name="value">The value.</param>
1455 <returns>The result of the conversion.</returns>
1456 </member>
1457 <member name="M:Newtonsoft.Json.Linq.JToken.op_Explicit(Newtonsoft.Json.Linq.JToken)~System.String">
1458 <summary>
1459 Performs an explicit conversion from <see cref="T:Newtonsoft.Json.Linq.JToken"/> to <see cref="T:System.String"/>.
1460 </summary>
1461 <param name="value">The value.</param>
1462 <returns>The result of the conversion.</returns>
1463 </member>
1464 <member name="M:Newtonsoft.Json.Linq.JToken.op_Explicit(Newtonsoft.Json.Linq.JToken)~System.UInt32">
1465 <summary>
1466 Performs an explicit conversion from <see cref="T:Newtonsoft.Json.Linq.JToken"/> to <see cref="T:System.UInt32"/>.
1467 </summary>
1468 <param name="value">The value.</param>
1469 <returns>The result of the conversion.</returns>
1470 </member>
1471 <member name="M:Newtonsoft.Json.Linq.JToken.op_Explicit(Newtonsoft.Json.Linq.JToken)~System.UInt64">
1472 <summary>
1473 Performs an explicit conversion from <see cref="T:Newtonsoft.Json.Linq.JToken"/> to <see cref="T:System.UInt64"/>.
1474 </summary>
1475 <param name="value">The value.</param>
1476 <returns>The result of the conversion.</returns>
1477 </member>
1478 <member name="M:Newtonsoft.Json.Linq.JToken.op_Explicit(Newtonsoft.Json.Linq.JToken)~System.Byte[]">
1479 <summary>
1480 Performs an explicit conversion from <see cref="T:Newtonsoft.Json.Linq.JToken"/> to <see cref="T:System.Byte[]"/>.
1481 </summary>
1482 <param name="value">The value.</param>
1483 <returns>The result of the conversion.</returns>
1484 </member>
1485 <member name="M:Newtonsoft.Json.Linq.JToken.op_Implicit(System.Boolean)~Newtonsoft.Json.Linq.JToken">
1486 <summary>
1487 Performs an implicit conversion from <see cref="T:System.Boolean"/> to <see cref="T:Newtonsoft.Json.Linq.JToken"/>.
1488 </summary>
1489 <param name="value">The value to create a <see cref="T:Newtonsoft.Json.Linq.JValue"/> from.</param>
1490 <returns>The <see cref="T:Newtonsoft.Json.Linq.JValue"/> initialized with the specified value.</returns>
1491 </member>
1492 <member name="M:Newtonsoft.Json.Linq.JToken.op_Implicit(System.Nullable{System.Boolean})~Newtonsoft.Json.Linq.JToken">
1493 <summary>
1494 Performs an implicit conversion from <see cref="T:System.Nullable`1"/> to <see cref="T:Newtonsoft.Json.Linq.JToken"/>.
1495 </summary>
1496 <param name="value">The value to create a <see cref="T:Newtonsoft.Json.Linq.JValue"/> from.</param>
1497 <returns>The <see cref="T:Newtonsoft.Json.Linq.JValue"/> initialized with the specified value.</returns>
1498 </member>
1499 <member name="M:Newtonsoft.Json.Linq.JToken.op_Implicit(System.Int64)~Newtonsoft.Json.Linq.JToken">
1500 <summary>
1501 Performs an implicit conversion from <see cref="T:System.Nullable`1"/> to <see cref="T:Newtonsoft.Json.Linq.JToken"/>.
1502 </summary>
1503 <param name="value">The value to create a <see cref="T:Newtonsoft.Json.Linq.JValue"/> from.</param>
1504 <returns>The <see cref="T:Newtonsoft.Json.Linq.JValue"/> initialized with the specified value.</returns>
1505 </member>
1506 <member name="M:Newtonsoft.Json.Linq.JToken.op_Implicit(System.Nullable{System.DateTime})~Newtonsoft.Json.Linq.JToken">
1507 <summary>
1508 Performs an implicit conversion from <see cref="T:System.Nullable`1"/> to <see cref="T:Newtonsoft.Json.Linq.JToken"/>.
1509 </summary>
1510 <param name="value">The value to create a <see cref="T:Newtonsoft.Json.Linq.JValue"/> from.</param>
1511 <returns>The <see cref="T:Newtonsoft.Json.Linq.JValue"/> initialized with the specified value.</returns>
1512 </member>
1513 <member name="M:Newtonsoft.Json.Linq.JToken.op_Implicit(System.Nullable{System.Decimal})~Newtonsoft.Json.Linq.JToken">
1514 <summary>
1515 Performs an implicit conversion from <see cref="T:System.Nullable`1"/> to <see cref="T:Newtonsoft.Json.Linq.JToken"/>.
1516 </summary>
1517 <param name="value">The value to create a <see cref="T:Newtonsoft.Json.Linq.JValue"/> from.</param>
1518 <returns>The <see cref="T:Newtonsoft.Json.Linq.JValue"/> initialized with the specified value.</returns>
1519 </member>
1520 <member name="M:Newtonsoft.Json.Linq.JToken.op_Implicit(System.Nullable{System.Double})~Newtonsoft.Json.Linq.JToken">
1521 <summary>
1522 Performs an implicit conversion from <see cref="T:System.Nullable`1"/> to <see cref="T:Newtonsoft.Json.Linq.JToken"/>.
1523 </summary>
1524 <param name="value">The value to create a <see cref="T:Newtonsoft.Json.Linq.JValue"/> from.</param>
1525 <returns>The <see cref="T:Newtonsoft.Json.Linq.JValue"/> initialized with the specified value.</returns>
1526 </member>
1527 <member name="M:Newtonsoft.Json.Linq.JToken.op_Implicit(System.UInt16)~Newtonsoft.Json.Linq.JToken">
1528 <summary>
1529 Performs an implicit conversion from <see cref="T:System.UInt16"/> to <see cref="T:Newtonsoft.Json.Linq.JToken"/>.
1530 </summary>
1531 <param name="value">The value to create a <see cref="T:Newtonsoft.Json.Linq.JValue"/> from.</param>
1532 <returns>The <see cref="T:Newtonsoft.Json.Linq.JValue"/> initialized with the specified value.</returns>
1533 </member>
1534 <member name="M:Newtonsoft.Json.Linq.JToken.op_Implicit(System.Int32)~Newtonsoft.Json.Linq.JToken">
1535 <summary>
1536 Performs an implicit conversion from <see cref="T:System.Int32"/> to <see cref="T:Newtonsoft.Json.Linq.JToken"/>.
1537 </summary>
1538 <param name="value">The value to create a <see cref="T:Newtonsoft.Json.Linq.JValue"/> from.</param>
1539 <returns>The <see cref="T:Newtonsoft.Json.Linq.JValue"/> initialized with the specified value.</returns>
1540 </member>
1541 <member name="M:Newtonsoft.Json.Linq.JToken.op_Implicit(System.Nullable{System.Int32})~Newtonsoft.Json.Linq.JToken">
1542 <summary>
1543 Performs an implicit conversion from <see cref="T:System.Nullable`1"/> to <see cref="T:Newtonsoft.Json.Linq.JToken"/>.
1544 </summary>
1545 <param name="value">The value to create a <see cref="T:Newtonsoft.Json.Linq.JValue"/> from.</param>
1546 <returns>The <see cref="T:Newtonsoft.Json.Linq.JValue"/> initialized with the specified value.</returns>
1547 </member>
1548 <member name="M:Newtonsoft.Json.Linq.JToken.op_Implicit(System.DateTime)~Newtonsoft.Json.Linq.JToken">
1549 <summary>
1550 Performs an implicit conversion from <see cref="T:System.DateTime"/> to <see cref="T:Newtonsoft.Json.Linq.JToken"/>.
1551 </summary>
1552 <param name="value">The value to create a <see cref="T:Newtonsoft.Json.Linq.JValue"/> from.</param>
1553 <returns>The <see cref="T:Newtonsoft.Json.Linq.JValue"/> initialized with the specified value.</returns>
1554 </member>
1555 <member name="M:Newtonsoft.Json.Linq.JToken.op_Implicit(System.Nullable{System.Int64})~Newtonsoft.Json.Linq.JToken">
1556 <summary>
1557 Performs an implicit conversion from <see cref="T:System.Nullable`1"/> to <see cref="T:Newtonsoft.Json.Linq.JToken"/>.
1558 </summary>
1559 <param name="value">The value to create a <see cref="T:Newtonsoft.Json.Linq.JValue"/> from.</param>
1560 <returns>The <see cref="T:Newtonsoft.Json.Linq.JValue"/> initialized with the specified value.</returns>
1561 </member>
1562 <member name="M:Newtonsoft.Json.Linq.JToken.op_Implicit(System.Nullable{System.Single})~Newtonsoft.Json.Linq.JToken">
1563 <summary>
1564 Performs an implicit conversion from <see cref="T:System.Nullable`1"/> to <see cref="T:Newtonsoft.Json.Linq.JToken"/>.
1565 </summary>
1566 <param name="value">The value to create a <see cref="T:Newtonsoft.Json.Linq.JValue"/> from.</param>
1567 <returns>The <see cref="T:Newtonsoft.Json.Linq.JValue"/> initialized with the specified value.</returns>
1568 </member>
1569 <member name="M:Newtonsoft.Json.Linq.JToken.op_Implicit(System.Decimal)~Newtonsoft.Json.Linq.JToken">
1570 <summary>
1571 Performs an implicit conversion from <see cref="T:System.Decimal"/> to <see cref="T:Newtonsoft.Json.Linq.JToken"/>.
1572 </summary>
1573 <param name="value">The value to create a <see cref="T:Newtonsoft.Json.Linq.JValue"/> from.</param>
1574 <returns>The <see cref="T:Newtonsoft.Json.Linq.JValue"/> initialized with the specified value.</returns>
1575 </member>
1576 <member name="M:Newtonsoft.Json.Linq.JToken.op_Implicit(System.Nullable{System.UInt16})~Newtonsoft.Json.Linq.JToken">
1577 <summary>
1578 Performs an implicit conversion from <see cref="T:System.Nullable`1"/> to <see cref="T:Newtonsoft.Json.Linq.JToken"/>.
1579 </summary>
1580 <param name="value">The value to create a <see cref="T:Newtonsoft.Json.Linq.JValue"/> from.</param>
1581 <returns>The <see cref="T:Newtonsoft.Json.Linq.JValue"/> initialized with the specified value.</returns>
1582 </member>
1583 <member name="M:Newtonsoft.Json.Linq.JToken.op_Implicit(System.Nullable{System.UInt32})~Newtonsoft.Json.Linq.JToken">
1584 <summary>
1585 Performs an implicit conversion from <see cref="T:System.Nullable`1"/> to <see cref="T:Newtonsoft.Json.Linq.JToken"/>.
1586 </summary>
1587 <param name="value">The value to create a <see cref="T:Newtonsoft.Json.Linq.JValue"/> from.</param>
1588 <returns>The <see cref="T:Newtonsoft.Json.Linq.JValue"/> initialized with the specified value.</returns>
1589 </member>
1590 <member name="M:Newtonsoft.Json.Linq.JToken.op_Implicit(System.Nullable{System.UInt64})~Newtonsoft.Json.Linq.JToken">
1591 <summary>
1592 Performs an implicit conversion from <see cref="T:System.Nullable`1"/> to <see cref="T:Newtonsoft.Json.Linq.JToken"/>.
1593 </summary>
1594 <param name="value">The value to create a <see cref="T:Newtonsoft.Json.Linq.JValue"/> from.</param>
1595 <returns>The <see cref="T:Newtonsoft.Json.Linq.JValue"/> initialized with the specified value.</returns>
1596 </member>
1597 <member name="M:Newtonsoft.Json.Linq.JToken.op_Implicit(System.Double)~Newtonsoft.Json.Linq.JToken">
1598 <summary>
1599 Performs an implicit conversion from <see cref="T:System.Double"/> to <see cref="T:Newtonsoft.Json.Linq.JToken"/>.
1600 </summary>
1601 <param name="value">The value to create a <see cref="T:Newtonsoft.Json.Linq.JValue"/> from.</param>
1602 <returns>The <see cref="T:Newtonsoft.Json.Linq.JValue"/> initialized with the specified value.</returns>
1603 </member>
1604 <member name="M:Newtonsoft.Json.Linq.JToken.op_Implicit(System.Single)~Newtonsoft.Json.Linq.JToken">
1605 <summary>
1606 Performs an implicit conversion from <see cref="T:System.Single"/> to <see cref="T:Newtonsoft.Json.Linq.JToken"/>.
1607 </summary>
1608 <param name="value">The value to create a <see cref="T:Newtonsoft.Json.Linq.JValue"/> from.</param>
1609 <returns>The <see cref="T:Newtonsoft.Json.Linq.JValue"/> initialized with the specified value.</returns>
1610 </member>
1611 <member name="M:Newtonsoft.Json.Linq.JToken.op_Implicit(System.String)~Newtonsoft.Json.Linq.JToken">
1612 <summary>
1613 Performs an implicit conversion from <see cref="T:System.String"/> to <see cref="T:Newtonsoft.Json.Linq.JToken"/>.
1614 </summary>
1615 <param name="value">The value to create a <see cref="T:Newtonsoft.Json.Linq.JValue"/> from.</param>
1616 <returns>The <see cref="T:Newtonsoft.Json.Linq.JValue"/> initialized with the specified value.</returns>
1617 </member>
1618 <member name="M:Newtonsoft.Json.Linq.JToken.op_Implicit(System.UInt32)~Newtonsoft.Json.Linq.JToken">
1619 <summary>
1620 Performs an implicit conversion from <see cref="T:System.UInt32"/> to <see cref="T:Newtonsoft.Json.Linq.JToken"/>.
1621 </summary>
1622 <param name="value">The value to create a <see cref="T:Newtonsoft.Json.Linq.JValue"/> from.</param>
1623 <returns>The <see cref="T:Newtonsoft.Json.Linq.JValue"/> initialized with the specified value.</returns>
1624 </member>
1625 <member name="M:Newtonsoft.Json.Linq.JToken.op_Implicit(System.UInt64)~Newtonsoft.Json.Linq.JToken">
1626 <summary>
1627 Performs an implicit conversion from <see cref="T:System.UInt64"/> to <see cref="T:Newtonsoft.Json.Linq.JToken"/>.
1628 </summary>
1629 <param name="value">The value to create a <see cref="T:Newtonsoft.Json.Linq.JValue"/> from.</param>
1630 <returns>The <see cref="T:Newtonsoft.Json.Linq.JValue"/> initialized with the specified value.</returns>
1631 </member>
1632 <member name="M:Newtonsoft.Json.Linq.JToken.op_Implicit(System.Byte[])~Newtonsoft.Json.Linq.JToken">
1633 <summary>
1634 Performs an implicit conversion from <see cref="T:System.Byte[]"/> to <see cref="T:Newtonsoft.Json.Linq.JToken"/>.
1635 </summary>
1636 <param name="value">The value to create a <see cref="T:Newtonsoft.Json.Linq.JValue"/> from.</param>
1637 <returns>The <see cref="T:Newtonsoft.Json.Linq.JValue"/> initialized with the specified value.</returns>
1638 </member>
1639 <member name="M:Newtonsoft.Json.Linq.JToken.CreateReader">
1640 <summary>
1641 Creates an <see cref="T:Newtonsoft.Json.JsonReader"/> for this token.
1642 </summary>
1643 <returns>An <see cref="T:Newtonsoft.Json.JsonReader"/> that can be used to read this token and its descendants.</returns>
1644 </member>
1645 <member name="M:Newtonsoft.Json.Linq.JToken.FromObject(System.Object)">
1646 <summary>
1647 Creates a <see cref="T:Newtonsoft.Json.Linq.JToken"/> from an object.
1648 </summary>
1649 <param name="o">The object that will be used to create <see cref="T:Newtonsoft.Json.Linq.JToken"/>.</param>
1650 <returns>A <see cref="T:Newtonsoft.Json.Linq.JToken"/> with the value of the specified object</returns>
1651 </member>
1652 <member name="M:Newtonsoft.Json.Linq.JToken.FromObject(System.Object,Newtonsoft.Json.JsonSerializer)">
1653 <summary>
1654 Creates a <see cref="T:Newtonsoft.Json.Linq.JToken"/> from an object using the specified <see cref="T:Newtonsoft.Json.JsonSerializer"/>.
1655 </summary>
1656 <param name="o">The object that will be used to create <see cref="T:Newtonsoft.Json.Linq.JToken"/>.</param>
1657 <param name="jsonSerializer">The <see cref="T:Newtonsoft.Json.JsonSerializer"/> that will be used when reading the object.</param>
1658 <returns>A <see cref="T:Newtonsoft.Json.Linq.JToken"/> with the value of the specified object</returns>
1659 </member>
1660 <member name="M:Newtonsoft.Json.Linq.JToken.ReadFrom(Newtonsoft.Json.JsonReader)">
1661 <summary>
1662 Creates a <see cref="T:Newtonsoft.Json.Linq.JToken"/> from a <see cref="T:Newtonsoft.Json.JsonReader"/>.
1663 </summary>
1664 <param name="reader">An <see cref="T:Newtonsoft.Json.JsonReader"/> positioned at the token to read into this <see cref="T:Newtonsoft.Json.Linq.JToken"/>.</param>
1665 <returns>
1666 An <see cref="T:Newtonsoft.Json.Linq.JToken"/> that contains the token and its descendant tokens
1667 that were read from the reader. The runtime type of the token is determined
1668 by the token type of the first token encountered in the reader.
1669 </returns>
1670 </member>
1671 <member name="M:Newtonsoft.Json.Linq.JToken.SelectToken(System.String)">
1672 <summary>
1673 Selects the token that matches the object path.
1674 </summary>
1675 <param name="path">
1676 The object path from the current <see cref="T:Newtonsoft.Json.Linq.JToken"/> to the <see cref="T:Newtonsoft.Json.Linq.JToken"/>
1677 to be returned. This must be a string of property names or array indexes separated
1678 by periods, such as <code>Tables[0].DefaultView[0].Price</code> in C# or
1679 <code>Tables(0).DefaultView(0).Price</code> in Visual Basic.
1680 </param>
1681 <returns>The <see cref="T:Newtonsoft.Json.Linq.JToken"/> that matches the object path or a null reference if no matching token is found.</returns>
1682 </member>
1683 <member name="M:Newtonsoft.Json.Linq.JToken.SelectToken(System.String,System.Boolean)">
1684 <summary>
1685 Selects the token that matches the object path.
1686 </summary>
1687 <param name="path">
1688 The object path from the current <see cref="T:Newtonsoft.Json.Linq.JToken"/> to the <see cref="T:Newtonsoft.Json.Linq.JToken"/>
1689 to be returned. This must be a string of property names or array indexes separated
1690 by periods, such as <code>Tables[0].DefaultView[0].Price</code> in C# or
1691 <code>Tables(0).DefaultView(0).Price</code> in Visual Basic.
1692 </param>
1693 <param name="errorWhenNoMatch">A flag to indicate whether an error should be thrown if no token is found.</param>
1694 <returns>The <see cref="T:Newtonsoft.Json.Linq.JToken"/> that matches the object path.</returns>
1695 </member>
1696 <member name="P:Newtonsoft.Json.Linq.JToken.EqualityComparer">
1697 <summary>
1698 Gets a comparer that can compare two tokens for value equality.
1699 </summary>
1700 <value>A <see cref="T:Newtonsoft.Json.Linq.JTokenEqualityComparer"/> that can compare two nodes for value equality.</value>
1701 </member>
1702 <member name="P:Newtonsoft.Json.Linq.JToken.Parent">
1703 <summary>
1704 Gets or sets the parent.
1705 </summary>
1706 <value>The parent.</value>
1707 </member>
1708 <member name="P:Newtonsoft.Json.Linq.JToken.Root">
1709 <summary>
1710 Gets the root <see cref="T:Newtonsoft.Json.Linq.JToken"/> of this <see cref="T:Newtonsoft.Json.Linq.JToken"/>.
1711 </summary>
1712 <value>The root <see cref="T:Newtonsoft.Json.Linq.JToken"/> of this <see cref="T:Newtonsoft.Json.Linq.JToken"/>.</value>
1713 </member>
1714 <member name="P:Newtonsoft.Json.Linq.JToken.Type">
1715 <summary>
1716 Gets the node type for this <see cref="T:Newtonsoft.Json.Linq.JToken"/>.
1717 </summary>
1718 <value>The type.</value>
1719 </member>
1720 <member name="P:Newtonsoft.Json.Linq.JToken.HasValues">
1721 <summary>
1722 Gets a value indicating whether this token has childen tokens.
1723 </summary>
1724 <value>
1725 <c>true</c> if this token has child values; otherwise, <c>false</c>.
1726 </value>
1727 </member>
1728 <member name="P:Newtonsoft.Json.Linq.JToken.Next">
1729 <summary>
1730 Gets the next sibling token of this node.
1731 </summary>
1732 <value>The <see cref="T:Newtonsoft.Json.Linq.JToken"/> that contains the next sibling token.</value>
1733 </member>
1734 <member name="P:Newtonsoft.Json.Linq.JToken.Previous">
1735 <summary>
1736 Gets the previous sibling token of this node.
1737 </summary>
1738 <value>The <see cref="T:Newtonsoft.Json.Linq.JToken"/> that contains the previous sibling token.</value>
1739 </member>
1740 <member name="P:Newtonsoft.Json.Linq.JToken.Item(System.Object)">
1741 <summary>
1742 Gets the <see cref="T:Newtonsoft.Json.Linq.JToken"/> with the specified key.
1743 </summary>
1744 <value>The <see cref="T:Newtonsoft.Json.Linq.JToken"/> with the specified key.</value>
1745 </member>
1746 <member name="P:Newtonsoft.Json.Linq.JToken.First">
1747 <summary>
1748 Get the first child token of this token.
1749 </summary>
1750 <value>A <see cref="T:Newtonsoft.Json.Linq.JToken"/> containing the first child token of the <see cref="T:Newtonsoft.Json.Linq.JToken"/>.</value>
1751 </member>
1752 <member name="P:Newtonsoft.Json.Linq.JToken.Last">
1753 <summary>
1754 Get the last child token of this token.
1755 </summary>
1756 <value>A <see cref="T:Newtonsoft.Json.Linq.JToken"/> containing the last child token of the <see cref="T:Newtonsoft.Json.Linq.JToken"/>.</value>
1757 </member>
1758 <member name="M:Newtonsoft.Json.Linq.JValue.#ctor(Newtonsoft.Json.Linq.JValue)">
1759 <summary>
1760 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Linq.JValue"/> class from another <see cref="T:Newtonsoft.Json.Linq.JValue"/> object.
1761 </summary>
1762 <param name="other">A <see cref="T:Newtonsoft.Json.Linq.JValue"/> object to copy from.</param>
1763 </member>
1764 <member name="M:Newtonsoft.Json.Linq.JValue.#ctor(System.Int64)">
1765 <summary>
1766 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Linq.JValue"/> class with the given value.
1767 </summary>
1768 <param name="value">The value.</param>
1769 </member>
1770 <member name="M:Newtonsoft.Json.Linq.JValue.#ctor(System.UInt64)">
1771 <summary>
1772 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Linq.JValue"/> class with the given value.
1773 </summary>
1774 <param name="value">The value.</param>
1775 </member>
1776 <member name="M:Newtonsoft.Json.Linq.JValue.#ctor(System.Double)">
1777 <summary>
1778 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Linq.JValue"/> class with the given value.
1779 </summary>
1780 <param name="value">The value.</param>
1781 </member>
1782 <member name="M:Newtonsoft.Json.Linq.JValue.#ctor(System.DateTime)">
1783 <summary>
1784 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Linq.JValue"/> class with the given value.
1785 </summary>
1786 <param name="value">The value.</param>
1787 </member>
1788 <member name="M:Newtonsoft.Json.Linq.JValue.#ctor(System.Boolean)">
1789 <summary>
1790 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Linq.JValue"/> class with the given value.
1791 </summary>
1792 <param name="value">The value.</param>
1793 </member>
1794 <member name="M:Newtonsoft.Json.Linq.JValue.#ctor(System.String)">
1795 <summary>
1796 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Linq.JValue"/> class with the given value.
1797 </summary>
1798 <param name="value">The value.</param>
1799 </member>
1800 <member name="M:Newtonsoft.Json.Linq.JValue.#ctor(System.Object)">
1801 <summary>
1802 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Linq.JValue"/> class with the given value.
1803 </summary>
1804 <param name="value">The value.</param>
1805 </member>
1806 <member name="M:Newtonsoft.Json.Linq.JValue.CreateComment(System.String)">
1807 <summary>
1808 Creates a <see cref="T:Newtonsoft.Json.Linq.JValue"/> comment with the given value.
1809 </summary>
1810 <param name="value">The value.</param>
1811 <returns>A <see cref="T:Newtonsoft.Json.Linq.JValue"/> comment with the given value.</returns>
1812 </member>
1813 <member name="M:Newtonsoft.Json.Linq.JValue.CreateString(System.String)">
1814 <summary>
1815 Creates a <see cref="T:Newtonsoft.Json.Linq.JValue"/> string with the given value.
1816 </summary>
1817 <param name="value">The value.</param>
1818 <returns>A <see cref="T:Newtonsoft.Json.Linq.JValue"/> string with the given value.</returns>
1819 </member>
1820 <member name="M:Newtonsoft.Json.Linq.JValue.WriteTo(Newtonsoft.Json.JsonWriter,Newtonsoft.Json.JsonConverter[])">
1821 <summary>
1822 Writes this token to a <see cref="T:Newtonsoft.Json.JsonWriter"/>.
1823 </summary>
1824 <param name="writer">A <see cref="T:Newtonsoft.Json.JsonWriter"/> into which this method will write.</param>
1825 <param name="converters">A collection of <see cref="T:Newtonsoft.Json.JsonConverter"/> which will be used when writing the token.</param>
1826 </member>
1827 <member name="M:Newtonsoft.Json.Linq.JValue.Equals(Newtonsoft.Json.Linq.JValue)">
1828 <summary>
1829 Indicates whether the current object is equal to another object of the same type.
1830 </summary>
1831 <returns>
1832 true if the current object is equal to the <paramref name="other"/> parameter; otherwise, false.
1833 </returns>
1834 <param name="other">An object to compare with this object.</param>
1835 </member>
1836 <member name="M:Newtonsoft.Json.Linq.JValue.Equals(System.Object)">
1837 <summary>
1838 Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>.
1839 </summary>
1840 <param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>.</param>
1841 <returns>
1842 true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false.
1843 </returns>
1844 <exception cref="T:System.NullReferenceException">
1845 The <paramref name="obj"/> parameter is null.
1846 </exception>
1847 </member>
1848 <member name="M:Newtonsoft.Json.Linq.JValue.GetHashCode">
1849 <summary>
1850 Serves as a hash function for a particular type.
1851 </summary>
1852 <returns>
1853 A hash code for the current <see cref="T:System.Object"/>.
1854 </returns>
1855 </member>
1856 <member name="P:Newtonsoft.Json.Linq.JValue.HasValues">
1857 <summary>
1858 Gets a value indicating whether this token has childen tokens.
1859 </summary>
1860 <value>
1861 <c>true</c> if this token has child values; otherwise, <c>false</c>.
1862 </value>
1863 </member>
1864 <member name="P:Newtonsoft.Json.Linq.JValue.Type">
1865 <summary>
1866 Gets the node type for this <see cref="T:Newtonsoft.Json.Linq.JToken"/>.
1867 </summary>
1868 <value>The type.</value>
1869 </member>
1870 <member name="P:Newtonsoft.Json.Linq.JValue.Value">
1871 <summary>
1872 Gets or sets the underlying token value.
1873 </summary>
1874 <value>The underlying token value.</value>
1875 </member>
1876 <member name="M:Newtonsoft.Json.Linq.JRaw.#ctor(Newtonsoft.Json.Linq.JRaw)">
1877 <summary>
1878 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Linq.JRaw"/> class from another <see cref="T:Newtonsoft.Json.Linq.JRaw"/> object.
1879 </summary>
1880 <param name="other">A <see cref="T:Newtonsoft.Json.Linq.JRaw"/> object to copy from.</param>
1881 </member>
1882 <member name="M:Newtonsoft.Json.Linq.JRaw.#ctor(System.String)">
1883 <summary>
1884 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Linq.JRaw"/> class.
1885 </summary>
1886 <param name="rawJson">The raw json.</param>
1887 </member>
1888 <member name="M:Newtonsoft.Json.Linq.JRaw.Create(Newtonsoft.Json.JsonReader)">
1889 <summary>
1890 Creates an instance of <see cref="T:Newtonsoft.Json.Linq.JRaw"/> with the content of the reader's current token.
1891 </summary>
1892 <param name="reader">The reader.</param>
1893 <returns>An instance of <see cref="T:Newtonsoft.Json.Linq.JRaw"/> with the content of the reader's current token.</returns>
1894 </member>
1895 <member name="T:Newtonsoft.Json.Required">
1896 <summary>
1897 Indicating whether a property is required.
1898 </summary>
1899 </member>
1900 <member name="F:Newtonsoft.Json.Required.Default">
1901 <summary>
1902 The property is not required. The default state.
1903 </summary>
1904 </member>
1905 <member name="F:Newtonsoft.Json.Required.AllowNull">
1906 <summary>
1907 The property must be defined in JSON but can be a null value.
1908 </summary>
1909 </member>
1910 <member name="F:Newtonsoft.Json.Required.Always">
1911 <summary>
1912 The property must be defined in JSON and cannot be a null value.
1913 </summary>
1914 </member>
1915 <member name="T:Newtonsoft.Json.Serialization.IReferenceResolver">
1916 <summary>
1917 Used to resolve references when serializing and deserializing JSON by the <see cref="T:Newtonsoft.Json.JsonSerializer"/>.
1918 </summary>
1919 </member>
1920 <member name="M:Newtonsoft.Json.Serialization.IReferenceResolver.ResolveReference(System.String)">
1921 <summary>
1922 Resolves a reference to its object.
1923 </summary>
1924 <param name="reference">The reference to resolve.</param>
1925 <returns>The object that</returns>
1926 </member>
1927 <member name="M:Newtonsoft.Json.Serialization.IReferenceResolver.GetReference(System.Object)">
1928 <summary>
1929 Gets the reference for the sepecified object.
1930 </summary>
1931 <param name="value">The object to get a reference for.</param>
1932 <returns>The reference to the object.</returns>
1933 </member>
1934 <member name="M:Newtonsoft.Json.Serialization.IReferenceResolver.IsReferenced(System.Object)">
1935 <summary>
1936 Determines whether the specified object is referenced.
1937 </summary>
1938 <param name="value">The object to test for a reference.</param>
1939 <returns>
1940 <c>true</c> if the specified object is referenced; otherwise, <c>false</c>.
1941 </returns>
1942 </member>
1943 <member name="M:Newtonsoft.Json.Serialization.IReferenceResolver.AddReference(System.String,System.Object)">
1944 <summary>
1945 Adds a reference to the specified object.
1946 </summary>
1947 <param name="reference">The reference.</param>
1948 <param name="value">The object to reference.</param>
1949 </member>
1950 <member name="T:Newtonsoft.Json.PreserveReferencesHandling">
1951 <summary>
1952 Specifies reference handling options for the <see cref="T:Newtonsoft.Json.JsonSerializer"/>.
1953 </summary>
1954 </member>
1955 <member name="F:Newtonsoft.Json.PreserveReferencesHandling.None">
1956 <summary>
1957 Do not preserve references when serializing types.
1958 </summary>
1959 </member>
1960 <member name="F:Newtonsoft.Json.PreserveReferencesHandling.Objects">
1961 <summary>
1962 Preserve references when serializing into a JSON object structure.
1963 </summary>
1964 </member>
1965 <member name="F:Newtonsoft.Json.PreserveReferencesHandling.Arrays">
1966 <summary>
1967 Preserve references when serializing into a JSON array structure.
1968 </summary>
1969 </member>
1970 <member name="F:Newtonsoft.Json.PreserveReferencesHandling.All">
1971 <summary>
1972 Preserve references when serializing.
1973 </summary>
1974 </member>
1975 <member name="T:Newtonsoft.Json.JsonArrayAttribute">
1976 <summary>
1977 Instructs the <see cref="T:Newtonsoft.Json.JsonSerializer"/> how to serialize the collection.
1978 </summary>
1979 </member>
1980 <member name="T:Newtonsoft.Json.JsonContainerAttribute">
1981 <summary>
1982 Instructs the <see cref="T:Newtonsoft.Json.JsonSerializer"/> how to serialize the object.
1983 </summary>
1984 </member>
1985 <member name="M:Newtonsoft.Json.JsonContainerAttribute.#ctor">
1986 <summary>
1987 Initializes a new instance of the <see cref="T:Newtonsoft.Json.JsonContainerAttribute"/> class.
1988 </summary>
1989 </member>
1990 <member name="M:Newtonsoft.Json.JsonContainerAttribute.#ctor(System.String)">
1991 <summary>
1992 Initializes a new instance of the <see cref="T:Newtonsoft.Json.JsonContainerAttribute"/> class with the specified container Id.
1993 </summary>
1994 <param name="id">The container Id.</param>
1995 </member>
1996 <member name="P:Newtonsoft.Json.JsonContainerAttribute.Id">
1997 <summary>
1998 Gets or sets the id.
1999 </summary>
2000 <value>The id.</value>
2001 </member>
2002 <member name="P:Newtonsoft.Json.JsonContainerAttribute.Title">
2003 <summary>
2004 Gets or sets the title.
2005 </summary>
2006 <value>The title.</value>
2007 </member>
2008 <member name="P:Newtonsoft.Json.JsonContainerAttribute.Description">
2009 <summary>
2010 Gets or sets the description.
2011 </summary>
2012 <value>The description.</value>
2013 </member>
2014 <member name="P:Newtonsoft.Json.JsonContainerAttribute.IsReference">
2015 <summary>
2016 Gets or sets a value that indicates whether to preserve object reference data.
2017 </summary>
2018 <value>
2019 <c>true</c> to keep object reference; otherwise, <c>false</c>. The default is <c>false</c>.
2020 </value>
2021 </member>
2022 <member name="M:Newtonsoft.Json.JsonArrayAttribute.#ctor">
2023 <summary>
2024 Initializes a new instance of the <see cref="T:Newtonsoft.Json.JsonArrayAttribute"/> class.
2025 </summary>
2026 </member>
2027 <member name="M:Newtonsoft.Json.JsonArrayAttribute.#ctor(System.Boolean)">
2028 <summary>
2029 Initializes a new instance of the <see cref="T:Newtonsoft.Json.JsonObjectAttribute"/> class with a flag indicating whether the array can contain null items
2030 </summary>
2031 <param name="allowNullItems">A flag indicating whether the array can contain null items.</param>
2032 </member>
2033 <member name="M:Newtonsoft.Json.JsonArrayAttribute.#ctor(System.String)">
2034 <summary>
2035 Initializes a new instance of the <see cref="T:Newtonsoft.Json.JsonArrayAttribute"/> class with the specified container Id.
2036 </summary>
2037 <param name="id">The container Id.</param>
2038 </member>
2039 <member name="P:Newtonsoft.Json.JsonArrayAttribute.AllowNullItems">
2040 <summary>
2041 Gets or sets a value indicating whether null items are allowed in the collection.
2042 </summary>
2043 <value><c>true</c> if null items are allowed in the collection; otherwise, <c>false</c>.</value>
2044 </member>
2045 <member name="T:Newtonsoft.Json.DefaultValueHandling">
2046 <summary>
2047 Specifies default value handling options for the <see cref="T:Newtonsoft.Json.JsonSerializer"/>.
2048 </summary>
2049 </member>
2050 <member name="F:Newtonsoft.Json.DefaultValueHandling.Include">
2051 <summary>
2052 Include null values when serializing and deserializing objects.
2053 </summary>
2054 </member>
2055 <member name="F:Newtonsoft.Json.DefaultValueHandling.Ignore">
2056 <summary>
2057 Ignore null values when serializing and deserializing objects.
2058 </summary>
2059 </member>
2060 <member name="T:Newtonsoft.Json.JsonConverterAttribute">
2061 <summary>
2062 Instructs the <see cref="T:Newtonsoft.Json.JsonSerializer"/> to use the specified <see cref="T:Newtonsoft.Json.JsonConverter"/> when serializing the member or class.
2063 </summary>
2064 </member>
2065 <member name="M:Newtonsoft.Json.JsonConverterAttribute.#ctor(System.Type)">
2066 <summary>
2067 Initializes a new instance of the <see cref="T:Newtonsoft.Json.JsonConverterAttribute"/> class.
2068 </summary>
2069 <param name="converterType">Type of the converter.</param>
2070 </member>
2071 <member name="P:Newtonsoft.Json.JsonConverterAttribute.ConverterType">
2072 <summary>
2073 Gets the type of the converter.
2074 </summary>
2075 <value>The type of the converter.</value>
2076 </member>
2077 <member name="T:Newtonsoft.Json.JsonObjectAttribute">
2078 <summary>
2079 Instructs the <see cref="T:Newtonsoft.Json.JsonSerializer"/> how to serialize the object.
2080 </summary>
2081 </member>
2082 <member name="M:Newtonsoft.Json.JsonObjectAttribute.#ctor">
2083 <summary>
2084 Initializes a new instance of the <see cref="T:Newtonsoft.Json.JsonObjectAttribute"/> class.
2085 </summary>
2086 </member>
2087 <member name="M:Newtonsoft.Json.JsonObjectAttribute.#ctor(Newtonsoft.Json.MemberSerialization)">
2088 <summary>
2089 Initializes a new instance of the <see cref="T:Newtonsoft.Json.JsonObjectAttribute"/> class with the specified member serialization.
2090 </summary>
2091 <param name="memberSerialization">The member serialization.</param>
2092 </member>
2093 <member name="M:Newtonsoft.Json.JsonObjectAttribute.#ctor(System.String)">
2094 <summary>
2095 Initializes a new instance of the <see cref="T:Newtonsoft.Json.JsonObjectAttribute"/> class with the specified container Id.
2096 </summary>
2097 <param name="id">The container Id.</param>
2098 </member>
2099 <member name="P:Newtonsoft.Json.JsonObjectAttribute.MemberSerialization">
2100 <summary>
2101 Gets or sets the member serialization.
2102 </summary>
2103 <value>The member serialization.</value>
2104 </member>
2105 <member name="T:Newtonsoft.Json.JsonSerializerSettings">
2106 <summary>
2107 Specifies the settings on a <see cref="T:Newtonsoft.Json.JsonSerializer"/> object.
2108 </summary>
2109 </member>
2110 <member name="M:Newtonsoft.Json.JsonSerializerSettings.#ctor">
2111 <summary>
2112 Initializes a new instance of the <see cref="T:Newtonsoft.Json.JsonSerializerSettings"/> class.
2113 </summary>
2114 </member>
2115 <member name="P:Newtonsoft.Json.JsonSerializerSettings.ReferenceLoopHandling">
2116 <summary>
2117 Gets or sets how reference loops (e.g. a class referencing itself) is handled.
2118 </summary>
2119 <value>Reference loop handling.</value>
2120 </member>
2121 <member name="P:Newtonsoft.Json.JsonSerializerSettings.MissingMemberHandling">
2122 <summary>
2123 Gets or sets how missing members (e.g. JSON contains a property that isn't a member on the object) are handled during deserialization.
2124 </summary>
2125 <value>Missing member handling.</value>
2126 </member>
2127 <member name="P:Newtonsoft.Json.JsonSerializerSettings.ObjectCreationHandling">
2128 <summary>
2129 Gets or sets how objects are created during deserialization.
2130 </summary>
2131 <value>The object creation handling.</value>
2132 </member>
2133 <member name="P:Newtonsoft.Json.JsonSerializerSettings.NullValueHandling">
2134 <summary>
2135 Gets or sets how null values are handled during serialization and deserialization.
2136 </summary>
2137 <value>Null value handling.</value>
2138 </member>
2139 <member name="P:Newtonsoft.Json.JsonSerializerSettings.DefaultValueHandling">
2140 <summary>
2141 Gets or sets how null default are handled during serialization and deserialization.
2142 </summary>
2143 <value>The default value handling.</value>
2144 </member>
2145 <member name="P:Newtonsoft.Json.JsonSerializerSettings.Converters">
2146 <summary>
2147 Gets or sets a collection <see cref="T:Newtonsoft.Json.JsonConverter"/> that will be used during serialization.
2148 </summary>
2149 <value>The converters.</value>
2150 </member>
2151 <member name="P:Newtonsoft.Json.JsonSerializerSettings.PreserveReferencesHandling">
2152 <summary>
2153 Gets or sets how object references are preserved by the serializer.
2154 </summary>
2155 <value>The preserve references handling.</value>
2156 </member>
2157 <member name="P:Newtonsoft.Json.JsonSerializerSettings.TypeNameHandling">
2158 <summary>
2159 Gets or sets how type name writing and reading is handled by the serializer.
2160 </summary>
2161 <value>The type name handling.</value>
2162 </member>
2163 <member name="P:Newtonsoft.Json.JsonSerializerSettings.ConstructorHandling">
2164 <summary>
2165 Gets or sets how constructors are used during deserialization.
2166 </summary>
2167 <value>The constructor handling.</value>
2168 </member>
2169 <member name="P:Newtonsoft.Json.JsonSerializerSettings.ContractResolver">
2170 <summary>
2171 Gets or sets the contract resolver used by the serializer when
2172 serializing .NET objects to JSON and vice versa.
2173 </summary>
2174 <value>The contract resolver.</value>
2175 </member>
2176 <member name="P:Newtonsoft.Json.JsonSerializerSettings.ReferenceResolver">
2177 <summary>
2178 Gets or sets the <see cref="T:Newtonsoft.Json.Serialization.IReferenceResolver"/> used by the serializer when resolving references.
2179 </summary>
2180 <value>The reference resolver.</value>
2181 </member>
2182 <member name="P:Newtonsoft.Json.JsonSerializerSettings.Binder">
2183 <summary>
2184 Gets or sets the <see cref="T:System.Runtime.Serialization.SerializationBinder"/> used by the serializer when resolving type names.
2185 </summary>
2186 <value>The binder.</value>
2187 </member>
2188 <member name="P:Newtonsoft.Json.JsonSerializerSettings.Error">
2189 <summary>
2190 Gets or sets the error handler called during serialization and deserialization.
2191 </summary>
2192 <value>The error handler called during serialization and deserialization.</value>
2193 </member>
2194 <member name="P:Newtonsoft.Json.JsonSerializerSettings.Context">
2195 <summary>
2196 Gets or sets the <see cref="T:System.Runtime.Serialization.StreamingContext"/> used by the serializer when invoking serialization callback methods.
2197 </summary>
2198 <value>The context.</value>
2199 </member>
2200 <member name="T:Newtonsoft.Json.JsonValidatingReader">
2201 <summary>
2202 Represents a reader that provides <see cref="T:Newtonsoft.Json.Schema.JsonSchema"/> validation.
2203 </summary>
2204 </member>
2205 <member name="M:Newtonsoft.Json.JsonValidatingReader.#ctor(Newtonsoft.Json.JsonReader)">
2206 <summary>
2207 Initializes a new instance of the <see cref="T:Newtonsoft.Json.JsonValidatingReader"/> class that
2208 validates the content returned from the given <see cref="T:Newtonsoft.Json.JsonReader"/>.
2209 </summary>
2210 <param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader"/> to read from while validating.</param>
2211 </member>
2212 <member name="M:Newtonsoft.Json.JsonValidatingReader.ReadAsBytes">
2213 <summary>
2214 Reads the next JSON token from the stream as a <see cref="T:Byte[]"/>.
2215 </summary>
2216 <returns>
2217 A <see cref="T:Byte[]"/> or a null reference if the next JSON token is null.
2218 </returns>
2219 </member>
2220 <member name="M:Newtonsoft.Json.JsonValidatingReader.Read">
2221 <summary>
2222 Reads the next JSON token from the stream.
2223 </summary>
2224 <returns>
2225 true if the next token was read successfully; false if there are no more tokens to read.
2226 </returns>
2227 </member>
2228 <member name="E:Newtonsoft.Json.JsonValidatingReader.ValidationEventHandler">
2229 <summary>
2230 Sets an event handler for receiving schema validation errors.
2231 </summary>
2232 </member>
2233 <member name="P:Newtonsoft.Json.JsonValidatingReader.Value">
2234 <summary>
2235 Gets the text value of the current Json token.
2236 </summary>
2237 <value></value>
2238 </member>
2239 <member name="P:Newtonsoft.Json.JsonValidatingReader.Depth">
2240 <summary>
2241 Gets the depth of the current token in the JSON document.
2242 </summary>
2243 <value>The depth of the current token in the JSON document.</value>
2244 </member>
2245 <member name="P:Newtonsoft.Json.JsonValidatingReader.QuoteChar">
2246 <summary>
2247 Gets the quotation mark character used to enclose the value of a string.
2248 </summary>
2249 <value></value>
2250 </member>
2251 <member name="P:Newtonsoft.Json.JsonValidatingReader.TokenType">
2252 <summary>
2253 Gets the type of the current Json token.
2254 </summary>
2255 <value></value>
2256 </member>
2257 <member name="P:Newtonsoft.Json.JsonValidatingReader.ValueType">
2258 <summary>
2259 Gets The Common Language Runtime (CLR) type for the current Json token.
2260 </summary>
2261 <value></value>
2262 </member>
2263 <member name="P:Newtonsoft.Json.JsonValidatingReader.Schema">
2264 <summary>
2265 Gets or sets the schema.
2266 </summary>
2267 <value>The schema.</value>
2268 </member>
2269 <member name="P:Newtonsoft.Json.JsonValidatingReader.Reader">
2270 <summary>
2271 Gets the <see cref="T:Newtonsoft.Json.JsonReader"/> used to construct this <see cref="T:Newtonsoft.Json.JsonValidatingReader"/>.
2272 </summary>
2273 <value>The <see cref="T:Newtonsoft.Json.JsonReader"/> specified in the constructor.</value>
2274 </member>
2275 <member name="T:Newtonsoft.Json.Linq.JTokenEqualityComparer">
2276 <summary>
2277 Compares tokens to determine whether they are equal.
2278 </summary>
2279 </member>
2280 <member name="M:Newtonsoft.Json.Linq.JTokenEqualityComparer.Equals(Newtonsoft.Json.Linq.JToken,Newtonsoft.Json.Linq.JToken)">
2281 <summary>
2282 Determines whether the specified objects are equal.
2283 </summary>
2284 <param name="x">The first object of type <paramref name="T"/> to compare.</param>
2285 <param name="y">The second object of type <paramref name="T"/> to compare.</param>
2286 <returns>
2287 true if the specified objects are equal; otherwise, false.
2288 </returns>
2289 </member>
2290 <member name="M:Newtonsoft.Json.Linq.JTokenEqualityComparer.GetHashCode(Newtonsoft.Json.Linq.JToken)">
2291 <summary>
2292 Returns a hash code for the specified object.
2293 </summary>
2294 <param name="obj">The <see cref="T:System.Object"/> for which a hash code is to be returned.</param>
2295 <returns>A hash code for the specified object.</returns>
2296 <exception cref="T:System.ArgumentNullException">The type of <paramref name="obj"/> is a reference type and <paramref name="obj"/> is null.</exception>
2297 </member>
2298 <member name="T:Newtonsoft.Json.MemberSerialization">
2299 <summary>
2300 Specifies the member serialization options for the <see cref="T:Newtonsoft.Json.JsonSerializer"/>.
2301 </summary>
2302 </member>
2303 <member name="F:Newtonsoft.Json.MemberSerialization.OptOut">
2304 <summary>
2305 All members are serialized by default. Members can be excluded using the <see cref="T:Newtonsoft.Json.JsonIgnoreAttribute"/>.
2306 </summary>
2307 </member>
2308 <member name="F:Newtonsoft.Json.MemberSerialization.OptIn">
2309 <summary>
2310 Only members must be marked with the <see cref="T:Newtonsoft.Json.JsonPropertyAttribute"/> are serialized.
2311 </summary>
2312 </member>
2313 <member name="T:Newtonsoft.Json.ObjectCreationHandling">
2314 <summary>
2315 Specifies how object creation is handled by the <see cref="T:Newtonsoft.Json.JsonSerializer"/>.
2316 </summary>
2317 </member>
2318 <member name="F:Newtonsoft.Json.ObjectCreationHandling.Auto">
2319 <summary>
2320 Reuse existing objects, create new objects when needed.
2321 </summary>
2322 </member>
2323 <member name="F:Newtonsoft.Json.ObjectCreationHandling.Reuse">
2324 <summary>
2325 Only reuse existing objects.
2326 </summary>
2327 </member>
2328 <member name="F:Newtonsoft.Json.ObjectCreationHandling.Replace">
2329 <summary>
2330 Always create new objects.
2331 </summary>
2332 </member>
2333 <member name="T:Newtonsoft.Json.Converters.IsoDateTimeConverter">
2334 <summary>
2335 Converts a <see cref="T:System.DateTime"/> to and from the ISO 8601 date format (e.g. 2008-04-12T12:53Z).
2336 </summary>
2337 </member>
2338 <member name="M:Newtonsoft.Json.Converters.IsoDateTimeConverter.WriteJson(Newtonsoft.Json.JsonWriter,System.Object,Newtonsoft.Json.JsonSerializer)">
2339 <summary>
2340 Writes the JSON representation of the object.
2341 </summary>
2342 <param name="writer">The <see cref="T:Newtonsoft.Json.JsonWriter"/> to write to.</param>
2343 <param name="value">The value.</param>
2344 <param name="serializer">The calling serializer.</param>
2345 </member>
2346 <member name="M:Newtonsoft.Json.Converters.IsoDateTimeConverter.ReadJson(Newtonsoft.Json.JsonReader,System.Type,Newtonsoft.Json.JsonSerializer)">
2347 <summary>
2348 Reads the JSON representation of the object.
2349 </summary>
2350 <param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader"/> to read from.</param>
2351 <param name="objectType">Type of the object.</param>
2352 <param name="serializer">The calling serializer.</param>
2353 <returns>The object value.</returns>
2354 </member>
2355 <member name="P:Newtonsoft.Json.Converters.IsoDateTimeConverter.DateTimeStyles">
2356 <summary>
2357 Gets or sets the date time styles used when converting a date to and from JSON.
2358 </summary>
2359 <value>The date time styles used when converting a date to and from JSON.</value>
2360 </member>
2361 <member name="P:Newtonsoft.Json.Converters.IsoDateTimeConverter.DateTimeFormat">
2362 <summary>
2363 Gets or sets the date time format used when converting a date to and from JSON.
2364 </summary>
2365 <value>The date time format used when converting a date to and from JSON.</value>
2366 </member>
2367 <member name="P:Newtonsoft.Json.Converters.IsoDateTimeConverter.Culture">
2368 <summary>
2369 Gets or sets the culture used when converting a date to and from JSON.
2370 </summary>
2371 <value>The culture used when converting a date to and from JSON.</value>
2372 </member>
2373 <member name="T:Newtonsoft.Json.Converters.JavaScriptDateTimeConverter">
2374 <summary>
2375 Converts a <see cref="T:System.DateTime"/> to and from a JavaScript date constructor (e.g. new Date(52231943)).
2376 </summary>
2377 </member>
2378 <member name="M:Newtonsoft.Json.Converters.JavaScriptDateTimeConverter.WriteJson(Newtonsoft.Json.JsonWriter,System.Object,Newtonsoft.Json.JsonSerializer)">
2379 <summary>
2380 Writes the JSON representation of the object.
2381 </summary>
2382 <param name="writer">The <see cref="T:Newtonsoft.Json.JsonWriter"/> to write to.</param>
2383 <param name="value">The value.</param>
2384 <param name="serializer">The calling serializer.</param>
2385 </member>
2386 <member name="M:Newtonsoft.Json.Converters.JavaScriptDateTimeConverter.ReadJson(Newtonsoft.Json.JsonReader,System.Type,Newtonsoft.Json.JsonSerializer)">
2387 <summary>
2388 Reads the JSON representation of the object.
2389 </summary>
2390 <param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader"/> to read from.</param>
2391 <param name="objectType">Type of the object.</param>
2392 <param name="serializer">The calling serializer.</param>
2393 <returns>The object value.</returns>
2394 </member>
2395 <member name="T:Newtonsoft.Json.Converters.JsonDateTimeSerializationMode">
2396 <summary>
2397 Specifies whether a DateTime object represents a local time, a Coordinated Universal Time (UTC), or is not specified as either local time or UTC.
2398 </summary>
2399 </member>
2400 <member name="F:Newtonsoft.Json.Converters.JsonDateTimeSerializationMode.Local">
2401 <summary>
2402 The time represented is local time.
2403 </summary>
2404 </member>
2405 <member name="F:Newtonsoft.Json.Converters.JsonDateTimeSerializationMode.Utc">
2406 <summary>
2407 The time represented is UTC.
2408 </summary>
2409 </member>
2410 <member name="F:Newtonsoft.Json.Converters.JsonDateTimeSerializationMode.Unspecified">
2411 <summary>
2412 The time represented is not specified as either local time or Coordinated Universal Time (UTC).
2413 </summary>
2414 </member>
2415 <member name="F:Newtonsoft.Json.Converters.JsonDateTimeSerializationMode.RoundtripKind">
2416 <summary>
2417 Preserves the DateTimeKind field of a date when a DateTime object is converted to a string and the string is then converted back to a DateTime object.
2418 </summary>
2419 </member>
2420 <member name="T:Newtonsoft.Json.Converters.XmlNodeConverter">
2421 <summary>
2422 Converts an <see cref="T:System.Xml.XmlNode"/> to and from JSON.
2423 </summary>
2424 </member>
2425 <member name="M:Newtonsoft.Json.Converters.XmlNodeConverter.WriteJson(Newtonsoft.Json.JsonWriter,System.Object,Newtonsoft.Json.JsonSerializer)">
2426 <summary>
2427 Writes the JSON representation of the object.
2428 </summary>
2429 <param name="writer">The <see cref="T:Newtonsoft.Json.JsonWriter"/> to write to.</param>
2430 <param name="serializer">The calling serializer.</param>
2431 <param name="value">The value.</param>
2432 </member>
2433 <member name="M:Newtonsoft.Json.Converters.XmlNodeConverter.ReadJson(Newtonsoft.Json.JsonReader,System.Type,Newtonsoft.Json.JsonSerializer)">
2434 <summary>
2435 Reads the JSON representation of the object.
2436 </summary>
2437 <param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader"/> to read from.</param>
2438 <param name="objectType">Type of the object.</param>
2439 <param name="serializer">The calling serializer.</param>
2440 <returns>The object value.</returns>
2441 </member>
2442 <member name="M:Newtonsoft.Json.Converters.XmlNodeConverter.IsNamespaceAttribute(System.String,System.String@)">
2443 <summary>
2444 Checks if the attributeName is a namespace attribute.
2445 </summary>
2446 <param name="attributeName">Attribute name to test.</param>
2447 <param name="prefix">The attribute name prefix if it has one, otherwise an empty string.</param>
2448 <returns>True if attribute name is for a namespace attribute, otherwise false.</returns>
2449 </member>
2450 <member name="M:Newtonsoft.Json.Converters.XmlNodeConverter.CanConvert(System.Type)">
2451 <summary>
2452 Determines whether this instance can convert the specified value type.
2453 </summary>
2454 <param name="valueType">Type of the value.</param>
2455 <returns>
2456 <c>true</c> if this instance can convert the specified value type; otherwise, <c>false</c>.
2457 </returns>
2458 </member>
2459 <member name="P:Newtonsoft.Json.Converters.XmlNodeConverter.DeserializeRootElementName">
2460 <summary>
2461 Gets or sets the name of the root element to insert when deserializing to XML if the JSON structure has produces multiple root elements.
2462 </summary>
2463 <value>The name of the deserialize root element.</value>
2464 </member>
2465 <member name="T:Newtonsoft.Json.Converters.HtmlColorConverter">
2466 <summary>
2467 Converts a <see cref="T:System.Drawing.Color"/> object to and from JSON.
2468 </summary>
2469 </member>
2470 <member name="M:Newtonsoft.Json.Converters.HtmlColorConverter.WriteJson(Newtonsoft.Json.JsonWriter,System.Object,Newtonsoft.Json.JsonSerializer)">
2471 <summary>
2472 Writes the JSON representation of the object.
2473 </summary>
2474 <param name="writer">The <see cref="T:Newtonsoft.Json.JsonWriter"/> to write to.</param>
2475 <param name="serializer">The calling serializer.</param>
2476 <param name="value">The value.</param>
2477 </member>
2478 <member name="M:Newtonsoft.Json.Converters.HtmlColorConverter.CanConvert(System.Type)">
2479 <summary>
2480 Determines whether this instance can convert the specified value type.
2481 </summary>
2482 <param name="valueType">Type of the value.</param>
2483 <returns>
2484 <c>true</c> if this instance can convert the specified value type; otherwise, <c>false</c>.
2485 </returns>
2486 </member>
2487 <member name="M:Newtonsoft.Json.Converters.HtmlColorConverter.ReadJson(Newtonsoft.Json.JsonReader,System.Type,Newtonsoft.Json.JsonSerializer)">
2488 <summary>
2489 Reads the JSON representation of the object.
2490 </summary>
2491 <param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader"/> to read from.</param>
2492 <param name="objectType">Type of the object.</param>
2493 <param name="serializer">The calling serializer.</param>
2494 <returns>The object value.</returns>
2495 </member>
2496 <member name="T:Newtonsoft.Json.JsonTextReader">
2497 <summary>
2498 Represents a reader that provides fast, non-cached, forward-only access to serialized Json data.
2499 </summary>
2500 </member>
2501 <member name="M:Newtonsoft.Json.JsonTextReader.#ctor(System.IO.TextReader)">
2502 <summary>
2503 Initializes a new instance of the <see cref="T:Newtonsoft.Json.JsonReader"/> class with the specified <see cref="T:System.IO.TextReader"/>.
2504 </summary>
2505 <param name="reader">The <c>TextReader</c> containing the XML data to read.</param>
2506 </member>
2507 <member name="M:Newtonsoft.Json.JsonTextReader.Read">
2508 <summary>
2509 Reads the next JSON token from the stream.
2510 </summary>
2511 <returns>
2512 true if the next token was read successfully; false if there are no more tokens to read.
2513 </returns>
2514 </member>
2515 <member name="M:Newtonsoft.Json.JsonTextReader.ReadAsBytes">
2516 <summary>
2517 Reads the next JSON token from the stream as a <see cref="T:Byte[]"/>.
2518 </summary>
2519 <returns>
2520 A <see cref="T:Byte[]"/> or a null reference if the next JSON token is null.
2521 </returns>
2522 </member>
2523 <member name="M:Newtonsoft.Json.JsonTextReader.Close">
2524 <summary>
2525 Changes the state to closed.
2526 </summary>
2527 </member>
2528 <member name="M:Newtonsoft.Json.JsonTextReader.HasLineInfo">
2529 <summary>
2530 Gets a value indicating whether the class can return line information.
2531 </summary>
2532 <returns>
2533 <c>true</c> if LineNumber and LinePosition can be provided; otherwise, <c>false</c>.
2534 </returns>
2535 </member>
2536 <member name="P:Newtonsoft.Json.JsonTextReader.LineNumber">
2537 <summary>
2538 Gets the current line number.
2539 </summary>
2540 <value>
2541 The current line number or 0 if no line information is available (for example, HasLineInfo returns false).
2542 </value>
2543 </member>
2544 <member name="P:Newtonsoft.Json.JsonTextReader.LinePosition">
2545 <summary>
2546 Gets the current line position.
2547 </summary>
2548 <value>
2549 The current line position or 0 if no line information is available (for example, HasLineInfo returns false).
2550 </value>
2551 </member>
2552 <member name="T:Newtonsoft.Json.JsonPropertyAttribute">
2553 <summary>
2554 Instructs the <see cref="T:Newtonsoft.Json.JsonSerializer"/> to always serialize the member with the specified name.
2555 </summary>
2556 </member>
2557 <member name="M:Newtonsoft.Json.JsonPropertyAttribute.#ctor">
2558 <summary>
2559 Initializes a new instance of the <see cref="T:Newtonsoft.Json.JsonPropertyAttribute"/> class.
2560 </summary>
2561 </member>
2562 <member name="M:Newtonsoft.Json.JsonPropertyAttribute.#ctor(System.String)">
2563 <summary>
2564 Initializes a new instance of the <see cref="T:Newtonsoft.Json.JsonPropertyAttribute"/> class with the specified name.
2565 </summary>
2566 <param name="propertyName">Name of the property.</param>
2567 </member>
2568 <member name="P:Newtonsoft.Json.JsonPropertyAttribute.NullValueHandling">
2569 <summary>
2570 Gets or sets the null value handling used when serializing this property.
2571 </summary>
2572 <value>The null value handling.</value>
2573 </member>
2574 <member name="P:Newtonsoft.Json.JsonPropertyAttribute.DefaultValueHandling">
2575 <summary>
2576 Gets or sets the default value handling used when serializing this property.
2577 </summary>
2578 <value>The default value handling.</value>
2579 </member>
2580 <member name="P:Newtonsoft.Json.JsonPropertyAttribute.ReferenceLoopHandling">
2581 <summary>
2582 Gets or sets the reference loop handling used when serializing this property.
2583 </summary>
2584 <value>The reference loop handling.</value>
2585 </member>
2586 <member name="P:Newtonsoft.Json.JsonPropertyAttribute.ObjectCreationHandling">
2587 <summary>
2588 Gets or sets the object creation handling used when deserializing this property.
2589 </summary>
2590 <value>The object creation handling.</value>
2591 </member>
2592 <member name="P:Newtonsoft.Json.JsonPropertyAttribute.IsReference">
2593 <summary>
2594 Gets or sets whether this property's value is serialized as a reference.
2595 </summary>
2596 <value>Whether this property's value is serialized as a reference.</value>
2597 </member>
2598 <member name="P:Newtonsoft.Json.JsonPropertyAttribute.PropertyName">
2599 <summary>
2600 Gets or sets the name of the property.
2601 </summary>
2602 <value>The name of the property.</value>
2603 </member>
2604 <member name="P:Newtonsoft.Json.JsonPropertyAttribute.Required">
2605 <summary>
2606 Gets or sets a value indicating whether this property is required.
2607 </summary>
2608 <value>
2609 A value indicating whether this property is required.
2610 </value>
2611 </member>
2612 <member name="T:Newtonsoft.Json.JsonIgnoreAttribute">
2613 <summary>
2614 Instructs the <see cref="T:Newtonsoft.Json.JsonSerializer"/> not to serialize the public field or public read/write property value.
2615 </summary>
2616 </member>
2617 <member name="T:Newtonsoft.Json.JsonTextWriter">
2618 <summary>
2619 Represents a writer that provides a fast, non-cached, forward-only way of generating Json data.
2620 </summary>
2621 </member>
2622 <member name="M:Newtonsoft.Json.JsonTextWriter.#ctor(System.IO.TextWriter)">
2623 <summary>
2624 Creates an instance of the <c>JsonWriter</c> class using the specified <see cref="T:System.IO.TextWriter"/>.
2625 </summary>
2626 <param name="textWriter">The <c>TextWriter</c> to write to.</param>
2627 </member>
2628 <member name="M:Newtonsoft.Json.JsonTextWriter.Flush">
2629 <summary>
2630 Flushes whatever is in the buffer to the underlying streams and also flushes the underlying stream.
2631 </summary>
2632 </member>
2633 <member name="M:Newtonsoft.Json.JsonTextWriter.Close">
2634 <summary>
2635 Closes this stream and the underlying stream.
2636 </summary>
2637 </member>
2638 <member name="M:Newtonsoft.Json.JsonTextWriter.WriteStartObject">
2639 <summary>
2640 Writes the beginning of a Json object.
2641 </summary>
2642 </member>
2643 <member name="M:Newtonsoft.Json.JsonTextWriter.WriteStartArray">
2644 <summary>
2645 Writes the beginning of a Json array.
2646 </summary>
2647 </member>
2648 <member name="M:Newtonsoft.Json.JsonTextWriter.WriteStartConstructor(System.String)">
2649 <summary>
2650 Writes the start of a constructor with the given name.
2651 </summary>
2652 <param name="name">The name of the constructor.</param>
2653 </member>
2654 <member name="M:Newtonsoft.Json.JsonTextWriter.WriteEnd(Newtonsoft.Json.JsonToken)">
2655 <summary>
2656 Writes the specified end token.
2657 </summary>
2658 <param name="token">The end token to write.</param>
2659 </member>
2660 <member name="M:Newtonsoft.Json.JsonTextWriter.WritePropertyName(System.String)">
2661 <summary>
2662 Writes the property name of a name/value pair on a Json object.
2663 </summary>
2664 <param name="name">The name of the property.</param>
2665 </member>
2666 <member name="M:Newtonsoft.Json.JsonTextWriter.WriteIndent">
2667 <summary>
2668 Writes indent characters.
2669 </summary>
2670 </member>
2671 <member name="M:Newtonsoft.Json.JsonTextWriter.WriteValueDelimiter">
2672 <summary>
2673 Writes the JSON value delimiter.
2674 </summary>
2675 </member>
2676 <member name="M:Newtonsoft.Json.JsonTextWriter.WriteIndentSpace">
2677 <summary>
2678 Writes an indent space.
2679 </summary>
2680 </member>
2681 <member name="M:Newtonsoft.Json.JsonTextWriter.WriteNull">
2682 <summary>
2683 Writes a null value.
2684 </summary>
2685 </member>
2686 <member name="M:Newtonsoft.Json.JsonTextWriter.WriteUndefined">
2687 <summary>
2688 Writes an undefined value.
2689 </summary>
2690 </member>
2691 <member name="M:Newtonsoft.Json.JsonTextWriter.WriteRaw(System.String)">
2692 <summary>
2693 Writes raw JSON.
2694 </summary>
2695 <param name="json">The raw JSON to write.</param>
2696 </member>
2697 <member name="M:Newtonsoft.Json.JsonTextWriter.WriteValue(System.String)">
2698 <summary>
2699 Writes a <see cref="T:System.String"/> value.
2700 </summary>
2701 <param name="value">The <see cref="T:System.String"/> value to write.</param>
2702 </member>
2703 <member name="M:Newtonsoft.Json.JsonTextWriter.WriteValue(System.Int32)">
2704 <summary>
2705 Writes a <see cref="T:System.Int32"/> value.
2706 </summary>
2707 <param name="value">The <see cref="T:System.Int32"/> value to write.</param>
2708 </member>
2709 <member name="M:Newtonsoft.Json.JsonTextWriter.WriteValue(System.UInt32)">
2710 <summary>
2711 Writes a <see cref="T:System.UInt32"/> value.
2712 </summary>
2713 <param name="value">The <see cref="T:System.UInt32"/> value to write.</param>
2714 </member>
2715 <member name="M:Newtonsoft.Json.JsonTextWriter.WriteValue(System.Int64)">
2716 <summary>
2717 Writes a <see cref="T:System.Int64"/> value.
2718 </summary>
2719 <param name="value">The <see cref="T:System.Int64"/> value to write.</param>
2720 </member>
2721 <member name="M:Newtonsoft.Json.JsonTextWriter.WriteValue(System.UInt64)">
2722 <summary>
2723 Writes a <see cref="T:System.UInt64"/> value.
2724 </summary>
2725 <param name="value">The <see cref="T:System.UInt64"/> value to write.</param>
2726 </member>
2727 <member name="M:Newtonsoft.Json.JsonTextWriter.WriteValue(System.Single)">
2728 <summary>
2729 Writes a <see cref="T:System.Single"/> value.
2730 </summary>
2731 <param name="value">The <see cref="T:System.Single"/> value to write.</param>
2732 </member>
2733 <member name="M:Newtonsoft.Json.JsonTextWriter.WriteValue(System.Double)">
2734 <summary>
2735 Writes a <see cref="T:System.Double"/> value.
2736 </summary>
2737 <param name="value">The <see cref="T:System.Double"/> value to write.</param>
2738 </member>
2739 <member name="M:Newtonsoft.Json.JsonTextWriter.WriteValue(System.Boolean)">
2740 <summary>
2741 Writes a <see cref="T:System.Boolean"/> value.
2742 </summary>
2743 <param name="value">The <see cref="T:System.Boolean"/> value to write.</param>
2744 </member>
2745 <member name="M:Newtonsoft.Json.JsonTextWriter.WriteValue(System.Int16)">
2746 <summary>
2747 Writes a <see cref="T:System.Int16"/> value.
2748 </summary>
2749 <param name="value">The <see cref="T:System.Int16"/> value to write.</param>
2750 </member>
2751 <member name="M:Newtonsoft.Json.JsonTextWriter.WriteValue(System.UInt16)">
2752 <summary>
2753 Writes a <see cref="T:System.UInt16"/> value.
2754 </summary>
2755 <param name="value">The <see cref="T:System.UInt16"/> value to write.</param>
2756 </member>
2757 <member name="M:Newtonsoft.Json.JsonTextWriter.WriteValue(System.Char)">
2758 <summary>
2759 Writes a <see cref="T:System.Char"/> value.
2760 </summary>
2761 <param name="value">The <see cref="T:System.Char"/> value to write.</param>
2762 </member>
2763 <member name="M:Newtonsoft.Json.JsonTextWriter.WriteValue(System.Byte)">
2764 <summary>
2765 Writes a <see cref="T:System.Byte"/> value.
2766 </summary>
2767 <param name="value">The <see cref="T:System.Byte"/> value to write.</param>
2768 </member>
2769 <member name="M:Newtonsoft.Json.JsonTextWriter.WriteValue(System.SByte)">
2770 <summary>
2771 Writes a <see cref="T:System.SByte"/> value.
2772 </summary>
2773 <param name="value">The <see cref="T:System.SByte"/> value to write.</param>
2774 </member>
2775 <member name="M:Newtonsoft.Json.JsonTextWriter.WriteValue(System.Decimal)">
2776 <summary>
2777 Writes a <see cref="T:System.Decimal"/> value.
2778 </summary>
2779 <param name="value">The <see cref="T:System.Decimal"/> value to write.</param>
2780 </member>
2781 <member name="M:Newtonsoft.Json.JsonTextWriter.WriteValue(System.DateTime)">
2782 <summary>
2783 Writes a <see cref="T:System.DateTime"/> value.
2784 </summary>
2785 <param name="value">The <see cref="T:System.DateTime"/> value to write.</param>
2786 </member>
2787 <member name="M:Newtonsoft.Json.JsonTextWriter.WriteValue(System.Byte[])">
2788 <summary>
2789 Writes a <see cref="T:Byte[]"/> value.
2790 </summary>
2791 <param name="value">The <see cref="T:Byte[]"/> value to write.</param>
2792 </member>
2793 <member name="M:Newtonsoft.Json.JsonTextWriter.WriteComment(System.String)">
2794 <summary>
2795 Writes out a comment <code>/*...*/</code> containing the specified text.
2796 </summary>
2797 <param name="text">Text to place inside the comment.</param>
2798 </member>
2799 <member name="M:Newtonsoft.Json.JsonTextWriter.WriteWhitespace(System.String)">
2800 <summary>
2801 Writes out the given white space.
2802 </summary>
2803 <param name="ws">The string of white space characters.</param>
2804 </member>
2805 <member name="P:Newtonsoft.Json.JsonTextWriter.Indentation">
2806 <summary>
2807 Gets or sets how many IndentChars to write for each level in the hierarchy when <paramref name="Formatting"/> is set to <c>Formatting.Indented</c>.
2808 </summary>
2809 </member>
2810 <member name="P:Newtonsoft.Json.JsonTextWriter.QuoteChar">
2811 <summary>
2812 Gets or sets which character to use to quote attribute values.
2813 </summary>
2814 </member>
2815 <member name="P:Newtonsoft.Json.JsonTextWriter.IndentChar">
2816 <summary>
2817 Gets or sets which character to use for indenting when <paramref name="Formatting"/> is set to <c>Formatting.Indented</c>.
2818 </summary>
2819 </member>
2820 <member name="P:Newtonsoft.Json.JsonTextWriter.QuoteName">
2821 <summary>
2822 Gets or sets a value indicating whether object names will be surrounded with quotes.
2823 </summary>
2824 </member>
2825 <member name="T:Newtonsoft.Json.JsonWriterException">
2826 <summary>
2827 The exception thrown when an error occurs while reading Json text.
2828 </summary>
2829 </member>
2830 <member name="M:Newtonsoft.Json.JsonWriterException.#ctor">
2831 <summary>
2832 Initializes a new instance of the <see cref="T:Newtonsoft.Json.JsonWriterException"/> class.
2833 </summary>
2834 </member>
2835 <member name="M:Newtonsoft.Json.JsonWriterException.#ctor(System.String)">
2836 <summary>
2837 Initializes a new instance of the <see cref="T:Newtonsoft.Json.JsonWriterException"/> class
2838 with a specified error message.
2839 </summary>
2840 <param name="message">The error message that explains the reason for the exception.</param>
2841 </member>
2842 <member name="M:Newtonsoft.Json.JsonWriterException.#ctor(System.String,System.Exception)">
2843 <summary>
2844 Initializes a new instance of the <see cref="T:Newtonsoft.Json.JsonWriterException"/> class
2845 with a specified error message and a reference to the inner exception that is the cause of this exception.
2846 </summary>
2847 <param name="message">The error message that explains the reason for the exception.</param>
2848 <param name="innerException">The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.</param>
2849 </member>
2850 <member name="T:Newtonsoft.Json.JsonReaderException">
2851 <summary>
2852 The exception thrown when an error occurs while reading Json text.
2853 </summary>
2854 </member>
2855 <member name="M:Newtonsoft.Json.JsonReaderException.#ctor">
2856 <summary>
2857 Initializes a new instance of the <see cref="T:Newtonsoft.Json.JsonReaderException"/> class.
2858 </summary>
2859 </member>
2860 <member name="M:Newtonsoft.Json.JsonReaderException.#ctor(System.String)">
2861 <summary>
2862 Initializes a new instance of the <see cref="T:Newtonsoft.Json.JsonReaderException"/> class
2863 with a specified error message.
2864 </summary>
2865 <param name="message">The error message that explains the reason for the exception.</param>
2866 </member>
2867 <member name="M:Newtonsoft.Json.JsonReaderException.#ctor(System.String,System.Exception)">
2868 <summary>
2869 Initializes a new instance of the <see cref="T:Newtonsoft.Json.JsonReaderException"/> class
2870 with a specified error message and a reference to the inner exception that is the cause of this exception.
2871 </summary>
2872 <param name="message">The error message that explains the reason for the exception.</param>
2873 <param name="innerException">The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.</param>
2874 </member>
2875 <member name="P:Newtonsoft.Json.JsonReaderException.LineNumber">
2876 <summary>
2877 Gets the line number indicating where the error occurred.
2878 </summary>
2879 <value>The line number indicating where the error occurred.</value>
2880 </member>
2881 <member name="P:Newtonsoft.Json.JsonReaderException.LinePosition">
2882 <summary>
2883 Gets the line position indicating where the error occurred.
2884 </summary>
2885 <value>The line position indicating where the error occurred.</value>
2886 </member>
2887 <member name="T:Newtonsoft.Json.JsonConverterCollection">
2888 <summary>
2889 Represents a collection of <see cref="T:Newtonsoft.Json.JsonConverter"/>.
2890 </summary>
2891 </member>
2892 <member name="T:Newtonsoft.Json.JsonConvert">
2893 <summary>
2894 Provides methods for converting between common language runtime types and JSON types.
2895 </summary>
2896 </member>
2897 <member name="F:Newtonsoft.Json.JsonConvert.True">
2898 <summary>
2899 Represents JavaScript's boolean value true as a string. This field is read-only.
2900 </summary>
2901 </member>
2902 <member name="F:Newtonsoft.Json.JsonConvert.False">
2903 <summary>
2904 Represents JavaScript's boolean value false as a string. This field is read-only.
2905 </summary>
2906 </member>
2907 <member name="F:Newtonsoft.Json.JsonConvert.Null">
2908 <summary>
2909 Represents JavaScript's null as a string. This field is read-only.
2910 </summary>
2911 </member>
2912 <member name="F:Newtonsoft.Json.JsonConvert.Undefined">
2913 <summary>
2914 Represents JavaScript's undefined as a string. This field is read-only.
2915 </summary>
2916 </member>
2917 <member name="F:Newtonsoft.Json.JsonConvert.PositiveInfinity">
2918 <summary>
2919 Represents JavaScript's positive infinity as a string. This field is read-only.
2920 </summary>
2921 </member>
2922 <member name="F:Newtonsoft.Json.JsonConvert.NegativeInfinity">
2923 <summary>
2924 Represents JavaScript's negative infinity as a string. This field is read-only.
2925 </summary>
2926 </member>
2927 <member name="F:Newtonsoft.Json.JsonConvert.NaN">
2928 <summary>
2929 Represents JavaScript's NaN as a string. This field is read-only.
2930 </summary>
2931 </member>
2932 <member name="M:Newtonsoft.Json.JsonConvert.ToString(System.DateTime)">
2933 <summary>
2934 Converts the <see cref="T:System.DateTime"/> to its JSON string representation.
2935 </summary>
2936 <param name="value">The value to convert.</param>
2937 <returns>A JSON string representation of the <see cref="T:System.DateTime"/>.</returns>
2938 </member>
2939 <member name="M:Newtonsoft.Json.JsonConvert.ToString(System.Boolean)">
2940 <summary>
2941 Converts the <see cref="T:System.Boolean"/> to its JSON string representation.
2942 </summary>
2943 <param name="value">The value to convert.</param>
2944 <returns>A JSON string representation of the <see cref="T:System.Boolean"/>.</returns>
2945 </member>
2946 <member name="M:Newtonsoft.Json.JsonConvert.ToString(System.Char)">
2947 <summary>
2948 Converts the <see cref="T:System.Char"/> to its JSON string representation.
2949 </summary>
2950 <param name="value">The value to convert.</param>
2951 <returns>A JSON string representation of the <see cref="T:System.Char"/>.</returns>
2952 </member>
2953 <member name="M:Newtonsoft.Json.JsonConvert.ToString(System.Enum)">
2954 <summary>
2955 Converts the <see cref="T:System.Enum"/> to its JSON string representation.
2956 </summary>
2957 <param name="value">The value to convert.</param>
2958 <returns>A JSON string representation of the <see cref="T:System.Enum"/>.</returns>
2959 </member>
2960 <member name="M:Newtonsoft.Json.JsonConvert.ToString(System.Int32)">
2961 <summary>
2962 Converts the <see cref="T:System.Int32"/> to its JSON string representation.
2963 </summary>
2964 <param name="value">The value to convert.</param>
2965 <returns>A JSON string representation of the <see cref="T:System.Int32"/>.</returns>
2966 </member>
2967 <member name="M:Newtonsoft.Json.JsonConvert.ToString(System.Int16)">
2968 <summary>
2969 Converts the <see cref="T:System.Int16"/> to its JSON string representation.
2970 </summary>
2971 <param name="value">The value to convert.</param>
2972 <returns>A JSON string representation of the <see cref="T:System.Int16"/>.</returns>
2973 </member>
2974 <member name="M:Newtonsoft.Json.JsonConvert.ToString(System.UInt16)">
2975 <summary>
2976 Converts the <see cref="T:System.UInt16"/> to its JSON string representation.
2977 </summary>
2978 <param name="value">The value to convert.</param>
2979 <returns>A JSON string representation of the <see cref="T:System.UInt16"/>.</returns>
2980 </member>
2981 <member name="M:Newtonsoft.Json.JsonConvert.ToString(System.UInt32)">
2982 <summary>
2983 Converts the <see cref="T:System.UInt32"/> to its JSON string representation.
2984 </summary>
2985 <param name="value">The value to convert.</param>
2986 <returns>A JSON string representation of the <see cref="T:System.UInt32"/>.</returns>
2987 </member>
2988 <member name="M:Newtonsoft.Json.JsonConvert.ToString(System.Int64)">
2989 <summary>
2990 Converts the <see cref="T:System.Int64"/> to its JSON string representation.
2991 </summary>
2992 <param name="value">The value to convert.</param>
2993 <returns>A JSON string representation of the <see cref="T:System.Int64"/>.</returns>
2994 </member>
2995 <member name="M:Newtonsoft.Json.JsonConvert.ToString(System.UInt64)">
2996 <summary>
2997 Converts the <see cref="T:System.UInt64"/> to its JSON string representation.
2998 </summary>
2999 <param name="value">The value to convert.</param>
3000 <returns>A JSON string representation of the <see cref="T:System.UInt64"/>.</returns>
3001 </member>
3002 <member name="M:Newtonsoft.Json.JsonConvert.ToString(System.Single)">
3003 <summary>
3004 Converts the <see cref="T:System.Single"/> to its JSON string representation.
3005 </summary>
3006 <param name="value">The value to convert.</param>
3007 <returns>A JSON string representation of the <see cref="T:System.Single"/>.</returns>
3008 </member>
3009 <member name="M:Newtonsoft.Json.JsonConvert.ToString(System.Double)">
3010 <summary>
3011 Converts the <see cref="T:System.Double"/> to its JSON string representation.
3012 </summary>
3013 <param name="value">The value to convert.</param>
3014 <returns>A JSON string representation of the <see cref="T:System.Double"/>.</returns>
3015 </member>
3016 <member name="M:Newtonsoft.Json.JsonConvert.ToString(System.Byte)">
3017 <summary>
3018 Converts the <see cref="T:System.Byte"/> to its JSON string representation.
3019 </summary>
3020 <param name="value">The value to convert.</param>
3021 <returns>A JSON string representation of the <see cref="T:System.Byte"/>.</returns>
3022 </member>
3023 <member name="M:Newtonsoft.Json.JsonConvert.ToString(System.SByte)">
3024 <summary>
3025 Converts the <see cref="T:System.SByte"/> to its JSON string representation.
3026 </summary>
3027 <param name="value">The value to convert.</param>
3028 <returns>A JSON string representation of the <see cref="T:System.SByte"/>.</returns>
3029 </member>
3030 <member name="M:Newtonsoft.Json.JsonConvert.ToString(System.Decimal)">
3031 <summary>
3032 Converts the <see cref="T:System.Decimal"/> to its JSON string representation.
3033 </summary>
3034 <param name="value">The value to convert.</param>
3035 <returns>A JSON string representation of the <see cref="T:System.SByte"/>.</returns>
3036 </member>
3037 <member name="M:Newtonsoft.Json.JsonConvert.ToString(System.Guid)">
3038 <summary>
3039 Converts the <see cref="T:System.Guid"/> to its JSON string representation.
3040 </summary>
3041 <param name="value">The value to convert.</param>
3042 <returns>A JSON string representation of the <see cref="T:System.Guid"/>.</returns>
3043 </member>
3044 <member name="M:Newtonsoft.Json.JsonConvert.ToString(System.String)">
3045 <summary>
3046 Converts the <see cref="T:System.String"/> to its JSON string representation.
3047 </summary>
3048 <param name="value">The value to convert.</param>
3049 <returns>A JSON string representation of the <see cref="T:System.String"/>.</returns>
3050 </member>
3051 <member name="M:Newtonsoft.Json.JsonConvert.ToString(System.String,System.Char)">
3052 <summary>
3053 Converts the <see cref="T:System.String"/> to its JSON string representation.
3054 </summary>
3055 <param name="value">The value to convert.</param>
3056 <param name="delimter">The string delimiter character.</param>
3057 <returns>A JSON string representation of the <see cref="T:System.String"/>.</returns>
3058 </member>
3059 <member name="M:Newtonsoft.Json.JsonConvert.ToString(System.Object)">
3060 <summary>
3061 Converts the <see cref="T:System.Object"/> to its JSON string representation.
3062 </summary>
3063 <param name="value">The value to convert.</param>
3064 <returns>A JSON string representation of the <see cref="T:System.Object"/>.</returns>
3065 </member>
3066 <member name="M:Newtonsoft.Json.JsonConvert.SerializeObject(System.Object)">
3067 <summary>
3068 Serializes the specified object to a JSON string.
3069 </summary>
3070 <param name="value">The object to serialize.</param>
3071 <returns>A JSON string representation of the object.</returns>
3072 </member>
3073 <member name="M:Newtonsoft.Json.JsonConvert.SerializeObject(System.Object,Newtonsoft.Json.Formatting)">
3074 <summary>
3075 Serializes the specified object to a JSON string.
3076 </summary>
3077 <param name="value">The object to serialize.</param>
3078 <param name="formatting">Indicates how the output is formatted.</param>
3079 <returns>
3080 A JSON string representation of the object.
3081 </returns>
3082 </member>
3083 <member name="M:Newtonsoft.Json.JsonConvert.SerializeObject(System.Object,Newtonsoft.Json.JsonConverter[])">
3084 <summary>
3085 Serializes the specified object to a JSON string using a collection of <see cref="T:Newtonsoft.Json.JsonConverter"/>.
3086 </summary>
3087 <param name="value">The object to serialize.</param>
3088 <param name="converters">A collection converters used while serializing.</param>
3089 <returns>A JSON string representation of the object.</returns>
3090 </member>
3091 <member name="M:Newtonsoft.Json.JsonConvert.SerializeObject(System.Object,Newtonsoft.Json.Formatting,Newtonsoft.Json.JsonConverter[])">
3092 <summary>
3093 Serializes the specified object to a JSON string using a collection of <see cref="T:Newtonsoft.Json.JsonConverter"/>.
3094 </summary>
3095 <param name="value">The object to serialize.</param>
3096 <param name="formatting">Indicates how the output is formatted.</param>
3097 <param name="converters">A collection converters used while serializing.</param>
3098 <returns>A JSON string representation of the object.</returns>
3099 </member>
3100 <member name="M:Newtonsoft.Json.JsonConvert.SerializeObject(System.Object,Newtonsoft.Json.Formatting,Newtonsoft.Json.JsonSerializerSettings)">
3101 <summary>
3102 Serializes the specified object to a JSON string using a collection of <see cref="T:Newtonsoft.Json.JsonConverter"/>.
3103 </summary>
3104 <param name="value">The object to serialize.</param>
3105 <param name="formatting">Indicates how the output is formatted.</param>
3106 <param name="settings">The <see cref="T:Newtonsoft.Json.JsonSerializerSettings"/> used to serialize the object.
3107 If this is null, default serialization settings will be is used.</param>
3108 <returns>
3109 A JSON string representation of the object.
3110 </returns>
3111 </member>
3112 <member name="M:Newtonsoft.Json.JsonConvert.DeserializeObject(System.String)">
3113 <summary>
3114 Deserializes the specified object to a Json object.
3115 </summary>
3116 <param name="value">The object to deserialize.</param>
3117 <returns>The deserialized object from the Json string.</returns>
3118 </member>
3119 <member name="M:Newtonsoft.Json.JsonConvert.DeserializeObject(System.String,System.Type)">
3120 <summary>
3121 Deserializes the specified object to a Json object.
3122 </summary>
3123 <param name="value">The object to deserialize.</param>
3124 <param name="type">The <see cref="T:System.Type"/> of object being deserialized.</param>
3125 <returns>The deserialized object from the Json string.</returns>
3126 </member>
3127 <member name="M:Newtonsoft.Json.JsonConvert.DeserializeObject``1(System.String)">
3128 <summary>
3129 Deserializes the specified object to a Json object.
3130 </summary>
3131 <typeparam name="T">The type of the object to deserialize.</typeparam>
3132 <param name="value">The object to deserialize.</param>
3133 <returns>The deserialized object from the Json string.</returns>
3134 </member>
3135 <member name="M:Newtonsoft.Json.JsonConvert.DeserializeAnonymousType``1(System.String,``0)">
3136 <summary>
3137 Deserializes the specified JSON to the given anonymous type.
3138 </summary>
3139 <typeparam name="T">
3140 The anonymous type to deserialize to. This can't be specified
3141 traditionally and must be infered from the anonymous type passed
3142 as a parameter.
3143 </typeparam>
3144 <param name="value">The object to deserialize.</param>
3145 <param name="anonymousTypeObject">The anonymous type object.</param>
3146 <returns>The deserialized anonymous type from the JSON string.</returns>
3147 </member>
3148 <member name="M:Newtonsoft.Json.JsonConvert.DeserializeObject``1(System.String,Newtonsoft.Json.JsonConverter[])">
3149 <summary>
3150 Deserializes the JSON string to the specified type.
3151 </summary>
3152 <typeparam name="T">The type of the object to deserialize.</typeparam>
3153 <param name="value">The object to deserialize.</param>
3154 <param name="converters">Converters to use while deserializing.</param>
3155 <returns>The deserialized object from the JSON string.</returns>
3156 </member>
3157 <member name="M:Newtonsoft.Json.JsonConvert.DeserializeObject``1(System.String,Newtonsoft.Json.JsonSerializerSettings)">
3158 <summary>
3159 Deserializes the JSON string to the specified type.
3160 </summary>
3161 <typeparam name="T">The type of the object to deserialize.</typeparam>
3162 <param name="value">The object to deserialize.</param>
3163 <param name="settings">
3164 The <see cref="T:Newtonsoft.Json.JsonSerializerSettings"/> used to deserialize the object.
3165 If this is null, default serialization settings will be is used.
3166 </param>
3167 <returns>The deserialized object from the JSON string.</returns>
3168 </member>
3169 <member name="M:Newtonsoft.Json.JsonConvert.DeserializeObject(System.String,System.Type,Newtonsoft.Json.JsonConverter[])">
3170 <summary>
3171 Deserializes the JSON string to the specified type.
3172 </summary>
3173 <param name="value">The object to deserialize.</param>
3174 <param name="type">The type of the object to deserialize.</param>
3175 <param name="converters">Converters to use while deserializing.</param>
3176 <returns>The deserialized object from the JSON string.</returns>
3177 </member>
3178 <member name="M:Newtonsoft.Json.JsonConvert.DeserializeObject(System.String,System.Type,Newtonsoft.Json.JsonSerializerSettings)">
3179 <summary>
3180 Deserializes the JSON string to the specified type.
3181 </summary>
3182 <param name="value">The JSON to deserialize.</param>
3183 <param name="type">The type of the object to deserialize.</param>
3184 <param name="settings">
3185 The <see cref="T:Newtonsoft.Json.JsonSerializerSettings"/> used to deserialize the object.
3186 If this is null, default serialization settings will be is used.
3187 </param>
3188 <returns>The deserialized object from the JSON string.</returns>
3189 </member>
3190 <member name="M:Newtonsoft.Json.JsonConvert.PopulateObject(System.String,System.Object)">
3191 <summary>
3192 Populates the object with values from the JSON string.
3193 </summary>
3194 <param name="value">The JSON to populate values from.</param>
3195 <param name="target">The target object to populate values onto.</param>
3196 </member>
3197 <member name="M:Newtonsoft.Json.JsonConvert.PopulateObject(System.String,System.Object,Newtonsoft.Json.JsonSerializerSettings)">
3198 <summary>
3199 Populates the object with values from the JSON string.
3200 </summary>
3201 <param name="value">The JSON to populate values from.</param>
3202 <param name="target">The target object to populate values onto.</param>
3203 <param name="settings">
3204 The <see cref="T:Newtonsoft.Json.JsonSerializerSettings"/> used to deserialize the object.
3205 If this is null, default serialization settings will be is used.
3206 </param>
3207 </member>
3208 <member name="M:Newtonsoft.Json.JsonConvert.SerializeXmlNode(System.Xml.XmlNode)">
3209 <summary>
3210 Serializes the XML node to a JSON string.
3211 </summary>
3212 <param name="node">The node to serialize.</param>
3213 <returns>A JSON string of the XmlNode.</returns>
3214 </member>
3215 <member name="M:Newtonsoft.Json.JsonConvert.DeserializeXmlNode(System.String)">
3216 <summary>
3217 Deserializes the XmlNode from a JSON string.
3218 </summary>
3219 <param name="value">The JSON string.</param>
3220 <returns>The deserialized XmlNode</returns>
3221 </member>
3222 <member name="M:Newtonsoft.Json.JsonConvert.DeserializeXmlNode(System.String,System.String)">
3223 <summary>
3224 Deserializes the XmlNode from a JSON string nested in a root elment.
3225 </summary>
3226 <param name="value">The JSON string.</param>
3227 <param name="deserializeRootElementName">The name of the root element to append when deserializing.</param>
3228 <returns>The deserialized XmlNode</returns>
3229 </member>
3230 <member name="T:Newtonsoft.Json.JsonSerializationException">
3231 <summary>
3232 The exception thrown when an error occurs during Json serialization or deserialization.
3233 </summary>
3234 </member>
3235 <member name="M:Newtonsoft.Json.JsonSerializationException.#ctor">
3236 <summary>
3237 Initializes a new instance of the <see cref="T:Newtonsoft.Json.JsonSerializationException"/> class.
3238 </summary>
3239 </member>
3240 <member name="M:Newtonsoft.Json.JsonSerializationException.#ctor(System.String)">
3241 <summary>
3242 Initializes a new instance of the <see cref="T:Newtonsoft.Json.JsonSerializationException"/> class
3243 with a specified error message.
3244 </summary>
3245 <param name="message">The error message that explains the reason for the exception.</param>
3246 </member>
3247 <member name="M:Newtonsoft.Json.JsonSerializationException.#ctor(System.String,System.Exception)">
3248 <summary>
3249 Initializes a new instance of the <see cref="T:Newtonsoft.Json.JsonSerializationException"/> class
3250 with a specified error message and a reference to the inner exception that is the cause of this exception.
3251 </summary>
3252 <param name="message">The error message that explains the reason for the exception.</param>
3253 <param name="innerException">The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.</param>
3254 </member>
3255 <member name="T:Newtonsoft.Json.JsonSerializer">
3256 <summary>
3257 Serializes and deserializes objects into and from the JSON format.
3258 The <see cref="T:Newtonsoft.Json.JsonSerializer"/> enables you to control how objects are encoded into JSON.
3259 </summary>
3260 </member>
3261 <member name="M:Newtonsoft.Json.JsonSerializer.#ctor">
3262 <summary>
3263 Initializes a new instance of the <see cref="T:Newtonsoft.Json.JsonSerializer"/> class.
3264 </summary>
3265 </member>
3266 <member name="M:Newtonsoft.Json.JsonSerializer.Create(Newtonsoft.Json.JsonSerializerSettings)">
3267 <summary>
3268 Creates a new <see cref="T:Newtonsoft.Json.JsonSerializer"/> instance using the specified <see cref="T:Newtonsoft.Json.JsonSerializerSettings"/>.
3269 </summary>
3270 <param name="settings">The settings to be applied to the <see cref="T:Newtonsoft.Json.JsonSerializer"/>.</param>
3271 <returns>A new <see cref="T:Newtonsoft.Json.JsonSerializer"/> instance using the specified <see cref="T:Newtonsoft.Json.JsonSerializerSettings"/>.</returns>
3272 </member>
3273 <member name="M:Newtonsoft.Json.JsonSerializer.Populate(System.IO.TextReader,System.Object)">
3274 <summary>
3275 Populates the JSON values onto the target object.
3276 </summary>
3277 <param name="reader">The <see cref="T:System.IO.TextReader"/> that contains the JSON structure to reader values from.</param>
3278 <param name="target">The target object to populate values onto.</param>
3279 </member>
3280 <member name="M:Newtonsoft.Json.JsonSerializer.Populate(Newtonsoft.Json.JsonReader,System.Object)">
3281 <summary>
3282 Populates the JSON values onto the target object.
3283 </summary>
3284 <param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader"/> that contains the JSON structure to reader values from.</param>
3285 <param name="target">The target object to populate values onto.</param>
3286 </member>
3287 <member name="M:Newtonsoft.Json.JsonSerializer.Deserialize(Newtonsoft.Json.JsonReader)">
3288 <summary>
3289 Deserializes the Json structure contained by the specified <see cref="T:Newtonsoft.Json.JsonReader"/>.
3290 </summary>
3291 <param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader"/> that contains the JSON structure to deserialize.</param>
3292 <returns>The <see cref="T:System.Object"/> being deserialized.</returns>
3293 </member>
3294 <member name="M:Newtonsoft.Json.JsonSerializer.Deserialize(System.IO.TextReader,System.Type)">
3295 <summary>
3296 Deserializes the Json structure contained by the specified <see cref="T:System.IO.StringReader"/>
3297 into an instance of the specified type.
3298 </summary>
3299 <param name="reader">The <see cref="T:System.IO.TextReader"/> containing the object.</param>
3300 <param name="objectType">The <see cref="T:System.Type"/> of object being deserialized.</param>
3301 <returns>The instance of <paramref name="objectType"/> being deserialized.</returns>
3302 </member>
3303 <member name="M:Newtonsoft.Json.JsonSerializer.Deserialize``1(Newtonsoft.Json.JsonReader)">
3304 <summary>
3305 Deserializes the Json structure contained by the specified <see cref="T:Newtonsoft.Json.JsonReader"/>
3306 into an instance of the specified type.
3307 </summary>
3308 <param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader"/> containing the object.</param>
3309 <typeparam name="T">The type of the object to deserialize.</typeparam>
3310 <returns>The instance of <typeparamref name="T"/> being deserialized.</returns>
3311 </member>
3312 <member name="M:Newtonsoft.Json.JsonSerializer.Deserialize(Newtonsoft.Json.JsonReader,System.Type)">
3313 <summary>
3314 Deserializes the Json structure contained by the specified <see cref="T:Newtonsoft.Json.JsonReader"/>
3315 into an instance of the specified type.
3316 </summary>
3317 <param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader"/> containing the object.</param>
3318 <param name="objectType">The <see cref="T:System.Type"/> of object being deserialized.</param>
3319 <returns>The instance of <paramref name="objectType"/> being deserialized.</returns>
3320 </member>
3321 <member name="M:Newtonsoft.Json.JsonSerializer.Serialize(System.IO.TextWriter,System.Object)">
3322 <summary>
3323 Serializes the specified <see cref="T:System.Object"/> and writes the Json structure
3324 to a <c>Stream</c> using the specified <see cref="T:System.IO.TextWriter"/>.
3325 </summary>
3326 <param name="textWriter">The <see cref="T:System.IO.TextWriter"/> used to write the Json structure.</param>
3327 <param name="value">The <see cref="T:System.Object"/> to serialize.</param>
3328 </member>
3329 <member name="M:Newtonsoft.Json.JsonSerializer.Serialize(Newtonsoft.Json.JsonWriter,System.Object)">
3330 <summary>
3331 Serializes the specified <see cref="T:System.Object"/> and writes the Json structure
3332 to a <c>Stream</c> using the specified <see cref="T:Newtonsoft.Json.JsonWriter"/>.
3333 </summary>
3334 <param name="jsonWriter">The <see cref="T:Newtonsoft.Json.JsonWriter"/> used to write the Json structure.</param>
3335 <param name="value">The <see cref="T:System.Object"/> to serialize.</param>
3336 </member>
3337 <member name="E:Newtonsoft.Json.JsonSerializer.Error">
3338 <summary>
3339 Occurs when the <see cref="T:Newtonsoft.Json.JsonSerializer"/> errors during serialization and deserialization.
3340 </summary>
3341 </member>
3342 <member name="P:Newtonsoft.Json.JsonSerializer.ReferenceResolver">
3343 <summary>
3344 Gets or sets the <see cref="T:Newtonsoft.Json.Serialization.IReferenceResolver"/> used by the serializer when resolving references.
3345 </summary>
3346 </member>
3347 <member name="P:Newtonsoft.Json.JsonSerializer.Binder">
3348 <summary>
3349 Gets or sets the <see cref="T:System.Runtime.Serialization.SerializationBinder"/> used by the serializer when resolving type names.
3350 </summary>
3351 </member>
3352 <member name="P:Newtonsoft.Json.JsonSerializer.TypeNameHandling">
3353 <summary>
3354 Gets or sets how type name writing and reading is handled by the serializer.
3355 </summary>
3356 </member>
3357 <member name="P:Newtonsoft.Json.JsonSerializer.PreserveReferencesHandling">
3358 <summary>
3359 Gets or sets how object references are preserved by the serializer.
3360 </summary>
3361 </member>
3362 <member name="P:Newtonsoft.Json.JsonSerializer.ReferenceLoopHandling">
3363 <summary>
3364 Get or set how reference loops (e.g. a class referencing itself) is handled.
3365 </summary>
3366 </member>
3367 <member name="P:Newtonsoft.Json.JsonSerializer.MissingMemberHandling">
3368 <summary>
3369 Get or set how missing members (e.g. JSON contains a property that isn't a member on the object) are handled during deserialization.
3370 </summary>
3371 </member>
3372 <member name="P:Newtonsoft.Json.JsonSerializer.NullValueHandling">
3373 <summary>
3374 Get or set how null values are handled during serialization and deserialization.
3375 </summary>
3376 </member>
3377 <member name="P:Newtonsoft.Json.JsonSerializer.DefaultValueHandling">
3378 <summary>
3379 Get or set how null default are handled during serialization and deserialization.
3380 </summary>
3381 </member>
3382 <member name="P:Newtonsoft.Json.JsonSerializer.ObjectCreationHandling">
3383 <summary>
3384 Gets or sets how objects are created during deserialization.
3385 </summary>
3386 <value>The object creation handling.</value>
3387 </member>
3388 <member name="P:Newtonsoft.Json.JsonSerializer.ConstructorHandling">
3389 <summary>
3390 Gets or sets how constructors are used during deserialization.
3391 </summary>
3392 <value>The constructor handling.</value>
3393 </member>
3394 <member name="P:Newtonsoft.Json.JsonSerializer.Converters">
3395 <summary>
3396 Gets a collection <see cref="T:Newtonsoft.Json.JsonConverter"/> that will be used during serialization.
3397 </summary>
3398 <value>Collection <see cref="T:Newtonsoft.Json.JsonConverter"/> that will be used during serialization.</value>
3399 </member>
3400 <member name="P:Newtonsoft.Json.JsonSerializer.ContractResolver">
3401 <summary>
3402 Gets or sets the contract resolver used by the serializer when
3403 serializing .NET objects to JSON and vice versa.
3404 </summary>
3405 </member>
3406 <member name="P:Newtonsoft.Json.JsonSerializer.Context">
3407 <summary>
3408 Gets or sets the <see cref="T:System.Runtime.Serialization.StreamingContext"/> used by the serializer when invoking serialization callback methods.
3409 </summary>
3410 <value>The context.</value>
3411 </member>
3412 <member name="T:Newtonsoft.Json.Linq.Extensions">
3413 <summary>
3414 Contains the LINQ to JSON extension methods.
3415 </summary>
3416 </member>
3417 <member name="M:Newtonsoft.Json.Linq.Extensions.Ancestors``1(System.Collections.Generic.IEnumerable{``0})">
3418 <summary>
3419 Returns a collection of tokens that contains the ancestors of every token in the source collection.
3420 </summary>
3421 <typeparam name="T">The type of the objects in source, constrained to <see cref="T:Newtonsoft.Json.Linq.JToken"/>.</typeparam>
3422 <param name="source">An <see cref="T:System.Collections.Generic.IEnumerable`1"/> of <see cref="T:Newtonsoft.Json.Linq.JToken"/> that contains the source collection.</param>
3423 <returns>An <see cref="T:System.Collections.Generic.IEnumerable`1"/> of <see cref="T:Newtonsoft.Json.Linq.JToken"/> that contains the ancestors of every node in the source collection.</returns>
3424 </member>
3425 <member name="M:Newtonsoft.Json.Linq.Extensions.Descendants``1(System.Collections.Generic.IEnumerable{``0})">
3426 <summary>
3427 Returns a collection of tokens that contains the descendants of every token in the source collection.
3428 </summary>
3429 <typeparam name="T">The type of the objects in source, constrained to <see cref="T:Newtonsoft.Json.Linq.JContainer"/>.</typeparam>
3430 <param name="source">An <see cref="T:System.Collections.Generic.IEnumerable`1"/> of <see cref="T:Newtonsoft.Json.Linq.JToken"/> that contains the source collection.</param>
3431 <returns>An <see cref="T:System.Collections.Generic.IEnumerable`1"/> of <see cref="T:Newtonsoft.Json.Linq.JToken"/> that contains the descendants of every node in the source collection.</returns>
3432 </member>
3433 <member name="M:Newtonsoft.Json.Linq.Extensions.Properties(System.Collections.Generic.IEnumerable{Newtonsoft.Json.Linq.JObject})">
3434 <summary>
3435 Returns a collection of child properties of every object in the source collection.
3436 </summary>
3437 <param name="source">An <see cref="T:System.Collections.Generic.IEnumerable`1"/> of <see cref="T:Newtonsoft.Json.Linq.JObject"/> that contains the source collection.</param>
3438 <returns>An <see cref="T:System.Collections.Generic.IEnumerable`1"/> of <see cref="T:Newtonsoft.Json.Linq.JProperty"/> that contains the properties of every object in the source collection.</returns>
3439 </member>
3440 <member name="M:Newtonsoft.Json.Linq.Extensions.Values(System.Collections.Generic.IEnumerable{Newtonsoft.Json.Linq.JToken},System.Object)">
3441 <summary>
3442 Returns a collection of child values of every object in the source collection with the given key.
3443 </summary>
3444 <param name="source">An <see cref="T:System.Collections.Generic.IEnumerable`1"/> of <see cref="T:Newtonsoft.Json.Linq.JToken"/> that contains the source collection.</param>
3445 <param name="key">The token key.</param>
3446 <returns>An <see cref="T:System.Collections.Generic.IEnumerable`1"/> of <see cref="T:Newtonsoft.Json.Linq.JToken"/> that contains the values of every node in the source collection with the given key.</returns>
3447 </member>
3448 <member name="M:Newtonsoft.Json.Linq.Extensions.Values(System.Collections.Generic.IEnumerable{Newtonsoft.Json.Linq.JToken})">
3449 <summary>
3450 Returns a collection of child values of every object in the source collection.
3451 </summary>
3452 <param name="source">An <see cref="T:System.Collections.Generic.IEnumerable`1"/> of <see cref="T:Newtonsoft.Json.Linq.JToken"/> that contains the source collection.</param>
3453 <returns>An <see cref="T:System.Collections.Generic.IEnumerable`1"/> of <see cref="T:Newtonsoft.Json.Linq.JToken"/> that contains the values of every node in the source collection.</returns>
3454 </member>
3455 <member name="M:Newtonsoft.Json.Linq.Extensions.Values``1(System.Collections.Generic.IEnumerable{Newtonsoft.Json.Linq.JToken},System.Object)">
3456 <summary>
3457 Returns a collection of converted child values of every object in the source collection with the given key.
3458 </summary>
3459 <typeparam name="U">The type to convert the values to.</typeparam>
3460 <param name="source">An <see cref="T:System.Collections.Generic.IEnumerable`1"/> of <see cref="T:Newtonsoft.Json.Linq.JToken"/> that contains the source collection.</param>
3461 <param name="key">The token key.</param>
3462 <returns>An <see cref="T:System.Collections.Generic.IEnumerable`1"/> that contains the converted values of every node in the source collection with the given key.</returns>
3463 </member>
3464 <member name="M:Newtonsoft.Json.Linq.Extensions.Values``1(System.Collections.Generic.IEnumerable{Newtonsoft.Json.Linq.JToken})">
3465 <summary>
3466 Returns a collection of converted child values of every object in the source collection.
3467 </summary>
3468 <typeparam name="U">The type to convert the values to.</typeparam>
3469 <param name="source">An <see cref="T:System.Collections.Generic.IEnumerable`1"/> of <see cref="T:Newtonsoft.Json.Linq.JToken"/> that contains the source collection.</param>
3470 <returns>An <see cref="T:System.Collections.Generic.IEnumerable`1"/> that contains the converted values of every node in the source collection.</returns>
3471 </member>
3472 <member name="M:Newtonsoft.Json.Linq.Extensions.Value``1(System.Collections.Generic.IEnumerable{Newtonsoft.Json.Linq.JToken})">
3473 <summary>
3474 Converts the value.
3475 </summary>
3476 <typeparam name="U">The type to convert the value to.</typeparam>
3477 <param name="value">A <see cref="T:Newtonsoft.Json.Linq.JToken"/> cast as a <see cref="T:System.Collections.Generic.IEnumerable`1"/> of <see cref="T:Newtonsoft.Json.Linq.JToken"/>.</param>
3478 <returns>A converted value.</returns>
3479 </member>
3480 <member name="M:Newtonsoft.Json.Linq.Extensions.Value``2(System.Collections.Generic.IEnumerable{``0})">
3481 <summary>
3482 Converts the value.
3483 </summary>
3484 <typeparam name="T">The source collection type.</typeparam>
3485 <typeparam name="U">The type to convert the value to.</typeparam>
3486 <param name="value">A <see cref="T:Newtonsoft.Json.Linq.JToken"/> cast as a <see cref="T:System.Collections.Generic.IEnumerable`1"/> of <see cref="T:Newtonsoft.Json.Linq.JToken"/>.</param>
3487 <returns>A converted value.</returns>
3488 </member>
3489 <member name="M:Newtonsoft.Json.Linq.Extensions.Children``1(System.Collections.Generic.IEnumerable{``0})">
3490 <summary>
3491 Returns a collection of child tokens of every array in the source collection.
3492 </summary>
3493 <typeparam name="T">The source collection type.</typeparam>
3494 <param name="source">An <see cref="T:System.Collections.Generic.IEnumerable`1"/> of <see cref="T:Newtonsoft.Json.Linq.JToken"/> that contains the source collection.</param>
3495 <returns>An <see cref="T:System.Collections.Generic.IEnumerable`1"/> of <see cref="T:Newtonsoft.Json.Linq.JToken"/> that contains the values of every node in the source collection.</returns>
3496 </member>
3497 <member name="M:Newtonsoft.Json.Linq.Extensions.Children``2(System.Collections.Generic.IEnumerable{``0})">
3498 <summary>
3499 Returns a collection of converted child tokens of every array in the source collection.
3500 </summary>
3501 <param name="source">An <see cref="T:System.Collections.Generic.IEnumerable`1"/> of <see cref="T:Newtonsoft.Json.Linq.JToken"/> that contains the source collection.</param>
3502 <typeparam name="U">The type to convert the values to.</typeparam>
3503 <typeparam name="T">The source collection type.</typeparam>
3504 <returns>An <see cref="T:System.Collections.Generic.IEnumerable`1"/> that contains the converted values of every node in the source collection.</returns>
3505 </member>
3506 <member name="M:Newtonsoft.Json.Linq.Extensions.AsJEnumerable(System.Collections.Generic.IEnumerable{Newtonsoft.Json.Linq.JToken})">
3507 <summary>
3508 Returns the input typed as <see cref="T:Newtonsoft.Json.Linq.IJEnumerable`1"/>.
3509 </summary>
3510 <param name="source">An <see cref="T:System.Collections.Generic.IEnumerable`1"/> of <see cref="T:Newtonsoft.Json.Linq.JToken"/> that contains the source collection.</param>
3511 <returns>The input typed as <see cref="T:Newtonsoft.Json.Linq.IJEnumerable`1"/>.</returns>
3512 </member>
3513 <member name="M:Newtonsoft.Json.Linq.Extensions.AsJEnumerable``1(System.Collections.Generic.IEnumerable{``0})">
3514 <summary>
3515 Returns the input typed as <see cref="T:Newtonsoft.Json.Linq.IJEnumerable`1"/>.
3516 </summary>
3517 <typeparam name="T">The source collection type.</typeparam>
3518 <param name="source">An <see cref="T:System.Collections.Generic.IEnumerable`1"/> of <see cref="T:Newtonsoft.Json.Linq.JToken"/> that contains the source collection.</param>
3519 <returns>The input typed as <see cref="T:Newtonsoft.Json.Linq.IJEnumerable`1"/>.</returns>
3520 </member>
3521 <member name="T:Newtonsoft.Json.Linq.JConstructor">
3522 <summary>
3523 Represents a JSON constructor.
3524 </summary>
3525 </member>
3526 <member name="T:Newtonsoft.Json.Linq.JContainer">
3527 <summary>
3528 Represents a token that can contain other tokens.
3529 </summary>
3530 </member>
3531 <member name="M:Newtonsoft.Json.Linq.JContainer.OnAddingNew(System.ComponentModel.AddingNewEventArgs)">
3532 <summary>
3533 Raises the <see cref="E:Newtonsoft.Json.Linq.JContainer.AddingNew"/> event.
3534 </summary>
3535 <param name="e">The <see cref="T:System.ComponentModel.AddingNewEventArgs"/> instance containing the event data.</param>
3536 </member>
3537 <member name="M:Newtonsoft.Json.Linq.JContainer.OnListChanged(System.ComponentModel.ListChangedEventArgs)">
3538 <summary>
3539 Raises the <see cref="E:Newtonsoft.Json.Linq.JContainer.ListChanged"/> event.
3540 </summary>
3541 <param name="e">The <see cref="T:System.ComponentModel.ListChangedEventArgs"/> instance containing the event data.</param>
3542 </member>
3543 <member name="M:Newtonsoft.Json.Linq.JContainer.Children">
3544 <summary>
3545 Returns a collection of the child tokens of this token, in document order.
3546 </summary>
3547 <returns>
3548 An <see cref="T:System.Collections.Generic.IEnumerable`1"/> of <see cref="T:Newtonsoft.Json.Linq.JToken"/> containing the child tokens of this <see cref="T:Newtonsoft.Json.Linq.JToken"/>, in document order.
3549 </returns>
3550 </member>
3551 <member name="M:Newtonsoft.Json.Linq.JContainer.Values``1">
3552 <summary>
3553 Returns a collection of the child values of this token, in document order.
3554 </summary>
3555 <typeparam name="T">The type to convert the values to.</typeparam>
3556 <returns>
3557 A <see cref="T:System.Collections.Generic.IEnumerable`1"/> containing the child values of this <see cref="T:Newtonsoft.Json.Linq.JToken"/>, in document order.
3558 </returns>
3559 </member>
3560 <member name="M:Newtonsoft.Json.Linq.JContainer.Descendants">
3561 <summary>
3562 Returns a collection of the descendant tokens for this token in document order.
3563 </summary>
3564 <returns>An <see cref="T:System.Collections.Generic.IEnumerable`1"/> containing the descendant tokens of the <see cref="T:Newtonsoft.Json.Linq.JToken"/>.</returns>
3565 </member>
3566 <member name="M:Newtonsoft.Json.Linq.JContainer.Add(System.Object)">
3567 <summary>
3568 Adds the specified content as children of this <see cref="T:Newtonsoft.Json.Linq.JToken"/>.
3569 </summary>
3570 <param name="content">The content to be added.</param>
3571 </member>
3572 <member name="M:Newtonsoft.Json.Linq.JContainer.AddFirst(System.Object)">
3573 <summary>
3574 Adds the specified content as the first children of this <see cref="T:Newtonsoft.Json.Linq.JToken"/>.
3575 </summary>
3576 <param name="content">The content to be added.</param>
3577 </member>
3578 <member name="M:Newtonsoft.Json.Linq.JContainer.CreateWriter">
3579 <summary>
3580 Creates an <see cref="T:Newtonsoft.Json.JsonWriter"/> that can be used to add tokens to the <see cref="T:Newtonsoft.Json.Linq.JToken"/>.
3581 </summary>
3582 <returns>An <see cref="T:Newtonsoft.Json.JsonWriter"/> that is ready to have content written to it.</returns>
3583 </member>
3584 <member name="M:Newtonsoft.Json.Linq.JContainer.ReplaceAll(System.Object)">
3585 <summary>
3586 Replaces the children nodes of this token with the specified content.
3587 </summary>
3588 <param name="content">The content.</param>
3589 </member>
3590 <member name="M:Newtonsoft.Json.Linq.JContainer.RemoveAll">
3591 <summary>
3592 Removes the child nodes from this token.
3593 </summary>
3594 </member>
3595 <member name="E:Newtonsoft.Json.Linq.JContainer.ListChanged">
3596 <summary>
3597 Occurs when the list changes or an item in the list changes.
3598 </summary>
3599 </member>
3600 <member name="E:Newtonsoft.Json.Linq.JContainer.AddingNew">
3601 <summary>
3602 Occurs before an item is added to the collection.
3603 </summary>
3604 </member>
3605 <member name="P:Newtonsoft.Json.Linq.JContainer.HasValues">
3606 <summary>
3607 Gets a value indicating whether this token has childen tokens.
3608 </summary>
3609 <value>
3610 <c>true</c> if this token has child values; otherwise, <c>false</c>.
3611 </value>
3612 </member>
3613 <member name="P:Newtonsoft.Json.Linq.JContainer.First">
3614 <summary>
3615 Get the first child token of this token.
3616 </summary>
3617 <value>
3618 A <see cref="T:Newtonsoft.Json.Linq.JToken"/> containing the first child token of the <see cref="T:Newtonsoft.Json.Linq.JToken"/>.
3619 </value>
3620 </member>
3621 <member name="P:Newtonsoft.Json.Linq.JContainer.Last">
3622 <summary>
3623 Get the last child token of this token.
3624 </summary>
3625 <value>
3626 A <see cref="T:Newtonsoft.Json.Linq.JToken"/> containing the last child token of the <see cref="T:Newtonsoft.Json.Linq.JToken"/>.
3627 </value>
3628 </member>
3629 <member name="M:Newtonsoft.Json.Linq.JConstructor.#ctor">
3630 <summary>
3631 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Linq.JConstructor"/> class.
3632 </summary>
3633 </member>
3634 <member name="M:Newtonsoft.Json.Linq.JConstructor.#ctor(Newtonsoft.Json.Linq.JConstructor)">
3635 <summary>
3636 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Linq.JConstructor"/> class from another <see cref="T:Newtonsoft.Json.Linq.JConstructor"/> object.
3637 </summary>
3638 <param name="other">A <see cref="T:Newtonsoft.Json.Linq.JConstructor"/> object to copy from.</param>
3639 </member>
3640 <member name="M:Newtonsoft.Json.Linq.JConstructor.#ctor(System.String,System.Object[])">
3641 <summary>
3642 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Linq.JConstructor"/> class with the specified name and content.
3643 </summary>
3644 <param name="name">The constructor name.</param>
3645 <param name="content">The contents of the constructor.</param>
3646 </member>
3647 <member name="M:Newtonsoft.Json.Linq.JConstructor.#ctor(System.String,System.Object)">
3648 <summary>
3649 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Linq.JConstructor"/> class with the specified name and content.
3650 </summary>
3651 <param name="name">The constructor name.</param>
3652 <param name="content">The contents of the constructor.</param>
3653 </member>
3654 <member name="M:Newtonsoft.Json.Linq.JConstructor.#ctor(System.String)">
3655 <summary>
3656 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Linq.JConstructor"/> class with the specified name.
3657 </summary>
3658 <param name="name">The constructor name.</param>
3659 </member>
3660 <member name="M:Newtonsoft.Json.Linq.JConstructor.WriteTo(Newtonsoft.Json.JsonWriter,Newtonsoft.Json.JsonConverter[])">
3661 <summary>
3662 Writes this token to a <see cref="T:Newtonsoft.Json.JsonWriter"/>.
3663 </summary>
3664 <param name="writer">A <see cref="T:Newtonsoft.Json.JsonWriter"/> into which this method will write.</param>
3665 <param name="converters">A collection of <see cref="T:Newtonsoft.Json.JsonConverter"/> which will be used when writing the token.</param>
3666 </member>
3667 <member name="M:Newtonsoft.Json.Linq.JConstructor.Load(Newtonsoft.Json.JsonReader)">
3668 <summary>
3669 Loads an <see cref="T:Newtonsoft.Json.Linq.JConstructor"/> from a <see cref="T:Newtonsoft.Json.JsonReader"/>.
3670 </summary>
3671 <param name="reader">A <see cref="T:Newtonsoft.Json.JsonReader"/> that will be read for the content of the <see cref="T:Newtonsoft.Json.Linq.JConstructor"/>.</param>
3672 <returns>A <see cref="T:Newtonsoft.Json.Linq.JConstructor"/> that contains the JSON that was read from the specified <see cref="T:Newtonsoft.Json.JsonReader"/>.</returns>
3673 </member>
3674 <member name="P:Newtonsoft.Json.Linq.JConstructor.Name">
3675 <summary>
3676 Gets or sets the name of this constructor.
3677 </summary>
3678 <value>The constructor name.</value>
3679 </member>
3680 <member name="P:Newtonsoft.Json.Linq.JConstructor.Type">
3681 <summary>
3682 Gets the node type for this <see cref="T:Newtonsoft.Json.Linq.JToken"/>.
3683 </summary>
3684 <value>The type.</value>
3685 </member>
3686 <member name="P:Newtonsoft.Json.Linq.JConstructor.Item(System.Object)">
3687 <summary>
3688 Gets the <see cref="T:Newtonsoft.Json.Linq.JToken"/> with the specified key.
3689 </summary>
3690 <value>The <see cref="T:Newtonsoft.Json.Linq.JToken"/> with the specified key.</value>
3691 </member>
3692 <member name="T:Newtonsoft.Json.Linq.JEnumerable`1">
3693 <summary>
3694 Represents a collection of <see cref="T:Newtonsoft.Json.Linq.JToken"/> objects.
3695 </summary>
3696 <typeparam name="T">The type of token</typeparam>
3697 </member>
3698 <member name="F:Newtonsoft.Json.Linq.JEnumerable`1.Empty">
3699 <summary>
3700 An empty collection of <see cref="T:Newtonsoft.Json.Linq.JToken"/> objects.
3701 </summary>
3702 </member>
3703 <member name="M:Newtonsoft.Json.Linq.JEnumerable`1.#ctor(System.Collections.Generic.IEnumerable{`0})">
3704 <summary>
3705 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Linq.JEnumerable`1"/> struct.
3706 </summary>
3707 <param name="enumerable">The enumerable.</param>
3708 </member>
3709 <member name="M:Newtonsoft.Json.Linq.JEnumerable`1.GetEnumerator">
3710 <summary>
3711 Returns an enumerator that iterates through the collection.
3712 </summary>
3713 <returns>
3714 A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.
3715 </returns>
3716 </member>
3717 <member name="M:Newtonsoft.Json.Linq.JEnumerable`1.System#Collections#IEnumerable#GetEnumerator">
3718 <summary>
3719 Returns an enumerator that iterates through a collection.
3720 </summary>
3721 <returns>
3722 An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
3723 </returns>
3724 </member>
3725 <member name="M:Newtonsoft.Json.Linq.JEnumerable`1.Equals(System.Object)">
3726 <summary>
3727 Determines whether the specified <see cref="T:System.Object"/> is equal to this instance.
3728 </summary>
3729 <param name="obj">The <see cref="T:System.Object"/> to compare with this instance.</param>
3730 <returns>
3731 <c>true</c> if the specified <see cref="T:System.Object"/> is equal to this instance; otherwise, <c>false</c>.
3732 </returns>
3733 </member>
3734 <member name="M:Newtonsoft.Json.Linq.JEnumerable`1.GetHashCode">
3735 <summary>
3736 Returns a hash code for this instance.
3737 </summary>
3738 <returns>
3739 A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
3740 </returns>
3741 </member>
3742 <member name="P:Newtonsoft.Json.Linq.JEnumerable`1.Item(System.Object)">
3743 <summary>
3744 Gets the <see cref="T:Newtonsoft.Json.Linq.IJEnumerable`1"/> with the specified key.
3745 </summary>
3746 <value></value>
3747 </member>
3748 <member name="T:Newtonsoft.Json.Linq.JObject">
3749 <summary>
3750 Represents a JSON object.
3751 </summary>
3752 </member>
3753 <member name="M:Newtonsoft.Json.Linq.JObject.#ctor">
3754 <summary>
3755 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Linq.JObject"/> class.
3756 </summary>
3757 </member>
3758 <member name="M:Newtonsoft.Json.Linq.JObject.#ctor(Newtonsoft.Json.Linq.JObject)">
3759 <summary>
3760 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Linq.JObject"/> class from another <see cref="T:Newtonsoft.Json.Linq.JObject"/> object.
3761 </summary>
3762 <param name="other">A <see cref="T:Newtonsoft.Json.Linq.JObject"/> object to copy from.</param>
3763 </member>
3764 <member name="M:Newtonsoft.Json.Linq.JObject.#ctor(System.Object[])">
3765 <summary>
3766 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Linq.JObject"/> class with the specified content.
3767 </summary>
3768 <param name="content">The contents of the object.</param>
3769 </member>
3770 <member name="M:Newtonsoft.Json.Linq.JObject.#ctor(System.Object)">
3771 <summary>
3772 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Linq.JObject"/> class with the specified content.
3773 </summary>
3774 <param name="content">The contents of the object.</param>
3775 </member>
3776 <member name="M:Newtonsoft.Json.Linq.JObject.Properties">
3777 <summary>
3778 Gets an <see cref="T:System.Collections.Generic.IEnumerable`1"/> of this object's properties.
3779 </summary>
3780 <returns>An <see cref="T:System.Collections.Generic.IEnumerable`1"/> of this object's properties.</returns>
3781 </member>
3782 <member name="M:Newtonsoft.Json.Linq.JObject.Property(System.String)">
3783 <summary>
3784 Gets a <see cref="T:Newtonsoft.Json.Linq.JProperty"/> the specified name.
3785 </summary>
3786 <param name="name">The property name.</param>
3787 <returns>A <see cref="T:Newtonsoft.Json.Linq.JProperty"/> with the specified name or null.</returns>
3788 </member>
3789 <member name="M:Newtonsoft.Json.Linq.JObject.PropertyValues">
3790 <summary>
3791 Gets an <see cref="T:Newtonsoft.Json.Linq.JEnumerable`1"/> of this object's property values.
3792 </summary>
3793 <returns>An <see cref="T:Newtonsoft.Json.Linq.JEnumerable`1"/> of this object's property values.</returns>
3794 </member>
3795 <member name="M:Newtonsoft.Json.Linq.JObject.Load(Newtonsoft.Json.JsonReader)">
3796 <summary>
3797 Loads an <see cref="T:Newtonsoft.Json.Linq.JObject"/> from a <see cref="T:Newtonsoft.Json.JsonReader"/>.
3798 </summary>
3799 <param name="reader">A <see cref="T:Newtonsoft.Json.JsonReader"/> that will be read for the content of the <see cref="T:Newtonsoft.Json.Linq.JObject"/>.</param>
3800 <returns>A <see cref="T:Newtonsoft.Json.Linq.JObject"/> that contains the JSON that was read from the specified <see cref="T:Newtonsoft.Json.JsonReader"/>.</returns>
3801 </member>
3802 <member name="M:Newtonsoft.Json.Linq.JObject.Parse(System.String)">
3803 <summary>
3804 Load a <see cref="T:Newtonsoft.Json.Linq.JObject"/> from a string that contains JSON.
3805 </summary>
3806 <param name="json">A <see cref="T:System.String"/> that contains JSON.</param>
3807 <returns>A <see cref="T:Newtonsoft.Json.Linq.JObject"/> populated from the string that contains JSON.</returns>
3808 </member>
3809 <member name="M:Newtonsoft.Json.Linq.JObject.FromObject(System.Object)">
3810 <summary>
3811 Creates a <see cref="T:Newtonsoft.Json.Linq.JObject"/> from an object.
3812 </summary>
3813 <param name="o">The object that will be used to create <see cref="T:Newtonsoft.Json.Linq.JObject"/>.</param>
3814 <returns>A <see cref="T:Newtonsoft.Json.Linq.JObject"/> with the values of the specified object</returns>
3815 </member>
3816 <member name="M:Newtonsoft.Json.Linq.JObject.FromObject(System.Object,Newtonsoft.Json.JsonSerializer)">
3817 <summary>
3818 Creates a <see cref="T:Newtonsoft.Json.Linq.JArray"/> from an object.
3819 </summary>
3820 <param name="o">The object that will be used to create <see cref="T:Newtonsoft.Json.Linq.JArray"/>.</param>
3821 <param name="jsonSerializer">The <see cref="T:Newtonsoft.Json.JsonSerializer"/> that will be used to read the object.</param>
3822 <returns>A <see cref="T:Newtonsoft.Json.Linq.JArray"/> with the values of the specified object</returns>
3823 </member>
3824 <member name="M:Newtonsoft.Json.Linq.JObject.WriteTo(Newtonsoft.Json.JsonWriter,Newtonsoft.Json.JsonConverter[])">
3825 <summary>
3826 Writes this token to a <see cref="T:Newtonsoft.Json.JsonWriter"/>.
3827 </summary>
3828 <param name="writer">A <see cref="T:Newtonsoft.Json.JsonWriter"/> into which this method will write.</param>
3829 <param name="converters">A collection of <see cref="T:Newtonsoft.Json.JsonConverter"/> which will be used when writing the token.</param>
3830 </member>
3831 <member name="M:Newtonsoft.Json.Linq.JObject.Add(System.String,Newtonsoft.Json.Linq.JToken)">
3832 <summary>
3833 Adds the specified property name.
3834 </summary>
3835 <param name="propertyName">Name of the property.</param>
3836 <param name="value">The value.</param>
3837 </member>
3838 <member name="M:Newtonsoft.Json.Linq.JObject.Remove(System.String)">
3839 <summary>
3840 Removes the property with the specified name.
3841 </summary>
3842 <param name="propertyName">Name of the property.</param>
3843 <returns>true if item was successfully removed; otherwise, false.</returns>
3844 </member>
3845 <member name="M:Newtonsoft.Json.Linq.JObject.TryGetValue(System.String,Newtonsoft.Json.Linq.JToken@)">
3846 <summary>
3847 Tries the get value.
3848 </summary>
3849 <param name="propertyName">Name of the property.</param>
3850 <param name="value">The value.</param>
3851 <returns>true if a value was successfully retrieved; otherwise, false.</returns>
3852 </member>
3853 <member name="M:Newtonsoft.Json.Linq.JObject.GetEnumerator">
3854 <summary>
3855 Returns an enumerator that iterates through the collection.
3856 </summary>
3857 <returns>
3858 A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.
3859 </returns>
3860 </member>
3861 <member name="M:Newtonsoft.Json.Linq.JObject.OnPropertyChanged(System.String)">
3862 <summary>
3863 Raises the <see cref="E:Newtonsoft.Json.Linq.JObject.PropertyChanged"/> event with the provided arguments.
3864 </summary>
3865 <param name="propertyName">Name of the property.</param>
3866 </member>
3867 <member name="E:Newtonsoft.Json.Linq.JObject.PropertyChanged">
3868 <summary>
3869 Occurs when a property value changes.
3870 </summary>
3871 </member>
3872 <member name="P:Newtonsoft.Json.Linq.JObject.Type">
3873 <summary>
3874 Gets the node type for this <see cref="T:Newtonsoft.Json.Linq.JToken"/>.
3875 </summary>
3876 <value>The type.</value>
3877 </member>
3878 <member name="P:Newtonsoft.Json.Linq.JObject.Item(System.Object)">
3879 <summary>
3880 Gets the <see cref="T:Newtonsoft.Json.Linq.JToken"/> with the specified key.
3881 </summary>
3882 <value>The <see cref="T:Newtonsoft.Json.Linq.JToken"/> with the specified key.</value>
3883 </member>
3884 <member name="P:Newtonsoft.Json.Linq.JObject.Item(System.String)">
3885 <summary>
3886 Gets or sets the <see cref="T:Newtonsoft.Json.Linq.JToken"/> with the specified property name.
3887 </summary>
3888 <value></value>
3889 </member>
3890 <member name="P:Newtonsoft.Json.Linq.JObject.Count">
3891 <summary>
3892 Gets the number of elements contained in the <see cref="T:System.Collections.Generic.ICollection`1"/>.
3893 </summary>
3894 <value></value>
3895 <returns>The number of elements contained in the <see cref="T:System.Collections.Generic.ICollection`1"/>.</returns>
3896 </member>
3897 <member name="T:Newtonsoft.Json.Linq.JArray">
3898 <summary>
3899 Represents a JSON array.
3900 </summary>
3901 </member>
3902 <member name="M:Newtonsoft.Json.Linq.JArray.#ctor">
3903 <summary>
3904 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Linq.JArray"/> class.
3905 </summary>
3906 </member>
3907 <member name="M:Newtonsoft.Json.Linq.JArray.#ctor(Newtonsoft.Json.Linq.JArray)">
3908 <summary>
3909 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Linq.JArray"/> class from another <see cref="T:Newtonsoft.Json.Linq.JArray"/> object.
3910 </summary>
3911 <param name="other">A <see cref="T:Newtonsoft.Json.Linq.JArray"/> object to copy from.</param>
3912 </member>
3913 <member name="M:Newtonsoft.Json.Linq.JArray.#ctor(System.Object[])">
3914 <summary>
3915 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Linq.JArray"/> class with the specified content.
3916 </summary>
3917 <param name="content">The contents of the array.</param>
3918 </member>
3919 <member name="M:Newtonsoft.Json.Linq.JArray.#ctor(System.Object)">
3920 <summary>
3921 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Linq.JArray"/> class with the specified content.
3922 </summary>
3923 <param name="content">The contents of the array.</param>
3924 </member>
3925 <member name="M:Newtonsoft.Json.Linq.JArray.Load(Newtonsoft.Json.JsonReader)">
3926 <summary>
3927 Loads an <see cref="T:Newtonsoft.Json.Linq.JArray"/> from a <see cref="T:Newtonsoft.Json.JsonReader"/>.
3928 </summary>
3929 <param name="reader">A <see cref="T:Newtonsoft.Json.JsonReader"/> that will be read for the content of the <see cref="T:Newtonsoft.Json.Linq.JArray"/>.</param>
3930 <returns>A <see cref="T:Newtonsoft.Json.Linq.JArray"/> that contains the JSON that was read from the specified <see cref="T:Newtonsoft.Json.JsonReader"/>.</returns>
3931 </member>
3932 <member name="M:Newtonsoft.Json.Linq.JArray.Parse(System.String)">
3933 <summary>
3934 Load a <see cref="T:Newtonsoft.Json.Linq.JArray"/> from a string that contains JSON.
3935 </summary>
3936 <param name="json">A <see cref="T:System.String"/> that contains JSON.</param>
3937 <returns>A <see cref="T:Newtonsoft.Json.Linq.JArray"/> populated from the string that contains JSON.</returns>
3938 </member>
3939 <member name="M:Newtonsoft.Json.Linq.JArray.FromObject(System.Object)">
3940 <summary>
3941 Creates a <see cref="T:Newtonsoft.Json.Linq.JArray"/> from an object.
3942 </summary>
3943 <param name="o">The object that will be used to create <see cref="T:Newtonsoft.Json.Linq.JArray"/>.</param>
3944 <returns>A <see cref="T:Newtonsoft.Json.Linq.JArray"/> with the values of the specified object</returns>
3945 </member>
3946 <member name="M:Newtonsoft.Json.Linq.JArray.FromObject(System.Object,Newtonsoft.Json.JsonSerializer)">
3947 <summary>
3948 Creates a <see cref="T:Newtonsoft.Json.Linq.JArray"/> from an object.
3949 </summary>
3950 <param name="o">The object that will be used to create <see cref="T:Newtonsoft.Json.Linq.JArray"/>.</param>
3951 <param name="jsonSerializer">The <see cref="T:Newtonsoft.Json.JsonSerializer"/> that will be used to read the object.</param>
3952 <returns>A <see cref="T:Newtonsoft.Json.Linq.JArray"/> with the values of the specified object</returns>
3953 </member>
3954 <member name="M:Newtonsoft.Json.Linq.JArray.WriteTo(Newtonsoft.Json.JsonWriter,Newtonsoft.Json.JsonConverter[])">
3955 <summary>
3956 Writes this token to a <see cref="T:Newtonsoft.Json.JsonWriter"/>.
3957 </summary>
3958 <param name="writer">A <see cref="T:Newtonsoft.Json.JsonWriter"/> into which this method will write.</param>
3959 <param name="converters">A collection of <see cref="T:Newtonsoft.Json.JsonConverter"/> which will be used when writing the token.</param>
3960 </member>
3961 <member name="M:Newtonsoft.Json.Linq.JArray.IndexOf(Newtonsoft.Json.Linq.JToken)">
3962 <summary>
3963 Determines the index of a specific item in the <see cref="T:System.Collections.Generic.IList`1"/>.
3964 </summary>
3965 <param name="item">The object to locate in the <see cref="T:System.Collections.Generic.IList`1"/>.</param>
3966 <returns>
3967 The index of <paramref name="item"/> if found in the list; otherwise, -1.
3968 </returns>
3969 </member>
3970 <member name="M:Newtonsoft.Json.Linq.JArray.Insert(System.Int32,Newtonsoft.Json.Linq.JToken)">
3971 <summary>
3972 Inserts an item to the <see cref="T:System.Collections.Generic.IList`1"/> at the specified index.
3973 </summary>
3974 <param name="index">The zero-based index at which <paramref name="item"/> should be inserted.</param>
3975 <param name="item">The object to insert into the <see cref="T:System.Collections.Generic.IList`1"/>.</param>
3976 <exception cref="T:System.ArgumentOutOfRangeException">
3977 <paramref name="index"/> is not a valid index in the <see cref="T:System.Collections.Generic.IList`1"/>.</exception>
3978 <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.IList`1"/> is read-only.</exception>
3979 </member>
3980 <member name="M:Newtonsoft.Json.Linq.JArray.RemoveAt(System.Int32)">
3981 <summary>
3982 Removes the <see cref="T:System.Collections.Generic.IList`1"/> item at the specified index.
3983 </summary>
3984 <param name="index">The zero-based index of the item to remove.</param>
3985 <exception cref="T:System.ArgumentOutOfRangeException">
3986 <paramref name="index"/> is not a valid index in the <see cref="T:System.Collections.Generic.IList`1"/>.</exception>
3987 <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.IList`1"/> is read-only.</exception>
3988 </member>
3989 <member name="M:Newtonsoft.Json.Linq.JArray.Add(Newtonsoft.Json.Linq.JToken)">
3990 <summary>
3991 Adds an item to the <see cref="T:System.Collections.Generic.ICollection`1"/>.
3992 </summary>
3993 <param name="item">The object to add to the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param>
3994 <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.</exception>
3995 </member>
3996 <member name="M:Newtonsoft.Json.Linq.JArray.Clear">
3997 <summary>
3998 Removes all items from the <see cref="T:System.Collections.Generic.ICollection`1"/>.
3999 </summary>
4000 <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only. </exception>
4001 </member>
4002 <member name="M:Newtonsoft.Json.Linq.JArray.Contains(Newtonsoft.Json.Linq.JToken)">
4003 <summary>
4004 Determines whether the <see cref="T:System.Collections.Generic.ICollection`1"/> contains a specific value.
4005 </summary>
4006 <param name="item">The object to locate in the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param>
4007 <returns>
4008 true if <paramref name="item"/> is found in the <see cref="T:System.Collections.Generic.ICollection`1"/>; otherwise, false.
4009 </returns>
4010 </member>
4011 <member name="M:Newtonsoft.Json.Linq.JArray.Remove(Newtonsoft.Json.Linq.JToken)">
4012 <summary>
4013 Removes the first occurrence of a specific object from the <see cref="T:System.Collections.Generic.ICollection`1"/>.
4014 </summary>
4015 <param name="item">The object to remove from the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param>
4016 <returns>
4017 true if <paramref name="item"/> was successfully removed from the <see cref="T:System.Collections.Generic.ICollection`1"/>; otherwise, false. This method also returns false if <paramref name="item"/> is not found in the original <see cref="T:System.Collections.Generic.ICollection`1"/>.
4018 </returns>
4019 <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.</exception>
4020 </member>
4021 <member name="P:Newtonsoft.Json.Linq.JArray.Type">
4022 <summary>
4023 Gets the node type for this <see cref="T:Newtonsoft.Json.Linq.JToken"/>.
4024 </summary>
4025 <value>The type.</value>
4026 </member>
4027 <member name="P:Newtonsoft.Json.Linq.JArray.Item(System.Object)">
4028 <summary>
4029 Gets the <see cref="T:Newtonsoft.Json.Linq.JToken"/> with the specified key.
4030 </summary>
4031 <value>The <see cref="T:Newtonsoft.Json.Linq.JToken"/> with the specified key.</value>
4032 </member>
4033 <member name="P:Newtonsoft.Json.Linq.JArray.Item(System.Int32)">
4034 <summary>
4035 Gets or sets the <see cref="T:Newtonsoft.Json.Linq.JToken"/> at the specified index.
4036 </summary>
4037 <value></value>
4038 </member>
4039 <member name="P:Newtonsoft.Json.Linq.JArray.Count">
4040 <summary>
4041 Gets the number of elements contained in the <see cref="T:System.Collections.Generic.ICollection`1"/>.
4042 </summary>
4043 <value></value>
4044 <returns>The number of elements contained in the <see cref="T:System.Collections.Generic.ICollection`1"/>.</returns>
4045 </member>
4046 <member name="T:Newtonsoft.Json.Linq.JTokenReader">
4047 <summary>
4048 Represents a reader that provides fast, non-cached, forward-only access to serialized Json data.
4049 </summary>
4050 </member>
4051 <member name="M:Newtonsoft.Json.Linq.JTokenReader.#ctor(Newtonsoft.Json.Linq.JToken)">
4052 <summary>
4053 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Linq.JTokenReader"/> class.
4054 </summary>
4055 <param name="token">The token to read from.</param>
4056 </member>
4057 <member name="M:Newtonsoft.Json.Linq.JTokenReader.ReadAsBytes">
4058 <summary>
4059 Reads the next JSON token from the stream as a <see cref="T:Byte[]"/>.
4060 </summary>
4061 <returns>
4062 A <see cref="T:Byte[]"/> or a null reference if the next JSON token is null.
4063 </returns>
4064 </member>
4065 <member name="M:Newtonsoft.Json.Linq.JTokenReader.Read">
4066 <summary>
4067 Reads the next JSON token from the stream.
4068 </summary>
4069 <returns>
4070 true if the next token was read successfully; false if there are no more tokens to read.
4071 </returns>
4072 </member>
4073 <member name="T:Newtonsoft.Json.Linq.JProperty">
4074 <summary>
4075 Represents a JSON property.
4076 </summary>
4077 </member>
4078 <member name="M:Newtonsoft.Json.Linq.JProperty.#ctor(Newtonsoft.Json.Linq.JProperty)">
4079 <summary>
4080 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Linq.JProperty"/> class from another <see cref="T:Newtonsoft.Json.Linq.JProperty"/> object.
4081 </summary>
4082 <param name="other">A <see cref="T:Newtonsoft.Json.Linq.JProperty"/> object to copy from.</param>
4083 </member>
4084 <member name="M:Newtonsoft.Json.Linq.JProperty.Children">
4085 <summary>
4086 Returns a collection of the child tokens of this token, in document order.
4087 </summary>
4088 <returns>
4089 An <see cref="T:System.Collections.Generic.IEnumerable`1"/> of <see cref="T:Newtonsoft.Json.Linq.JToken"/> containing the child tokens of this <see cref="T:Newtonsoft.Json.Linq.JToken"/>, in document order.
4090 </returns>
4091 </member>
4092 <member name="M:Newtonsoft.Json.Linq.JProperty.#ctor(System.String,System.Object[])">
4093 <summary>
4094 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Linq.JProperty"/> class.
4095 </summary>
4096 <param name="name">The property name.</param>
4097 <param name="content">The property content.</param>
4098 </member>
4099 <member name="M:Newtonsoft.Json.Linq.JProperty.#ctor(System.String,System.Object)">
4100 <summary>
4101 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Linq.JProperty"/> class.
4102 </summary>
4103 <param name="name">The property name.</param>
4104 <param name="content">The property content.</param>
4105 </member>
4106 <member name="M:Newtonsoft.Json.Linq.JProperty.WriteTo(Newtonsoft.Json.JsonWriter,Newtonsoft.Json.JsonConverter[])">
4107 <summary>
4108 Writes this token to a <see cref="T:Newtonsoft.Json.JsonWriter"/>.
4109 </summary>
4110 <param name="writer">A <see cref="T:Newtonsoft.Json.JsonWriter"/> into which this method will write.</param>
4111 <param name="converters">A collection of <see cref="T:Newtonsoft.Json.JsonConverter"/> which will be used when writing the token.</param>
4112 </member>
4113 <member name="M:Newtonsoft.Json.Linq.JProperty.Load(Newtonsoft.Json.JsonReader)">
4114 <summary>
4115 Loads an <see cref="T:Newtonsoft.Json.Linq.JProperty"/> from a <see cref="T:Newtonsoft.Json.JsonReader"/>.
4116 </summary>
4117 <param name="reader">A <see cref="T:Newtonsoft.Json.JsonReader"/> that will be read for the content of the <see cref="T:Newtonsoft.Json.Linq.JProperty"/>.</param>
4118 <returns>A <see cref="T:Newtonsoft.Json.Linq.JProperty"/> that contains the JSON that was read from the specified <see cref="T:Newtonsoft.Json.JsonReader"/>.</returns>
4119 </member>
4120 <member name="P:Newtonsoft.Json.Linq.JProperty.Name">
4121 <summary>
4122 Gets the property name.
4123 </summary>
4124 <value>The property name.</value>
4125 </member>
4126 <member name="P:Newtonsoft.Json.Linq.JProperty.Value">
4127 <summary>
4128 Gets or sets the property value.
4129 </summary>
4130 <value>The property value.</value>
4131 </member>
4132 <member name="P:Newtonsoft.Json.Linq.JProperty.Type">
4133 <summary>
4134 Gets the node type for this <see cref="T:Newtonsoft.Json.Linq.JToken"/>.
4135 </summary>
4136 <value>The type.</value>
4137 </member>
4138 <member name="T:Newtonsoft.Json.Linq.JTokenType">
4139 <summary>
4140 Specifies the type of token.
4141 </summary>
4142 </member>
4143 <member name="F:Newtonsoft.Json.Linq.JTokenType.None">
4144 <summary>
4145 No token type has been set.
4146 </summary>
4147 </member>
4148 <member name="F:Newtonsoft.Json.Linq.JTokenType.Object">
4149 <summary>
4150 A JSON object.
4151 </summary>
4152 </member>
4153 <member name="F:Newtonsoft.Json.Linq.JTokenType.Array">
4154 <summary>
4155 A JSON array.
4156 </summary>
4157 </member>
4158 <member name="F:Newtonsoft.Json.Linq.JTokenType.Constructor">
4159 <summary>
4160 A JSON constructor.
4161 </summary>
4162 </member>
4163 <member name="F:Newtonsoft.Json.Linq.JTokenType.Property">
4164 <summary>
4165 A JSON object property.
4166 </summary>
4167 </member>
4168 <member name="F:Newtonsoft.Json.Linq.JTokenType.Comment">
4169 <summary>
4170 A comment.
4171 </summary>
4172 </member>
4173 <member name="F:Newtonsoft.Json.Linq.JTokenType.Integer">
4174 <summary>
4175 An integer value.
4176 </summary>
4177 </member>
4178 <member name="F:Newtonsoft.Json.Linq.JTokenType.Float">
4179 <summary>
4180 A float value.
4181 </summary>
4182 </member>
4183 <member name="F:Newtonsoft.Json.Linq.JTokenType.String">
4184 <summary>
4185 A string value.
4186 </summary>
4187 </member>
4188 <member name="F:Newtonsoft.Json.Linq.JTokenType.Boolean">
4189 <summary>
4190 A boolean value.
4191 </summary>
4192 </member>
4193 <member name="F:Newtonsoft.Json.Linq.JTokenType.Null">
4194 <summary>
4195 A null value.
4196 </summary>
4197 </member>
4198 <member name="F:Newtonsoft.Json.Linq.JTokenType.Undefined">
4199 <summary>
4200 An undefined value.
4201 </summary>
4202 </member>
4203 <member name="F:Newtonsoft.Json.Linq.JTokenType.Date">
4204 <summary>
4205 A date value.
4206 </summary>
4207 </member>
4208 <member name="F:Newtonsoft.Json.Linq.JTokenType.Raw">
4209 <summary>
4210 A raw JSON value.
4211 </summary>
4212 </member>
4213 <member name="F:Newtonsoft.Json.Linq.JTokenType.Bytes">
4214 <summary>
4215 A collection of bytes value.
4216 </summary>
4217 </member>
4218 <member name="T:Newtonsoft.Json.Schema.Extensions">
4219 <summary>
4220 Contains the JSON schema extension methods.
4221 </summary>
4222 </member>
4223 <member name="M:Newtonsoft.Json.Schema.Extensions.IsValid(Newtonsoft.Json.Linq.JToken,Newtonsoft.Json.Schema.JsonSchema)">
4224 <summary>
4225 Determines whether the <see cref="T:Newtonsoft.Json.Linq.JToken"/> is valid.
4226 </summary>
4227 <param name="source">The source <see cref="T:Newtonsoft.Json.Linq.JToken"/> to test.</param>
4228 <param name="schema">The schema to test with.</param>
4229 <returns>
4230 <c>true</c> if the specified <see cref="T:Newtonsoft.Json.Linq.JToken"/> is valid; otherwise, <c>false</c>.
4231 </returns>
4232 </member>
4233 <member name="M:Newtonsoft.Json.Schema.Extensions.Validate(Newtonsoft.Json.Linq.JToken,Newtonsoft.Json.Schema.JsonSchema)">
4234 <summary>
4235 Validates the specified <see cref="T:Newtonsoft.Json.Linq.JToken"/>.
4236 </summary>
4237 <param name="source">The source <see cref="T:Newtonsoft.Json.Linq.JToken"/> to test.</param>
4238 <param name="schema">The schema to test with.</param>
4239 </member>
4240 <member name="M:Newtonsoft.Json.Schema.Extensions.Validate(Newtonsoft.Json.Linq.JToken,Newtonsoft.Json.Schema.JsonSchema,Newtonsoft.Json.Schema.ValidationEventHandler)">
4241 <summary>
4242 Validates the specified <see cref="T:Newtonsoft.Json.Linq.JToken"/>.
4243 </summary>
4244 <param name="source">The source <see cref="T:Newtonsoft.Json.Linq.JToken"/> to test.</param>
4245 <param name="schema">The schema to test with.</param>
4246 <param name="validationEventHandler">The validation event handler.</param>
4247 </member>
4248 <member name="T:Newtonsoft.Json.Schema.JsonSchemaException">
4249 <summary>
4250 Returns detailed information about the schema exception.
4251 </summary>
4252 </member>
4253 <member name="M:Newtonsoft.Json.Schema.JsonSchemaException.#ctor">
4254 <summary>
4255 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Schema.JsonSchemaException"/> class.
4256 </summary>
4257 </member>
4258 <member name="M:Newtonsoft.Json.Schema.JsonSchemaException.#ctor(System.String)">
4259 <summary>
4260 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Schema.JsonSchemaException"/> class
4261 with a specified error message.
4262 </summary>
4263 <param name="message">The error message that explains the reason for the exception.</param>
4264 </member>
4265 <member name="M:Newtonsoft.Json.Schema.JsonSchemaException.#ctor(System.String,System.Exception)">
4266 <summary>
4267 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Schema.JsonSchemaException"/> class
4268 with a specified error message and a reference to the inner exception that is the cause of this exception.
4269 </summary>
4270 <param name="message">The error message that explains the reason for the exception.</param>
4271 <param name="innerException">The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.</param>
4272 </member>
4273 <member name="P:Newtonsoft.Json.Schema.JsonSchemaException.LineNumber">
4274 <summary>
4275 Gets the line number indicating where the error occurred.
4276 </summary>
4277 <value>The line number indicating where the error occurred.</value>
4278 </member>
4279 <member name="P:Newtonsoft.Json.Schema.JsonSchemaException.LinePosition">
4280 <summary>
4281 Gets the line position indicating where the error occurred.
4282 </summary>
4283 <value>The line position indicating where the error occurred.</value>
4284 </member>
4285 <member name="T:Newtonsoft.Json.Schema.JsonSchemaResolver">
4286 <summary>
4287 Resolves <see cref="T:Newtonsoft.Json.Schema.JsonSchema"/> from an id.
4288 </summary>
4289 </member>
4290 <member name="M:Newtonsoft.Json.Schema.JsonSchemaResolver.#ctor">
4291 <summary>
4292 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Schema.JsonSchemaResolver"/> class.
4293 </summary>
4294 </member>
4295 <member name="M:Newtonsoft.Json.Schema.JsonSchemaResolver.GetSchema(System.String)">
4296 <summary>
4297 Gets a <see cref="T:Newtonsoft.Json.Schema.JsonSchema"/> for the specified id.
4298 </summary>
4299 <param name="id">The id.</param>
4300 <returns>A <see cref="T:Newtonsoft.Json.Schema.JsonSchema"/> for the specified id.</returns>
4301 </member>
4302 <member name="P:Newtonsoft.Json.Schema.JsonSchemaResolver.LoadedSchemas">
4303 <summary>
4304 Gets or sets the loaded schemas.
4305 </summary>
4306 <value>The loaded schemas.</value>
4307 </member>
4308 <member name="T:Newtonsoft.Json.Schema.UndefinedSchemaIdHandling">
4309 <summary>
4310 Specifies undefined schema Id handling options for the <see cref="T:Newtonsoft.Json.Schema.JsonSchemaGenerator"/>.
4311 </summary>
4312 </member>
4313 <member name="F:Newtonsoft.Json.Schema.UndefinedSchemaIdHandling.None">
4314 <summary>
4315 Do not infer a schema Id.
4316 </summary>
4317 </member>
4318 <member name="F:Newtonsoft.Json.Schema.UndefinedSchemaIdHandling.UseTypeName">
4319 <summary>
4320 Use the .NET type name as the schema Id.
4321 </summary>
4322 </member>
4323 <member name="F:Newtonsoft.Json.Schema.UndefinedSchemaIdHandling.UseAssemblyQualifiedName">
4324 <summary>
4325 Use the assembly qualified .NET type name as the schema Id.
4326 </summary>
4327 </member>
4328 <member name="T:Newtonsoft.Json.Schema.ValidationEventArgs">
4329 <summary>
4330 Returns detailed information related to the <see cref="T:Newtonsoft.Json.Schema.ValidationEventHandler"/>.
4331 </summary>
4332 </member>
4333 <member name="P:Newtonsoft.Json.Schema.ValidationEventArgs.Exception">
4334 <summary>
4335 Gets the <see cref="T:Newtonsoft.Json.Schema.JsonSchemaException"/> associated with the validation event.
4336 </summary>
4337 <value>The JsonSchemaException associated with the validation event.</value>
4338 </member>
4339 <member name="P:Newtonsoft.Json.Schema.ValidationEventArgs.Message">
4340 <summary>
4341 Gets the text description corresponding to the validation event.
4342 </summary>
4343 <value>The text description.</value>
4344 </member>
4345 <member name="T:Newtonsoft.Json.Schema.ValidationEventHandler">
4346 <summary>
4347 Represents the callback method that will handle JSON schema validation events and the <see cref="T:Newtonsoft.Json.Schema.ValidationEventArgs"/>.
4348 </summary>
4349 </member>
4350 <member name="T:Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver">
4351 <summary>
4352 Resolves member mappings for a type, camel casing property names.
4353 </summary>
4354 </member>
4355 <member name="T:Newtonsoft.Json.Serialization.DefaultContractResolver">
4356 <summary>
4357 Used by <see cref="T:Newtonsoft.Json.JsonSerializer"/> to resolves a <see cref="T:Newtonsoft.Json.Serialization.JsonContract"/> for a given <see cref="T:System.Type"/>.
4358 </summary>
4359 </member>
4360 <member name="T:Newtonsoft.Json.Serialization.IContractResolver">
4361 <summary>
4362 Used by <see cref="T:Newtonsoft.Json.JsonSerializer"/> to resolves a <see cref="T:Newtonsoft.Json.Serialization.JsonContract"/> for a given <see cref="T:System.Type"/>.
4363 </summary>
4364 </member>
4365 <member name="M:Newtonsoft.Json.Serialization.IContractResolver.ResolveContract(System.Type)">
4366 <summary>
4367 Resolves the contract for a given type.
4368 </summary>
4369 <param name="type">The type to resolve a contract for.</param>
4370 <returns>The contract for a given type.</returns>
4371 </member>
4372 <member name="M:Newtonsoft.Json.Serialization.DefaultContractResolver.#ctor">
4373 <summary>
4374 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Serialization.DefaultContractResolver"/> class.
4375 </summary>
4376 </member>
4377 <member name="M:Newtonsoft.Json.Serialization.DefaultContractResolver.ResolveContract(System.Type)">
4378 <summary>
4379 Resolves the contract for a given type.
4380 </summary>
4381 <param name="type">The type to resolve a contract for.</param>
4382 <returns>The contract for a given type.</returns>
4383 </member>
4384 <member name="M:Newtonsoft.Json.Serialization.DefaultContractResolver.GetSerializableMembers(System.Type)">
4385 <summary>
4386 Gets the serializable members for the type.
4387 </summary>
4388 <param name="objectType">The type to get serializable members for.</param>
4389 <returns>The serializable members for the type.</returns>
4390 </member>
4391 <member name="M:Newtonsoft.Json.Serialization.DefaultContractResolver.CreateObjectContract(System.Type)">
4392 <summary>
4393 Creates a <see cref="T:Newtonsoft.Json.Serialization.JsonObjectContract"/> for the given type.
4394 </summary>
4395 <param name="objectType">Type of the object.</param>
4396 <returns>A <see cref="T:Newtonsoft.Json.Serialization.JsonObjectContract"/> for the given type.</returns>
4397 </member>
4398 <member name="M:Newtonsoft.Json.Serialization.DefaultContractResolver.ResolveContractConverter(System.Type)">
4399 <summary>
4400 Resolves the default <see cref="T:Newtonsoft.Json.JsonConverter"/> for the contract.
4401 </summary>
4402 <param name="objectType">Type of the object.</param>
4403 <returns></returns>
4404 </member>
4405 <member name="M:Newtonsoft.Json.Serialization.DefaultContractResolver.CreateDictionaryContract(System.Type)">
4406 <summary>
4407 Creates a <see cref="T:Newtonsoft.Json.Serialization.JsonDictionaryContract"/> for the given type.
4408 </summary>
4409 <param name="objectType">Type of the object.</param>
4410 <returns>A <see cref="T:Newtonsoft.Json.Serialization.JsonDictionaryContract"/> for the given type.</returns>
4411 </member>
4412 <member name="M:Newtonsoft.Json.Serialization.DefaultContractResolver.CreateArrayContract(System.Type)">
4413 <summary>
4414 Creates a <see cref="T:Newtonsoft.Json.Serialization.JsonArrayContract"/> for the given type.
4415 </summary>
4416 <param name="objectType">Type of the object.</param>
4417 <returns>A <see cref="T:Newtonsoft.Json.Serialization.JsonArrayContract"/> for the given type.</returns>
4418 </member>
4419 <member name="M:Newtonsoft.Json.Serialization.DefaultContractResolver.CreatePrimitiveContract(System.Type)">
4420 <summary>
4421 Creates a <see cref="T:Newtonsoft.Json.Serialization.JsonPrimitiveContract"/> for the given type.
4422 </summary>
4423 <param name="objectType">Type of the object.</param>
4424 <returns>A <see cref="T:Newtonsoft.Json.Serialization.JsonPrimitiveContract"/> for the given type.</returns>
4425 </member>
4426 <member name="M:Newtonsoft.Json.Serialization.DefaultContractResolver.CreateLinqContract(System.Type)">
4427 <summary>
4428 Creates a <see cref="T:Newtonsoft.Json.Serialization.JsonLinqContract"/> for the given type.
4429 </summary>
4430 <param name="objectType">Type of the object.</param>
4431 <returns>A <see cref="T:Newtonsoft.Json.Serialization.JsonLinqContract"/> for the given type.</returns>
4432 </member>
4433 <member name="M:Newtonsoft.Json.Serialization.DefaultContractResolver.CreateProperties(Newtonsoft.Json.Serialization.JsonObjectContract)">
4434 <summary>
4435 Creates properties for the given <see cref="T:Newtonsoft.Json.Serialization.JsonObjectContract"/>.
4436 </summary>
4437 <param name="contract">The contract to create properties for.</param>
4438 <returns>Properties for the given <see cref="T:Newtonsoft.Json.Serialization.JsonObjectContract"/>.</returns>
4439 </member>
4440 <member name="M:Newtonsoft.Json.Serialization.DefaultContractResolver.CreateMemberValueProvider(System.Reflection.MemberInfo)">
4441 <summary>
4442 Creates the <see cref="T:Newtonsoft.Json.Serialization.IValueProvider"/> used by the serializer to get and set values from a member.
4443 </summary>
4444 <param name="member">The member.</param>
4445 <returns>The <see cref="T:Newtonsoft.Json.Serialization.IValueProvider"/> used by the serializer to get and set values from a member.</returns>
4446 </member>
4447 <member name="M:Newtonsoft.Json.Serialization.DefaultContractResolver.CreateProperty(Newtonsoft.Json.Serialization.JsonObjectContract,System.Reflection.MemberInfo)">
4448 <summary>
4449 Creates a <see cref="T:Newtonsoft.Json.Serialization.JsonProperty"/> for the given <see cref="T:System.Reflection.MemberInfo"/>.
4450 </summary>
4451 <param name="contract">The member's declaring types <see cref="T:Newtonsoft.Json.Serialization.JsonObjectContract"/>.</param>
4452 <param name="member">The member to create a <see cref="T:Newtonsoft.Json.Serialization.JsonProperty"/> for.</param>
4453 <returns>A created <see cref="T:Newtonsoft.Json.Serialization.JsonProperty"/> for the given <see cref="T:System.Reflection.MemberInfo"/>.</returns>
4454 </member>
4455 <member name="M:Newtonsoft.Json.Serialization.DefaultContractResolver.ResolvePropertyName(System.String)">
4456 <summary>
4457 Resolves the name of the property.
4458 </summary>
4459 <param name="propertyName">Name of the property.</param>
4460 <returns>Name of the property.</returns>
4461 </member>
4462 <member name="P:Newtonsoft.Json.Serialization.DefaultContractResolver.DefaultMembersSearchFlags">
4463 <summary>
4464 Gets or sets the default members search flags.
4465 </summary>
4466 <value>The default members search flags.</value>
4467 </member>
4468 <member name="M:Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver.ResolvePropertyName(System.String)">
4469 <summary>
4470 Resolves the name of the property.
4471 </summary>
4472 <param name="propertyName">Name of the property.</param>
4473 <returns>The property name camel cased.</returns>
4474 </member>
4475 <member name="T:Newtonsoft.Json.Serialization.DefaultSerializationBinder">
4476 <summary>
4477 The default serialization binder used when resolving and loading classes from type names.
4478 </summary>
4479 </member>
4480 <member name="M:Newtonsoft.Json.Serialization.DefaultSerializationBinder.BindToType(System.String,System.String)">
4481 <summary>
4482 When overridden in a derived class, controls the binding of a serialized object to a type.
4483 </summary>
4484 <param name="assemblyName">Specifies the <see cref="T:System.Reflection.Assembly"/> name of the serialized object.</param>
4485 <param name="typeName">Specifies the <see cref="T:System.Type"/> name of the serialized object.</param>
4486 <returns>
4487 The type of the object the formatter creates a new instance of.
4488 </returns>
4489 </member>
4490 <member name="T:Newtonsoft.Json.Serialization.DynamicValueProvider">
4491 <summary>
4492 Get and set values for a <see cref="T:System.Reflection.MemberInfo"/> using dynamic methods.
4493 </summary>
4494 </member>
4495 <member name="T:Newtonsoft.Json.Serialization.IValueProvider">
4496 <summary>
4497 Provides methods to get and set values.
4498 </summary>
4499 </member>
4500 <member name="M:Newtonsoft.Json.Serialization.IValueProvider.SetValue(System.Object,System.Object)">
4501 <summary>
4502 Sets the value.
4503 </summary>
4504 <param name="target">The target to set the value on.</param>
4505 <param name="value">The value to set on the target.</param>
4506 </member>
4507 <member name="M:Newtonsoft.Json.Serialization.IValueProvider.GetValue(System.Object)">
4508 <summary>
4509 Gets the value.
4510 </summary>
4511 <param name="target">The target to get the value from.</param>
4512 <returns>The value.</returns>
4513 </member>
4514 <member name="M:Newtonsoft.Json.Serialization.DynamicValueProvider.#ctor(System.Reflection.MemberInfo)">
4515 <summary>
4516 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Serialization.DynamicValueProvider"/> class.
4517 </summary>
4518 <param name="memberInfo">The member info.</param>
4519 </member>
4520 <member name="M:Newtonsoft.Json.Serialization.DynamicValueProvider.SetValue(System.Object,System.Object)">
4521 <summary>
4522 Sets the value.
4523 </summary>
4524 <param name="target">The target to set the value on.</param>
4525 <param name="value">The value to set on the target.</param>
4526 </member>
4527 <member name="M:Newtonsoft.Json.Serialization.DynamicValueProvider.GetValue(System.Object)">
4528 <summary>
4529 Gets the value.
4530 </summary>
4531 <param name="target">The target to get the value from.</param>
4532 <returns>The value.</returns>
4533 </member>
4534 <member name="T:Newtonsoft.Json.Serialization.ErrorContext">
4535 <summary>
4536 Provides information surrounding an error.
4537 </summary>
4538 </member>
4539 <member name="P:Newtonsoft.Json.Serialization.ErrorContext.Error">
4540 <summary>
4541 Gets or sets the error.
4542 </summary>
4543 <value>The error.</value>
4544 </member>
4545 <member name="P:Newtonsoft.Json.Serialization.ErrorContext.OriginalObject">
4546 <summary>
4547 Gets the original object that caused the error.
4548 </summary>
4549 <value>The original object that caused the error.</value>
4550 </member>
4551 <member name="P:Newtonsoft.Json.Serialization.ErrorContext.Member">
4552 <summary>
4553 Gets the member that caused the error.
4554 </summary>
4555 <value>The member that caused the error.</value>
4556 </member>
4557 <member name="P:Newtonsoft.Json.Serialization.ErrorContext.Handled">
4558 <summary>
4559 Gets or sets a value indicating whether this <see cref="T:Newtonsoft.Json.Serialization.ErrorContext"/> is handled.
4560 </summary>
4561 <value><c>true</c> if handled; otherwise, <c>false</c>.</value>
4562 </member>
4563 <member name="T:Newtonsoft.Json.Serialization.ErrorEventArgs">
4564 <summary>
4565 Provides data for the Error event.
4566 </summary>
4567 </member>
4568 <member name="M:Newtonsoft.Json.Serialization.ErrorEventArgs.#ctor(System.Object,Newtonsoft.Json.Serialization.ErrorContext)">
4569 <summary>
4570 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Serialization.ErrorEventArgs"/> class.
4571 </summary>
4572 <param name="currentObject">The current object.</param>
4573 <param name="errorContext">The error context.</param>
4574 </member>
4575 <member name="P:Newtonsoft.Json.Serialization.ErrorEventArgs.CurrentObject">
4576 <summary>
4577 Gets the current object the error event is being raised against.
4578 </summary>
4579 <value>The current object the error event is being raised against.</value>
4580 </member>
4581 <member name="P:Newtonsoft.Json.Serialization.ErrorEventArgs.ErrorContext">
4582 <summary>
4583 Gets the error context.
4584 </summary>
4585 <value>The error context.</value>
4586 </member>
4587 <member name="T:Newtonsoft.Json.Serialization.JsonArrayContract">
4588 <summary>
4589 Contract details for a <see cref="T:System.Type"/> used by the <see cref="T:Newtonsoft.Json.JsonSerializer"/>.
4590 </summary>
4591 </member>
4592 <member name="T:Newtonsoft.Json.Serialization.JsonContract">
4593 <summary>
4594 Contract details for a <see cref="T:System.Type"/> used by the <see cref="T:Newtonsoft.Json.JsonSerializer"/>.
4595 </summary>
4596 </member>
4597 <member name="P:Newtonsoft.Json.Serialization.JsonContract.UnderlyingType">
4598 <summary>
4599 Gets the underlying type for the contract.
4600 </summary>
4601 <value>The underlying type for the contract.</value>
4602 </member>
4603 <member name="P:Newtonsoft.Json.Serialization.JsonContract.CreatedType">
4604 <summary>
4605 Gets or sets the type created during deserialization.
4606 </summary>
4607 <value>The type created during deserialization.</value>
4608 </member>
4609 <member name="P:Newtonsoft.Json.Serialization.JsonContract.IsReference">
4610 <summary>
4611 Gets or sets whether this type contract is serialized as a reference.
4612 </summary>
4613 <value>Whether this type contract is serialized as a reference.</value>
4614 </member>
4615 <member name="P:Newtonsoft.Json.Serialization.JsonContract.Converter">
4616 <summary>
4617 Gets or sets the default <see cref="T:Newtonsoft.Json.JsonConverter"/> for this contract.
4618 </summary>
4619 <value>The converter.</value>
4620 </member>
4621 <member name="P:Newtonsoft.Json.Serialization.JsonContract.OnDeserialized">
4622 <summary>
4623 Gets or sets the method called immediately after deserialization of the object.
4624 </summary>
4625 <value>The method called immediately after deserialization of the object.</value>
4626 </member>
4627 <member name="P:Newtonsoft.Json.Serialization.JsonContract.OnDeserializing">
4628 <summary>
4629 Gets or sets the method called during deserialization of the object.
4630 </summary>
4631 <value>The method called during deserialization of the object.</value>
4632 </member>
4633 <member name="P:Newtonsoft.Json.Serialization.JsonContract.OnSerialized">
4634 <summary>
4635 Gets or sets the method called after serialization of the object graph.
4636 </summary>
4637 <value>The method called after serialization of the object graph.</value>
4638 </member>
4639 <member name="P:Newtonsoft.Json.Serialization.JsonContract.OnSerializing">
4640 <summary>
4641 Gets or sets the method called before serialization of the object.
4642 </summary>
4643 <value>The method called before serialization of the object.</value>
4644 </member>
4645 <member name="P:Newtonsoft.Json.Serialization.JsonContract.DefaultCreator">
4646 <summary>
4647 Gets or sets the default creator.
4648 </summary>
4649 <value>The default creator.</value>
4650 </member>
4651 <member name="P:Newtonsoft.Json.Serialization.JsonContract.DefaultCreatorNonPublic">
4652 <summary>
4653 Gets or sets a value indicating whether [default creator non public].
4654 </summary>
4655 <value><c>true</c> if the default object creator is non-public; otherwise, <c>false</c>.</value>
4656 </member>
4657 <member name="P:Newtonsoft.Json.Serialization.JsonContract.OnError">
4658 <summary>
4659 Gets or sets the method called when an error is thrown during the serialization of the object.
4660 </summary>
4661 <value>The method called when an error is thrown during the serialization of the object.</value>
4662 </member>
4663 <member name="M:Newtonsoft.Json.Serialization.JsonArrayContract.#ctor(System.Type)">
4664 <summary>
4665 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Serialization.JsonArrayContract"/> class.
4666 </summary>
4667 <param name="underlyingType">The underlying type for the contract.</param>
4668 </member>
4669 <member name="T:Newtonsoft.Json.Serialization.JsonDictionaryContract">
4670 <summary>
4671 Contract details for a <see cref="T:System.Type"/> used by the <see cref="T:Newtonsoft.Json.JsonSerializer"/>.
4672 </summary>
4673 </member>
4674 <member name="M:Newtonsoft.Json.Serialization.JsonDictionaryContract.#ctor(System.Type)">
4675 <summary>
4676 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Serialization.JsonDictionaryContract"/> class.
4677 </summary>
4678 <param name="underlyingType">The underlying type for the contract.</param>
4679 </member>
4680 <member name="T:Newtonsoft.Json.Serialization.JsonLinqContract">
4681 <summary>
4682 Contract details for a <see cref="T:System.Type"/> used by the <see cref="T:Newtonsoft.Json.JsonSerializer"/>.
4683 </summary>
4684 </member>
4685 <member name="M:Newtonsoft.Json.Serialization.JsonLinqContract.#ctor(System.Type)">
4686 <summary>
4687 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Serialization.JsonLinqContract"/> class.
4688 </summary>
4689 <param name="underlyingType">The underlying type for the contract.</param>
4690 </member>
4691 <member name="T:Newtonsoft.Json.Serialization.JsonPrimitiveContract">
4692 <summary>
4693 Contract details for a <see cref="T:System.Type"/> used by the <see cref="T:Newtonsoft.Json.JsonSerializer"/>.
4694 </summary>
4695 </member>
4696 <member name="M:Newtonsoft.Json.Serialization.JsonPrimitiveContract.#ctor(System.Type)">
4697 <summary>
4698 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Serialization.JsonPrimitiveContract"/> class.
4699 </summary>
4700 <param name="underlyingType">The underlying type for the contract.</param>
4701 </member>
4702 <member name="T:Newtonsoft.Json.Serialization.JsonProperty">
4703 <summary>
4704 Maps a JSON property to a .NET member.
4705 </summary>
4706 </member>
4707 <member name="P:Newtonsoft.Json.Serialization.JsonProperty.PropertyName">
4708 <summary>
4709 Gets the name of the property.
4710 </summary>
4711 <value>The name of the property.</value>
4712 </member>
4713 <member name="P:Newtonsoft.Json.Serialization.JsonProperty.ValueProvider">
4714 <summary>
4715 Gets the <see cref="T:Newtonsoft.Json.Serialization.IValueProvider"/> that will get and set the <see cref="T:Newtonsoft.Json.Serialization.JsonProperty"/> during serialization.
4716 </summary>
4717 <value>The <see cref="T:Newtonsoft.Json.Serialization.IValueProvider"/> that will get and set the <see cref="T:Newtonsoft.Json.Serialization.JsonProperty"/> during serialization.</value>
4718 </member>
4719 <member name="P:Newtonsoft.Json.Serialization.JsonProperty.PropertyType">
4720 <summary>
4721 Gets or sets the type of the property.
4722 </summary>
4723 <value>The type of the property.</value>
4724 </member>
4725 <member name="P:Newtonsoft.Json.Serialization.JsonProperty.Converter">
4726 <summary>
4727 Gets or sets the <see cref="T:Newtonsoft.Json.JsonConverter"/> for the property.
4728 If set this converter takes presidence over the contract converter for the property type.
4729 </summary>
4730 <value>The converter.</value>
4731 </member>
4732 <member name="P:Newtonsoft.Json.Serialization.JsonProperty.Ignored">
4733 <summary>
4734 Gets a value indicating whether this <see cref="T:Newtonsoft.Json.Serialization.JsonProperty"/> is ignored.
4735 </summary>
4736 <value><c>true</c> if ignored; otherwise, <c>false</c>.</value>
4737 </member>
4738 <member name="P:Newtonsoft.Json.Serialization.JsonProperty.Readable">
4739 <summary>
4740 Gets a value indicating whether this <see cref="T:Newtonsoft.Json.Serialization.JsonProperty"/> is readable.
4741 </summary>
4742 <value><c>true</c> if readable; otherwise, <c>false</c>.</value>
4743 </member>
4744 <member name="P:Newtonsoft.Json.Serialization.JsonProperty.Writable">
4745 <summary>
4746 Gets a value indicating whether this <see cref="T:Newtonsoft.Json.Serialization.JsonProperty"/> is writable.
4747 </summary>
4748 <value><c>true</c> if writable; otherwise, <c>false</c>.</value>
4749 </member>
4750 <member name="P:Newtonsoft.Json.Serialization.JsonProperty.MemberConverter">
4751 <summary>
4752 Gets the member converter.
4753 </summary>
4754 <value>The member converter.</value>
4755 </member>
4756 <member name="P:Newtonsoft.Json.Serialization.JsonProperty.DefaultValue">
4757 <summary>
4758 Gets the default value.
4759 </summary>
4760 <value>The default value.</value>
4761 </member>
4762 <member name="P:Newtonsoft.Json.Serialization.JsonProperty.Required">
4763 <summary>
4764 Gets a value indicating whether this <see cref="T:Newtonsoft.Json.Serialization.JsonProperty"/> is required.
4765 </summary>
4766 <value>A value indicating whether this <see cref="T:Newtonsoft.Json.Serialization.JsonProperty"/> is required.</value>
4767 </member>
4768 <member name="P:Newtonsoft.Json.Serialization.JsonProperty.IsReference">
4769 <summary>
4770 Gets a value indicating whether this property preserves object references.
4771 </summary>
4772 <value>
4773 <c>true</c> if this instance is reference; otherwise, <c>false</c>.
4774 </value>
4775 </member>
4776 <member name="P:Newtonsoft.Json.Serialization.JsonProperty.NullValueHandling">
4777 <summary>
4778 Gets the property null value handling.
4779 </summary>
4780 <value>The null value handling.</value>
4781 </member>
4782 <member name="P:Newtonsoft.Json.Serialization.JsonProperty.DefaultValueHandling">
4783 <summary>
4784 Gets the property default value handling.
4785 </summary>
4786 <value>The default value handling.</value>
4787 </member>
4788 <member name="P:Newtonsoft.Json.Serialization.JsonProperty.ReferenceLoopHandling">
4789 <summary>
4790 Gets the property reference loop handling.
4791 </summary>
4792 <value>The reference loop handling.</value>
4793 </member>
4794 <member name="P:Newtonsoft.Json.Serialization.JsonProperty.ObjectCreationHandling">
4795 <summary>
4796 Gets the property object creation handling.
4797 </summary>
4798 <value>The object creation handling.</value>
4799 </member>
4800 <member name="T:Newtonsoft.Json.Serialization.JsonPropertyCollection">
4801 <summary>
4802 A collection of <see cref="T:Newtonsoft.Json.Serialization.JsonProperty"/> objects.
4803 </summary>
4804 </member>
4805 <member name="M:Newtonsoft.Json.Serialization.JsonPropertyCollection.#ctor(Newtonsoft.Json.Serialization.JsonObjectContract)">
4806 <summary>
4807 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Serialization.JsonPropertyCollection"/> class.
4808 </summary>
4809 <param name="contract">The contract.</param>
4810 </member>
4811 <member name="M:Newtonsoft.Json.Serialization.JsonPropertyCollection.GetKeyForItem(Newtonsoft.Json.Serialization.JsonProperty)">
4812 <summary>
4813 When implemented in a derived class, extracts the key from the specified element.
4814 </summary>
4815 <param name="item">The element from which to extract the key.</param>
4816 <returns>The key for the specified element.</returns>
4817 </member>
4818 <member name="M:Newtonsoft.Json.Serialization.JsonPropertyCollection.AddProperty(Newtonsoft.Json.Serialization.JsonProperty)">
4819 <summary>
4820 Adds a <see cref="T:Newtonsoft.Json.Serialization.JsonProperty"/> object.
4821 </summary>
4822 <param name="property">The property to add to the collection.</param>
4823 </member>
4824 <member name="M:Newtonsoft.Json.Serialization.JsonPropertyCollection.GetClosestMatchProperty(System.String)">
4825 <summary>
4826 Gets the closest matching <see cref="T:Newtonsoft.Json.Serialization.JsonProperty"/> object.
4827 First attempts to get an exact case match of propertyName and then
4828 a case insensitive match.
4829 </summary>
4830 <param name="propertyName">Name of the property.</param>
4831 <returns>A matching property if found.</returns>
4832 </member>
4833 <member name="M:Newtonsoft.Json.Serialization.JsonPropertyCollection.GetProperty(System.String,System.StringComparison)">
4834 <summary>
4835 Gets a property by property name.
4836 </summary>
4837 <param name="propertyName">The name of the property to get.</param>
4838 <param name="comparisonType">Type property name string comparison.</param>
4839 <returns>A matching property if found.</returns>
4840 </member>
4841 <member name="T:Newtonsoft.Json.MissingMemberHandling">
4842 <summary>
4843 Specifies missing member handling options for the <see cref="T:Newtonsoft.Json.JsonSerializer"/>.
4844 </summary>
4845 </member>
4846 <member name="F:Newtonsoft.Json.MissingMemberHandling.Ignore">
4847 <summary>
4848 Ignore a missing member and do not attempt to deserialize it.
4849 </summary>
4850 </member>
4851 <member name="F:Newtonsoft.Json.MissingMemberHandling.Error">
4852 <summary>
4853 Throw a <see cref="T:Newtonsoft.Json.JsonSerializationException"/> when a missing member is encountered during deserialization.
4854 </summary>
4855 </member>
4856 <member name="T:Newtonsoft.Json.NullValueHandling">
4857 <summary>
4858 Specifies null value handling options for the <see cref="T:Newtonsoft.Json.JsonSerializer"/>.
4859 </summary>
4860 </member>
4861 <member name="F:Newtonsoft.Json.NullValueHandling.Include">
4862 <summary>
4863 Include null values when serializing and deserializing objects.
4864 </summary>
4865 </member>
4866 <member name="F:Newtonsoft.Json.NullValueHandling.Ignore">
4867 <summary>
4868 Ignore null values when serializing and deserializing objects.
4869 </summary>
4870 </member>
4871 <member name="T:Newtonsoft.Json.ReferenceLoopHandling">
4872 <summary>
4873 Specifies reference loop handling options for the <see cref="T:Newtonsoft.Json.JsonSerializer"/>.
4874 </summary>
4875 </member>
4876 <member name="F:Newtonsoft.Json.ReferenceLoopHandling.Error">
4877 <summary>
4878 Throw a <see cref="T:Newtonsoft.Json.JsonSerializationException"/> when a loop is encountered.
4879 </summary>
4880 </member>
4881 <member name="F:Newtonsoft.Json.ReferenceLoopHandling.Ignore">
4882 <summary>
4883 Ignore loop references and do not serialize.
4884 </summary>
4885 </member>
4886 <member name="F:Newtonsoft.Json.ReferenceLoopHandling.Serialize">
4887 <summary>
4888 Serialize loop references.
4889 </summary>
4890 </member>
4891 <member name="T:Newtonsoft.Json.Schema.JsonSchema">
4892 <summary>
4893 An in-memory representation of a JSON Schema.
4894 </summary>
4895 </member>
4896 <member name="M:Newtonsoft.Json.Schema.JsonSchema.#ctor">
4897 <summary>
4898 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Schema.JsonSchema"/> class.
4899 </summary>
4900 </member>
4901 <member name="M:Newtonsoft.Json.Schema.JsonSchema.Read(Newtonsoft.Json.JsonReader)">
4902 <summary>
4903 Reads a <see cref="T:Newtonsoft.Json.Schema.JsonSchema"/> from the specified <see cref="T:Newtonsoft.Json.JsonReader"/>.
4904 </summary>
4905 <param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader"/> containing the JSON Schema to read.</param>
4906 <returns>The <see cref="T:Newtonsoft.Json.Schema.JsonSchema"/> object representing the JSON Schema.</returns>
4907 </member>
4908 <member name="M:Newtonsoft.Json.Schema.JsonSchema.Read(Newtonsoft.Json.JsonReader,Newtonsoft.Json.Schema.JsonSchemaResolver)">
4909 <summary>
4910 Reads a <see cref="T:Newtonsoft.Json.Schema.JsonSchema"/> from the specified <see cref="T:Newtonsoft.Json.JsonReader"/>.
4911 </summary>
4912 <param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader"/> containing the JSON Schema to read.</param>
4913 <param name="resolver">The <see cref="T:Newtonsoft.Json.Schema.JsonSchemaResolver"/> to use when resolving schema references.</param>
4914 <returns>The <see cref="T:Newtonsoft.Json.Schema.JsonSchema"/> object representing the JSON Schema.</returns>
4915 </member>
4916 <member name="M:Newtonsoft.Json.Schema.JsonSchema.Parse(System.String)">
4917 <summary>
4918 Load a <see cref="T:Newtonsoft.Json.Schema.JsonSchema"/> from a string that contains schema JSON.
4919 </summary>
4920 <param name="json">A <see cref="T:System.String"/> that contains JSON.</param>
4921 <returns>A <see cref="T:Newtonsoft.Json.Schema.JsonSchema"/> populated from the string that contains JSON.</returns>
4922 </member>
4923 <member name="M:Newtonsoft.Json.Schema.JsonSchema.Parse(System.String,Newtonsoft.Json.Schema.JsonSchemaResolver)">
4924 <summary>
4925 Parses the specified json.
4926 </summary>
4927 <param name="json">The json.</param>
4928 <param name="resolver">The resolver.</param>
4929 <returns>A <see cref="T:Newtonsoft.Json.Schema.JsonSchema"/> populated from the string that contains JSON.</returns>
4930 </member>
4931 <member name="M:Newtonsoft.Json.Schema.JsonSchema.WriteTo(Newtonsoft.Json.JsonWriter)">
4932 <summary>
4933 Writes this schema to a <see cref="T:Newtonsoft.Json.JsonWriter"/>.
4934 </summary>
4935 <param name="writer">A <see cref="T:Newtonsoft.Json.JsonWriter"/> into which this method will write.</param>
4936 </member>
4937 <member name="M:Newtonsoft.Json.Schema.JsonSchema.WriteTo(Newtonsoft.Json.JsonWriter,Newtonsoft.Json.Schema.JsonSchemaResolver)">
4938 <summary>
4939 Writes this schema to a <see cref="T:Newtonsoft.Json.JsonWriter"/> using the specified <see cref="T:Newtonsoft.Json.Schema.JsonSchemaResolver"/>.
4940 </summary>
4941 <param name="writer">A <see cref="T:Newtonsoft.Json.JsonWriter"/> into which this method will write.</param>
4942 <param name="resolver">The resolver used.</param>
4943 </member>
4944 <member name="M:Newtonsoft.Json.Schema.JsonSchema.ToString">
4945 <summary>
4946 Returns a <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
4947 </summary>
4948 <returns>
4949 A <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
4950 </returns>
4951 </member>
4952 <member name="P:Newtonsoft.Json.Schema.JsonSchema.Id">
4953 <summary>
4954 Gets or sets the id.
4955 </summary>
4956 </member>
4957 <member name="P:Newtonsoft.Json.Schema.JsonSchema.Title">
4958 <summary>
4959 Gets or sets the title.
4960 </summary>
4961 </member>
4962 <member name="P:Newtonsoft.Json.Schema.JsonSchema.Optional">
4963 <summary>
4964 Gets or sets whether the object is optional.
4965 </summary>
4966 </member>
4967 <member name="P:Newtonsoft.Json.Schema.JsonSchema.ReadOnly">
4968 <summary>
4969 Gets or sets whether the object is read only.
4970 </summary>
4971 </member>
4972 <member name="P:Newtonsoft.Json.Schema.JsonSchema.Hidden">
4973 <summary>
4974 Gets or sets whether the object is visible to users.
4975 </summary>
4976 </member>
4977 <member name="P:Newtonsoft.Json.Schema.JsonSchema.Transient">
4978 <summary>
4979 Gets or sets whether the object is transient.
4980 </summary>
4981 </member>
4982 <member name="P:Newtonsoft.Json.Schema.JsonSchema.Description">
4983 <summary>
4984 Gets or sets the description of the object.
4985 </summary>
4986 </member>
4987 <member name="P:Newtonsoft.Json.Schema.JsonSchema.Type">
4988 <summary>
4989 Gets or sets the types of values allowed by the object.
4990 </summary>
4991 <value>The type.</value>
4992 </member>
4993 <member name="P:Newtonsoft.Json.Schema.JsonSchema.Pattern">
4994 <summary>
4995 Gets or sets the pattern.
4996 </summary>
4997 <value>The pattern.</value>
4998 </member>
4999 <member name="P:Newtonsoft.Json.Schema.JsonSchema.MinimumLength">
5000 <summary>
5001 Gets or sets the minimum length.
5002 </summary>
5003 <value>The minimum length.</value>
5004 </member>
5005 <member name="P:Newtonsoft.Json.Schema.JsonSchema.MaximumLength">
5006 <summary>
5007 Gets or sets the maximum length.
5008 </summary>
5009 <value>The maximum length.</value>
5010 </member>
5011 <member name="P:Newtonsoft.Json.Schema.JsonSchema.MaximumDecimals">
5012 <summary>
5013 Gets or sets the maximum decimals.
5014 </summary>
5015 <value>The maximum decimals.</value>
5016 </member>
5017 <member name="P:Newtonsoft.Json.Schema.JsonSchema.Minimum">
5018 <summary>
5019 Gets or sets the minimum.
5020 </summary>
5021 <value>The minimum.</value>
5022 </member>
5023 <member name="P:Newtonsoft.Json.Schema.JsonSchema.Maximum">
5024 <summary>
5025 Gets or sets the maximum.
5026 </summary>
5027 <value>The maximum.</value>
5028 </member>
5029 <member name="P:Newtonsoft.Json.Schema.JsonSchema.MinimumItems">
5030 <summary>
5031 Gets or sets the minimum number of items.
5032 </summary>
5033 <value>The minimum number of items.</value>
5034 </member>
5035 <member name="P:Newtonsoft.Json.Schema.JsonSchema.MaximumItems">
5036 <summary>
5037 Gets or sets the maximum number of items.
5038 </summary>
5039 <value>The maximum number of items.</value>
5040 </member>
5041 <member name="P:Newtonsoft.Json.Schema.JsonSchema.Items">
5042 <summary>
5043 Gets or sets the <see cref="T:Newtonsoft.Json.Schema.JsonSchema"/> of items.
5044 </summary>
5045 <value>The <see cref="T:Newtonsoft.Json.Schema.JsonSchema"/> of items.</value>
5046 </member>
5047 <member name="P:Newtonsoft.Json.Schema.JsonSchema.Properties">
5048 <summary>
5049 Gets or sets the <see cref="T:Newtonsoft.Json.Schema.JsonSchema"/> of properties.
5050 </summary>
5051 <value>The <see cref="T:Newtonsoft.Json.Schema.JsonSchema"/> of properties.</value>
5052 </member>
5053 <member name="P:Newtonsoft.Json.Schema.JsonSchema.AdditionalProperties">
5054 <summary>
5055 Gets or sets the <see cref="T:Newtonsoft.Json.Schema.JsonSchema"/> of additional properties.
5056 </summary>
5057 <value>The <see cref="T:Newtonsoft.Json.Schema.JsonSchema"/> of additional properties.</value>
5058 </member>
5059 <member name="P:Newtonsoft.Json.Schema.JsonSchema.AllowAdditionalProperties">
5060 <summary>
5061 Gets or sets a value indicating whether additional properties are allowed.
5062 </summary>
5063 <value>
5064 <c>true</c> if additional properties are allowed; otherwise, <c>false</c>.
5065 </value>
5066 </member>
5067 <member name="P:Newtonsoft.Json.Schema.JsonSchema.Requires">
5068 <summary>
5069 Gets or sets the required property if this property is present.
5070 </summary>
5071 <value>The required property if this property is present.</value>
5072 </member>
5073 <member name="P:Newtonsoft.Json.Schema.JsonSchema.Identity">
5074 <summary>
5075 Gets or sets the identity.
5076 </summary>
5077 <value>The identity.</value>
5078 </member>
5079 <member name="P:Newtonsoft.Json.Schema.JsonSchema.Enum">
5080 <summary>
5081 Gets or sets the a collection of valid enum values allowed.
5082 </summary>
5083 <value>A collection of valid enum values allowed.</value>
5084 </member>
5085 <member name="P:Newtonsoft.Json.Schema.JsonSchema.Options">
5086 <summary>
5087 Gets or sets a collection of options.
5088 </summary>
5089 <value>A collection of options.</value>
5090 </member>
5091 <member name="P:Newtonsoft.Json.Schema.JsonSchema.Disallow">
5092 <summary>
5093 Gets or sets disallowed types.
5094 </summary>
5095 <value>The disallow types.</value>
5096 </member>
5097 <member name="P:Newtonsoft.Json.Schema.JsonSchema.Default">
5098 <summary>
5099 Gets or sets the default value.
5100 </summary>
5101 <value>The default value.</value>
5102 </member>
5103 <member name="P:Newtonsoft.Json.Schema.JsonSchema.Extends">
5104 <summary>
5105 Gets or sets the extend <see cref="T:Newtonsoft.Json.Schema.JsonSchema"/>.
5106 </summary>
5107 <value>The extended <see cref="T:Newtonsoft.Json.Schema.JsonSchema"/>.</value>
5108 </member>
5109 <member name="P:Newtonsoft.Json.Schema.JsonSchema.Format">
5110 <summary>
5111 Gets or sets the format.
5112 </summary>
5113 <value>The format.</value>
5114 </member>
5115 <member name="T:Newtonsoft.Json.Schema.JsonSchemaGenerator">
5116 <summary>
5117 Generates a <see cref="T:Newtonsoft.Json.Schema.JsonSchema"/> from a specified <see cref="T:System.Type"/>.
5118 </summary>
5119 </member>
5120 <member name="M:Newtonsoft.Json.Schema.JsonSchemaGenerator.Generate(System.Type)">
5121 <summary>
5122 Generate a <see cref="T:Newtonsoft.Json.Schema.JsonSchema"/> from the specified type.
5123 </summary>
5124 <param name="type">The type to generate a <see cref="T:Newtonsoft.Json.Schema.JsonSchema"/> from.</param>
5125 <returns>A <see cref="T:Newtonsoft.Json.Schema.JsonSchema"/> generated from the specified type.</returns>
5126 </member>
5127 <member name="M:Newtonsoft.Json.Schema.JsonSchemaGenerator.Generate(System.Type,Newtonsoft.Json.Schema.JsonSchemaResolver)">
5128 <summary>
5129 Generate a <see cref="T:Newtonsoft.Json.Schema.JsonSchema"/> from the specified type.
5130 </summary>
5131 <param name="type">The type to generate a <see cref="T:Newtonsoft.Json.Schema.JsonSchema"/> from.</param>
5132 <param name="resolver">The <see cref="T:Newtonsoft.Json.Schema.JsonSchemaResolver"/> used to resolve schema references.</param>
5133 <returns>A <see cref="T:Newtonsoft.Json.Schema.JsonSchema"/> generated from the specified type.</returns>
5134 </member>
5135 <member name="M:Newtonsoft.Json.Schema.JsonSchemaGenerator.Generate(System.Type,System.Boolean)">
5136 <summary>
5137 Generate a <see cref="T:Newtonsoft.Json.Schema.JsonSchema"/> from the specified type.
5138 </summary>
5139 <param name="type">The type to generate a <see cref="T:Newtonsoft.Json.Schema.JsonSchema"/> from.</param>
5140 <param name="rootSchemaNullable">Specify whether the generated root <see cref="T:Newtonsoft.Json.Schema.JsonSchema"/> will be nullable.</param>
5141 <returns>A <see cref="T:Newtonsoft.Json.Schema.JsonSchema"/> generated from the specified type.</returns>
5142 </member>
5143 <member name="M:Newtonsoft.Json.Schema.JsonSchemaGenerator.Generate(System.Type,Newtonsoft.Json.Schema.JsonSchemaResolver,System.Boolean)">
5144 <summary>
5145 Generate a <see cref="T:Newtonsoft.Json.Schema.JsonSchema"/> from the specified type.
5146 </summary>
5147 <param name="type">The type to generate a <see cref="T:Newtonsoft.Json.Schema.JsonSchema"/> from.</param>
5148 <param name="resolver">The <see cref="T:Newtonsoft.Json.Schema.JsonSchemaResolver"/> used to resolve schema references.</param>
5149 <param name="rootSchemaNullable">Specify whether the generated root <see cref="T:Newtonsoft.Json.Schema.JsonSchema"/> will be nullable.</param>
5150 <returns>A <see cref="T:Newtonsoft.Json.Schema.JsonSchema"/> generated from the specified type.</returns>
5151 </member>
5152 <member name="P:Newtonsoft.Json.Schema.JsonSchemaGenerator.UndefinedSchemaIdHandling">
5153 <summary>
5154 Gets or sets how undefined schemas are handled by the serializer.
5155 </summary>
5156 </member>
5157 <member name="P:Newtonsoft.Json.Schema.JsonSchemaGenerator.ContractResolver">
5158 <summary>
5159 Gets or sets the contract resolver.
5160 </summary>
5161 <value>The contract resolver.</value>
5162 </member>
5163 <member name="T:Newtonsoft.Json.Schema.JsonSchemaType">
5164 <summary>
5165 The value types allowed by the <see cref="T:Newtonsoft.Json.Schema.JsonSchema"/>.
5166 </summary>
5167 </member>
5168 <member name="F:Newtonsoft.Json.Schema.JsonSchemaType.None">
5169 <summary>
5170 No type specified.
5171 </summary>
5172 </member>
5173 <member name="F:Newtonsoft.Json.Schema.JsonSchemaType.String">
5174 <summary>
5175 String type.
5176 </summary>
5177 </member>
5178 <member name="F:Newtonsoft.Json.Schema.JsonSchemaType.Float">
5179 <summary>
5180 Float type.
5181 </summary>
5182 </member>
5183 <member name="F:Newtonsoft.Json.Schema.JsonSchemaType.Integer">
5184 <summary>
5185 Integer type.
5186 </summary>
5187 </member>
5188 <member name="F:Newtonsoft.Json.Schema.JsonSchemaType.Boolean">
5189 <summary>
5190 Boolean type.
5191 </summary>
5192 </member>
5193 <member name="F:Newtonsoft.Json.Schema.JsonSchemaType.Object">
5194 <summary>
5195 Object type.
5196 </summary>
5197 </member>
5198 <member name="F:Newtonsoft.Json.Schema.JsonSchemaType.Array">
5199 <summary>
5200 Array type.
5201 </summary>
5202 </member>
5203 <member name="F:Newtonsoft.Json.Schema.JsonSchemaType.Null">
5204 <summary>
5205 Null type.
5206 </summary>
5207 </member>
5208 <member name="F:Newtonsoft.Json.Schema.JsonSchemaType.Any">
5209 <summary>
5210 Any type.
5211 </summary>
5212 </member>
5213 <member name="T:Newtonsoft.Json.Serialization.JsonObjectContract">
5214 <summary>
5215 Contract details for a <see cref="T:System.Type"/> used by the <see cref="T:Newtonsoft.Json.JsonSerializer"/>.
5216 </summary>
5217 </member>
5218 <member name="M:Newtonsoft.Json.Serialization.JsonObjectContract.#ctor(System.Type)">
5219 <summary>
5220 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Serialization.JsonObjectContract"/> class.
5221 </summary>
5222 <param name="underlyingType">The underlying type for the contract.</param>
5223 </member>
5224 <member name="P:Newtonsoft.Json.Serialization.JsonObjectContract.MemberSerialization">
5225 <summary>
5226 Gets or sets the object member serialization.
5227 </summary>
5228 <value>The member object serialization.</value>
5229 </member>
5230 <member name="P:Newtonsoft.Json.Serialization.JsonObjectContract.Properties">
5231 <summary>
5232 Gets the object's properties.
5233 </summary>
5234 <value>The object's properties.</value>
5235 </member>
5236 <member name="P:Newtonsoft.Json.Serialization.JsonObjectContract.ParametrizedConstructor">
5237 <summary>
5238 Gets or sets the parametrized constructor used to create the object.
5239 </summary>
5240 <value>The parametrized constructor.</value>
5241 </member>
5242 <member name="T:Newtonsoft.Json.Serialization.OnErrorAttribute">
5243 <summary>
5244 When applied to a method, specifies that the method is called when an error occurs serializing an object.
5245 </summary>
5246 </member>
5247 <member name="T:Newtonsoft.Json.Serialization.ReflectionValueProvider">
5248 <summary>
5249 Get and set values for a <see cref="T:System.Reflection.MemberInfo"/> using reflection.
5250 </summary>
5251 </member>
5252 <member name="M:Newtonsoft.Json.Serialization.ReflectionValueProvider.#ctor(System.Reflection.MemberInfo)">
5253 <summary>
5254 Initializes a new instance of the <see cref="T:Newtonsoft.Json.Serialization.ReflectionValueProvider"/> class.
5255 </summary>
5256 <param name="memberInfo">The member info.</param>
5257 </member>
5258 <member name="M:Newtonsoft.Json.Serialization.ReflectionValueProvider.SetValue(System.Object,System.Object)">
5259 <summary>
5260 Sets the value.
5261 </summary>
5262 <param name="target">The target to set the value on.</param>
5263 <param name="value">The value to set on the target.</param>
5264 </member>
5265 <member name="M:Newtonsoft.Json.Serialization.ReflectionValueProvider.GetValue(System.Object)">
5266 <summary>
5267 Gets the value.
5268 </summary>
5269 <param name="target">The target to get the value from.</param>
5270 <returns>The value.</returns>
5271 </member>
5272 <member name="T:Newtonsoft.Json.TypeNameHandling">
5273 <summary>
5274 Specifies type name handling options for the <see cref="T:Newtonsoft.Json.JsonSerializer"/>.
5275 </summary>
5276 </member>
5277 <member name="F:Newtonsoft.Json.TypeNameHandling.None">
5278 <summary>
5279 Do not include the .NET type name when serializing types.
5280 </summary>
5281 </member>
5282 <member name="F:Newtonsoft.Json.TypeNameHandling.Objects">
5283 <summary>
5284 Include the .NET type name when serializing into a JSON object structure.
5285 </summary>
5286 </member>
5287 <member name="F:Newtonsoft.Json.TypeNameHandling.Arrays">
5288 <summary>
5289 Include the .NET type name when serializing into a JSON array structure.
5290 </summary>
5291 </member>
5292 <member name="F:Newtonsoft.Json.TypeNameHandling.All">
5293 <summary>
5294 Always include the .NET type name when serializing.
5295 </summary>
5296 </member>
5297 <member name="M:Newtonsoft.Json.Utilities.ConvertUtils.Convert``1(System.Object)">
5298 <summary>
5299 Converts the value to the specified type.
5300 </summary>
5301 <typeparam name="T">The type to convert the value to.</typeparam>
5302 <param name="initialValue">The value to convert.</param>
5303 <returns>The converted type.</returns>
5304 </member>
5305 <member name="M:Newtonsoft.Json.Utilities.ConvertUtils.Convert``1(System.Object,System.Globalization.CultureInfo)">
5306 <summary>
5307 Converts the value to the specified type.
5308 </summary>
5309 <typeparam name="T">The type to convert the value to.</typeparam>
5310 <param name="initialValue">The value to convert.</param>
5311 <param name="culture">The culture to use when converting.</param>
5312 <returns>The converted type.</returns>
5313 </member>
5314 <member name="M:Newtonsoft.Json.Utilities.ConvertUtils.Convert(System.Object,System.Globalization.CultureInfo,System.Type)">
5315 <summary>
5316 Converts the value to the specified type.
5317 </summary>
5318 <param name="initialValue">The value to convert.</param>
5319 <param name="culture">The culture to use when converting.</param>
5320 <param name="targetType">The type to convert the value to.</param>
5321 <returns>The converted type.</returns>
5322 </member>
5323 <member name="M:Newtonsoft.Json.Utilities.ConvertUtils.TryConvert``1(System.Object,``0@)">
5324 <summary>
5325 Converts the value to the specified type.
5326 </summary>
5327 <typeparam name="T">The type to convert the value to.</typeparam>
5328 <param name="initialValue">The value to convert.</param>
5329 <param name="convertedValue">The converted value if the conversion was successful or the default value of <c>T</c> if it failed.</param>
5330 <returns>
5331 <c>true</c> if <c>initialValue</c> was converted successfully; otherwise, <c>false</c>.
5332 </returns>
5333 </member>
5334 <member name="M:Newtonsoft.Json.Utilities.ConvertUtils.TryConvert``1(System.Object,System.Globalization.CultureInfo,``0@)">
5335 <summary>
5336 Converts the value to the specified type.
5337 </summary>
5338 <typeparam name="T">The type to convert the value to.</typeparam>
5339 <param name="initialValue">The value to convert.</param>
5340 <param name="culture">The culture to use when converting.</param>
5341 <param name="convertedValue">The converted value if the conversion was successful or the default value of <c>T</c> if it failed.</param>
5342 <returns>
5343 <c>true</c> if <c>initialValue</c> was converted successfully; otherwise, <c>false</c>.
5344 </returns>
5345 </member>
5346 <member name="M:Newtonsoft.Json.Utilities.ConvertUtils.TryConvert(System.Object,System.Globalization.CultureInfo,System.Type,System.Object@)">
5347 <summary>
5348 Converts the value to the specified type.
5349 </summary>
5350 <param name="initialValue">The value to convert.</param>
5351 <param name="culture">The culture to use when converting.</param>
5352 <param name="targetType">The type to convert the value to.</param>
5353 <param name="convertedValue">The converted value if the conversion was successful or the default value of <c>T</c> if it failed.</param>
5354 <returns>
5355 <c>true</c> if <c>initialValue</c> was converted successfully; otherwise, <c>false</c>.
5356 </returns>
5357 </member>
5358 <member name="M:Newtonsoft.Json.Utilities.ConvertUtils.ConvertOrCast``1(System.Object)">
5359 <summary>
5360 Converts the value to the specified type. If the value is unable to be converted, the
5361 value is checked whether it assignable to the specified type.
5362 </summary>
5363 <typeparam name="T">The type to convert or cast the value to.</typeparam>
5364 <param name="initialValue">The value to convert.</param>
5365 <returns>The converted type. If conversion was unsuccessful, the initial value is returned if assignable to the target type</returns>
5366 </member>
5367 <member name="M:Newtonsoft.Json.Utilities.ConvertUtils.ConvertOrCast``1(System.Object,System.Globalization.CultureInfo)">
5368 <summary>
5369 Converts the value to the specified type. If the value is unable to be converted, the
5370 value is checked whether it assignable to the specified type.
5371 </summary>
5372 <typeparam name="T">The type to convert or cast the value to.</typeparam>
5373 <param name="initialValue">The value to convert.</param>
5374 <param name="culture">The culture to use when converting.</param>
5375 <returns>The converted type. If conversion was unsuccessful, the initial value is returned if assignable to the target type</returns>
5376 </member>
5377 <member name="M:Newtonsoft.Json.Utilities.ConvertUtils.ConvertOrCast(System.Object,System.Globalization.CultureInfo,System.Type)">
5378 <summary>
5379 Converts the value to the specified type. If the value is unable to be converted, the
5380 value is checked whether it assignable to the specified type.
5381 </summary>
5382 <param name="initialValue">The value to convert.</param>
5383 <param name="culture">The culture to use when converting.</param>
5384 <param name="targetType">The type to convert or cast the value to.</param>
5385 <returns>
5386 The converted type. If conversion was unsuccessful, the initial value
5387 is returned if assignable to the target type.
5388 </returns>
5389 </member>
5390 <member name="M:Newtonsoft.Json.Utilities.ConvertUtils.TryConvertOrCast``1(System.Object,``0@)">
5391 <summary>
5392 Converts the value to the specified type. If the value is unable to be converted, the
5393 value is checked whether it assignable to the specified type.
5394 </summary>
5395 <typeparam name="T">The type to convert the value to.</typeparam>
5396 <param name="initialValue">The value to convert.</param>
5397 <param name="convertedValue">The converted value if the conversion was successful or the default value of <c>T</c> if it failed.</param>
5398 <returns>
5399 <c>true</c> if <c>initialValue</c> was converted successfully or is assignable; otherwise, <c>false</c>.
5400 </returns>
5401 </member>
5402 <member name="M:Newtonsoft.Json.Utilities.ConvertUtils.TryConvertOrCast``1(System.Object,System.Globalization.CultureInfo,``0@)">
5403 <summary>
5404 Converts the value to the specified type. If the value is unable to be converted, the
5405 value is checked whether it assignable to the specified type.
5406 </summary>
5407 <typeparam name="T">The type to convert the value to.</typeparam>
5408 <param name="initialValue">The value to convert.</param>
5409 <param name="culture">The culture to use when converting.</param>
5410 <param name="convertedValue">The converted value if the conversion was successful or the default value of <c>T</c> if it failed.</param>
5411 <returns>
5412 <c>true</c> if <c>initialValue</c> was converted successfully or is assignable; otherwise, <c>false</c>.
5413 </returns>
5414 </member>
5415 <member name="M:Newtonsoft.Json.Utilities.ConvertUtils.TryConvertOrCast(System.Object,System.Globalization.CultureInfo,System.Type,System.Object@)">
5416 <summary>
5417 Converts the value to the specified type. If the value is unable to be converted, the
5418 value is checked whether it assignable to the specified type.
5419 </summary>
5420 <param name="initialValue">The value to convert.</param>
5421 <param name="culture">The culture to use when converting.</param>
5422 <param name="targetType">The type to convert the value to.</param>
5423 <param name="convertedValue">The converted value if the conversion was successful or the default value of <c>T</c> if it failed.</param>
5424 <returns>
5425 <c>true</c> if <c>initialValue</c> was converted successfully or is assignable; otherwise, <c>false</c>.
5426 </returns>
5427 </member>
5428 <member name="M:Newtonsoft.Json.Utilities.EnumUtils.Parse``1(System.String)">
5429 <summary>
5430 Parses the specified enum member name, returning it's value.
5431 </summary>
5432 <param name="enumMemberName">Name of the enum member.</param>
5433 <returns></returns>
5434 </member>
5435 <member name="M:Newtonsoft.Json.Utilities.EnumUtils.Parse``1(System.String,System.Boolean)">
5436 <summary>
5437 Parses the specified enum member name, returning it's value.
5438 </summary>
5439 <param name="enumMemberName">Name of the enum member.</param>
5440 <param name="ignoreCase">If set to <c>true</c> ignore case.</param>
5441 <returns></returns>
5442 </member>
5443 <member name="M:Newtonsoft.Json.Utilities.EnumUtils.GetNamesAndValues``1">
5444 <summary>
5445 Gets a dictionary of the names and values of an Enum type.
5446 </summary>
5447 <returns></returns>
5448 </member>
5449 <member name="M:Newtonsoft.Json.Utilities.EnumUtils.GetNamesAndValues``2">
5450 <summary>
5451 Gets a dictionary of the names and values of an Enum type.
5452 </summary>
5453 <returns></returns>
5454 </member>
5455 <member name="M:Newtonsoft.Json.Utilities.EnumUtils.GetNamesAndValues``1(System.Type)">
5456 <summary>
5457 Gets a dictionary of the names and values of an Enum type.
5458 </summary>
5459 <param name="enumType">The enum type to get names and values for.</param>
5460 <returns></returns>
5461 </member>
5462 <member name="M:Newtonsoft.Json.Utilities.EnumUtils.GetMaximumValue``1(System.Type)">
5463 <summary>
5464 Gets the maximum valid value of an Enum type. Flags enums are ORed.
5465 </summary>
5466 <typeparam name="TEnumType">The type of the returned value. Must be assignable from the enum's underlying value type.</typeparam>
5467 <param name="enumType">The enum type to get the maximum value for.</param>
5468 <returns></returns>
5469 </member>
5470 <member name="T:Newtonsoft.Json.JsonToken">
5471 <summary>
5472 Specifies the type of Json token.
5473 </summary>
5474 </member>
5475 <member name="F:Newtonsoft.Json.JsonToken.None">
5476 <summary>
5477 This is returned by the <see cref="T:Newtonsoft.Json.JsonReader"/> if a <see cref="M:Newtonsoft.Json.JsonReader.Read"/> method has not been called.
5478 </summary>
5479 </member>
5480 <member name="F:Newtonsoft.Json.JsonToken.StartObject">
5481 <summary>
5482 An object start token.
5483 </summary>
5484 </member>
5485 <member name="F:Newtonsoft.Json.JsonToken.StartArray">
5486 <summary>
5487 An array start token.
5488 </summary>
5489 </member>
5490 <member name="F:Newtonsoft.Json.JsonToken.StartConstructor">
5491 <summary>
5492 A constructor start token.
5493 </summary>
5494 </member>
5495 <member name="F:Newtonsoft.Json.JsonToken.PropertyName">
5496 <summary>
5497 An object property name.
5498 </summary>
5499 </member>
5500 <member name="F:Newtonsoft.Json.JsonToken.Comment">
5501 <summary>
5502 A comment.
5503 </summary>
5504 </member>
5505 <member name="F:Newtonsoft.Json.JsonToken.Raw">
5506 <summary>
5507 Raw JSON.
5508 </summary>
5509 </member>
5510 <member name="F:Newtonsoft.Json.JsonToken.Integer">
5511 <summary>
5512 An interger.
5513 </summary>
5514 </member>
5515 <member name="F:Newtonsoft.Json.JsonToken.Float">
5516 <summary>
5517 A float.
5518 </summary>
5519 </member>
5520 <member name="F:Newtonsoft.Json.JsonToken.String">
5521 <summary>
5522 A string.
5523 </summary>
5524 </member>
5525 <member name="F:Newtonsoft.Json.JsonToken.Boolean">
5526 <summary>
5527 A boolean.
5528 </summary>
5529 </member>
5530 <member name="F:Newtonsoft.Json.JsonToken.Null">
5531 <summary>
5532 A null token.
5533 </summary>
5534 </member>
5535 <member name="F:Newtonsoft.Json.JsonToken.Undefined">
5536 <summary>
5537 An undefined token.
5538 </summary>
5539 </member>
5540 <member name="F:Newtonsoft.Json.JsonToken.EndObject">
5541 <summary>
5542 An object end token.
5543 </summary>
5544 </member>
5545 <member name="F:Newtonsoft.Json.JsonToken.EndArray">
5546 <summary>
5547 An array end token.
5548 </summary>
5549 </member>
5550 <member name="F:Newtonsoft.Json.JsonToken.EndConstructor">
5551 <summary>
5552 A constructor end token.
5553 </summary>
5554 </member>
5555 <member name="F:Newtonsoft.Json.JsonToken.Date">
5556 <summary>
5557 A Date.
5558 </summary>
5559 </member>
5560 <member name="F:Newtonsoft.Json.JsonToken.Bytes">
5561 <summary>
5562 Byte data.
5563 </summary>
5564 </member>
5565 <member name="T:Newtonsoft.Json.WriteState">
5566 <summary>
5567 Specifies the state of the <see cref="T:Newtonsoft.Json.JsonWriter"/>.
5568 </summary>
5569 </member>
5570 <member name="F:Newtonsoft.Json.WriteState.Error">
5571 <summary>
5572 An exception has been thrown, which has left the <see cref="T:Newtonsoft.Json.JsonWriter"/> in an invalid state.
5573 You may call the <see cref="M:Newtonsoft.Json.JsonWriter.Close"/> method to put the <see cref="T:Newtonsoft.Json.JsonWriter"/> in the <c>Closed</c> state.
5574 Any other <see cref="T:Newtonsoft.Json.JsonWriter"/> method calls results in an <see cref="T:System.InvalidOperationException"/> being thrown.
5575 </summary>
5576 </member>
5577 <member name="F:Newtonsoft.Json.WriteState.Closed">
5578 <summary>
5579 The <see cref="M:Newtonsoft.Json.JsonWriter.Close"/> method has been called.
5580 </summary>
5581 </member>
5582 <member name="F:Newtonsoft.Json.WriteState.Object">
5583 <summary>
5584 An object is being written.
5585 </summary>
5586 </member>
5587 <member name="F:Newtonsoft.Json.WriteState.Array">
5588 <summary>
5589 A array is being written.
5590 </summary>
5591 </member>
5592 <member name="F:Newtonsoft.Json.WriteState.Constructor">
5593 <summary>
5594 A constructor is being written.
5595 </summary>
5596 </member>
5597 <member name="F:Newtonsoft.Json.WriteState.Property">
5598 <summary>
5599 A property is being written.
5600 </summary>
5601 </member>
5602 <member name="F:Newtonsoft.Json.WriteState.Start">
5603 <summary>
5604 A write method has not been called.
5605 </summary>
5606 </member>
5607 <member name="T:Newtonsoft.Json.Formatting">
5608 <summary>
5609 Specifies formatting options for the <see cref="T:Newtonsoft.Json.JsonTextWriter"/>.
5610 </summary>
5611 </member>
5612 <member name="F:Newtonsoft.Json.Formatting.None">
5613 <summary>
5614 No special formatting is applied. This is the default.
5615 </summary>
5616 </member>
5617 <member name="F:Newtonsoft.Json.Formatting.Indented">
5618 <summary>
5619 Causes child objects to be indented according to the <see cref="P:Newtonsoft.Json.JsonTextWriter.Indentation"/> and <see cref="P:Newtonsoft.Json.JsonTextWriter.IndentChar"/> settings.
5620 </summary>
5621 </member>
5622 <member name="T:Newtonsoft.Json.Utilities.StringBuffer">
5623 <summary>
5624 Builds a string. Unlike StringBuilder this class lets you reuse it's internal buffer.
5625 </summary>
5626 </member>
5627 <member name="M:Newtonsoft.Json.Utilities.CollectionUtils.IsNullOrEmpty(System.Collections.ICollection)">
5628 <summary>
5629 Determines whether the collection is null or empty.
5630 </summary>
5631 <param name="collection">The collection.</param>
5632 <returns>
5633 <c>true</c> if the collection is null or empty; otherwise, <c>false</c>.
5634 </returns>
5635 </member>
5636 <member name="M:Newtonsoft.Json.Utilities.CollectionUtils.IsNullOrEmpty``1(System.Collections.Generic.ICollection{``0})">
5637 <summary>
5638 Determines whether the collection is null or empty.
5639 </summary>
5640 <param name="collection">The collection.</param>
5641 <returns>
5642 <c>true</c> if the collection is null or empty; otherwise, <c>false</c>.
5643 </returns>
5644 </member>
5645 <member name="M:Newtonsoft.Json.Utilities.CollectionUtils.IsNullOrEmptyOrDefault``1(System.Collections.Generic.IList{``0})">
5646 <summary>
5647 Determines whether the collection is null, empty or its contents are uninitialized values.
5648 </summary>
5649 <param name="list">The list.</param>
5650 <returns>
5651 <c>true</c> if the collection is null or empty or its contents are uninitialized values; otherwise, <c>false</c>.
5652 </returns>
5653 </member>
5654 <member name="M:Newtonsoft.Json.Utilities.CollectionUtils.Slice``1(System.Collections.Generic.IList{``0},System.Nullable{System.Int32},System.Nullable{System.Int32})">
5655 <summary>
5656 Makes a slice of the specified list in between the start and end indexes.
5657 </summary>
5658 <param name="list">The list.</param>
5659 <param name="start">The start index.</param>
5660 <param name="end">The end index.</param>
5661 <returns>A slice of the list.</returns>
5662 </member>
5663 <member name="M:Newtonsoft.Json.Utilities.CollectionUtils.Slice``1(System.Collections.Generic.IList{``0},System.Nullable{System.Int32},System.Nullable{System.Int32},System.Nullable{System.Int32})">
5664 <summary>
5665 Makes a slice of the specified list in between the start and end indexes,
5666 getting every so many items based upon the step.
5667 </summary>
5668 <param name="list">The list.</param>
5669 <param name="start">The start index.</param>
5670 <param name="end">The end index.</param>
5671 <param name="step">The step.</param>
5672 <returns>A slice of the list.</returns>
5673 </member>
5674 <member name="M:Newtonsoft.Json.Utilities.CollectionUtils.GroupBy``2(System.Collections.Generic.ICollection{``1},System.Func{``1,``0})">
5675 <summary>
5676 Group the collection using a function which returns the key.
5677 </summary>
5678 <param name="source">The source collection to group.</param>
5679 <param name="keySelector">The key selector.</param>
5680 <returns>A Dictionary with each key relating to a list of objects in a list grouped under it.</returns>
5681 </member>
5682 <member name="M:Newtonsoft.Json.Utilities.CollectionUtils.AddRange``1(System.Collections.Generic.IList{``0},System.Collections.Generic.IEnumerable{``0})">
5683 <summary>
5684 Adds the elements of the specified collection to the specified generic IList.
5685 </summary>
5686 <param name="initial">The list to add to.</param>
5687 <param name="collection">The collection of elements to add.</param>
5688 </member>
5689 <member name="M:Newtonsoft.Json.Utilities.ReflectionUtils.GetCollectionItemType(System.Type)">
5690 <summary>
5691 Gets the type of the typed collection's items.
5692 </summary>
5693 <param name="type">The type.</param>
5694 <returns>The type of the typed collection's items.</returns>
5695 </member>
5696 <member name="M:Newtonsoft.Json.Utilities.ReflectionUtils.ItemsUnitializedValue``1(System.Collections.Generic.IList{``0})">
5697 <summary>
5698 Tests whether the list's items are their unitialized value.
5699 </summary>
5700 <param name="list">The list.</param>
5701 <returns>Whether the list's items are their unitialized value</returns>
5702 </member>
5703 <member name="M:Newtonsoft.Json.Utilities.ReflectionUtils.GetMemberUnderlyingType(System.Reflection.MemberInfo)">
5704 <summary>
5705 Gets the member's underlying type.
5706 </summary>
5707 <param name="member">The member.</param>
5708 <returns>The underlying type of the member.</returns>
5709 </member>
5710 <member name="M:Newtonsoft.Json.Utilities.ReflectionUtils.IsIndexedProperty(System.Reflection.MemberInfo)">
5711 <summary>
5712 Determines whether the member is an indexed property.
5713 </summary>
5714 <param name="member">The member.</param>
5715 <returns>
5716 <c>true</c> if the member is an indexed property; otherwise, <c>false</c>.
5717 </returns>
5718 </member>
5719 <member name="M:Newtonsoft.Json.Utilities.ReflectionUtils.IsIndexedProperty(System.Reflection.PropertyInfo)">
5720 <summary>
5721 Determines whether the property is an indexed property.
5722 </summary>
5723 <param name="property">The property.</param>
5724 <returns>
5725 <c>true</c> if the property is an indexed property; otherwise, <c>false</c>.
5726 </returns>
5727 </member>
5728 <member name="M:Newtonsoft.Json.Utilities.ReflectionUtils.GetMemberValue(System.Reflection.MemberInfo,System.Object)">
5729 <summary>
5730 Gets the member's value on the object.
5731 </summary>
5732 <param name="member">The member.</param>
5733 <param name="target">The target object.</param>
5734 <returns>The member's value on the object.</returns>
5735 </member>
5736 <member name="M:Newtonsoft.Json.Utilities.ReflectionUtils.SetMemberValue(System.Reflection.MemberInfo,System.Object,System.Object)">
5737 <summary>
5738 Sets the member's value on the target object.
5739 </summary>
5740 <param name="member">The member.</param>
5741 <param name="target">The target.</param>
5742 <param name="value">The value.</param>
5743 </member>
5744 <member name="M:Newtonsoft.Json.Utilities.ReflectionUtils.CanReadMemberValue(System.Reflection.MemberInfo)">
5745 <summary>
5746 Determines whether the specified MemberInfo can be read.
5747 </summary>
5748 <param name="member">The MemberInfo to determine whether can be read.</param>
5749 <returns>
5750 <c>true</c> if the specified MemberInfo can be read; otherwise, <c>false</c>.
5751 </returns>
5752 </member>
5753 <member name="M:Newtonsoft.Json.Utilities.ReflectionUtils.CanSetMemberValue(System.Reflection.MemberInfo)">
5754 <summary>
5755 Determines whether the specified MemberInfo can be set.
5756 </summary>
5757 <param name="member">The MemberInfo to determine whether can be set.</param>
5758 <returns>
5759 <c>true</c> if the specified MemberInfo can be set; otherwise, <c>false</c>.
5760 </returns>
5761 </member>
5762 <member name="M:Newtonsoft.Json.Utilities.StringUtils.ContainsWhiteSpace(System.String)">
5763 <summary>
5764 Determines whether the string contains white space.
5765 </summary>
5766 <param name="s">The string to test for white space.</param>
5767 <returns>
5768 <c>true</c> if the string contains white space; otherwise, <c>false</c>.
5769 </returns>
5770 </member>
5771 <member name="M:Newtonsoft.Json.Utilities.StringUtils.IsWhiteSpace(System.String)">
5772 <summary>
5773 Determines whether the string is all white space. Empty string will return false.
5774 </summary>
5775 <param name="s">The string to test whether it is all white space.</param>
5776 <returns>
5777 <c>true</c> if the string is all white space; otherwise, <c>false</c>.
5778 </returns>
5779 </member>
5780 <member name="M:Newtonsoft.Json.Utilities.StringUtils.EnsureEndsWith(System.String,System.String)">
5781 <summary>
5782 Ensures the target string ends with the specified string.
5783 </summary>
5784 <param name="target">The target.</param>
5785 <param name="value">The value.</param>
5786 <returns>The target string with the value string at the end.</returns>
5787 </member>
5788 <member name="M:Newtonsoft.Json.Utilities.StringUtils.IfNotNullOrEmpty(System.String,System.Action{System.String})">
5789 <summary>
5790 Perform an action if the string is not null or empty.
5791 </summary>
5792 <param name="value">The value.</param>
5793 <param name="action">The action to perform.</param>
5794 </member>
5795 <member name="M:Newtonsoft.Json.Utilities.StringUtils.Indent(System.String,System.Int32)">
5796 <summary>
5797 Indents the specified string.
5798 </summary>
5799 <param name="s">The string to indent.</param>
5800 <param name="indentation">The number of characters to indent by.</param>
5801 <returns></returns>
5802 </member>
5803 <member name="M:Newtonsoft.Json.Utilities.StringUtils.Indent(System.String,System.Int32,System.Char)">
5804 <summary>
5805 Indents the specified string.
5806 </summary>
5807 <param name="s">The string to indent.</param>
5808 <param name="indentation">The number of characters to indent by.</param>
5809 <param name="indentChar">The indent character.</param>
5810 <returns></returns>
5811 </member>
5812 <member name="M:Newtonsoft.Json.Utilities.StringUtils.NumberLines(System.String)">
5813 <summary>
5814 Numbers the lines.
5815 </summary>
5816 <param name="s">The string to number.</param>
5817 <returns></returns>
5818 </member>
5819 <member name="M:Newtonsoft.Json.Utilities.StringUtils.NullEmptyString(System.String)">
5820 <summary>
5821 Nulls an empty string.
5822 </summary>
5823 <param name="s">The string.</param>
5824 <returns>Null if the string was null, otherwise the string unchanged.</returns>
5825 </member>
5826 </members>
5827</doc>
diff --git a/bin/Newtonsoft.Json.pdb b/bin/Newtonsoft.Json.pdb
deleted file mode 100644
index 892546a..0000000
--- a/bin/Newtonsoft.Json.pdb
+++ /dev/null
Binary files differ
diff --git a/bin/OpenMetaverse.Rendering.Meshmerizer.dll b/bin/OpenMetaverse.Rendering.Meshmerizer.dll
index 1b4cab5..30b9c7b 100755
--- a/bin/OpenMetaverse.Rendering.Meshmerizer.dll
+++ b/bin/OpenMetaverse.Rendering.Meshmerizer.dll
Binary files differ
diff --git a/bin/OpenMetaverse.StructuredData.dll b/bin/OpenMetaverse.StructuredData.dll
index 7b5174d..5c0b3c6 100755
--- a/bin/OpenMetaverse.StructuredData.dll
+++ b/bin/OpenMetaverse.StructuredData.dll
Binary files differ
diff --git a/bin/OpenMetaverse.dll b/bin/OpenMetaverse.dll
index a08b406..511096e 100755
--- a/bin/OpenMetaverse.dll
+++ b/bin/OpenMetaverse.dll
Binary files differ
diff --git a/bin/OpenMetaverse.dll.config b/bin/OpenMetaverse.dll.config
index e8c90a4..b67da5f 100644
--- a/bin/OpenMetaverse.dll.config
+++ b/bin/OpenMetaverse.dll.config
@@ -1,7 +1,5 @@
1<configuration> 1<configuration>
2 <dllmap os="osx" dll="openjpeg-dotnet.dll" target="lib64/libopenjpeg-dotnet-2.1.3.0-dotnet-1.dylib" /> 2 <dllmap os="osx" dll="openjpeg-dotnet.dll" target="lib64/libopenjpeg-dotnet-2.1.5.0-dotnet-1.dylib" />
3 <dllmap os="!windows,osx" cpu="x86-64,ia64" dll="openjpeg-dotnet.dll" target="lib32/libopenjpeg-dotnet-2.1.3.0-dotnet-1-x86_64" /> 3 <dllmap os="!windows,osx" cpu="x86-64,ia64" dll="openjpeg-dotnet-x86_64.dll" target="lib64/libopenjpeg-dotnet-x86_64" />
4 <dllmap os="!windows,osx" cpu="x86-64,ia64" dll="openjpeg-dotnet-x86_64.dll" target="lib64/libopenjpeg-dotnet-2.1.3.0-dotnet-1-x86_64" /> 4 <dllmap os="!windows,osx" cpu="x86" dll="openjpeg-dotnet.dll" target="lib32/libopenjpeg-dotnet" />
5 <dllmap os="!windows,osx" cpu="x86" dll="openjpeg-dotnet.dll" target="lib32/libopenjpeg-dotnet-2.1.3.0-dotnet-1-i686" />
6 <dllmap os="!windows,osx" cpu="x86" dll="openjpeg-dotnet-x86_64.dll" target="lib64/libopenjpeg-dotnet-2.1.3.0-dotnet-1-i686" />
7</configuration> 5</configuration>
diff --git a/bin/OpenMetaverseTypes.dll b/bin/OpenMetaverseTypes.dll
index fc4f8eb..8bc8885 100755
--- a/bin/OpenMetaverseTypes.dll
+++ b/bin/OpenMetaverseTypes.dll
Binary files differ
diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example
index 9c68b65..b21a214 100644
--- a/bin/OpenSim.ini.example
+++ b/bin/OpenSim.ini.example
@@ -1,19 +1,23 @@
1;; This is the main configuration file for OpenSimulator. If it's named OpenSim.ini 1;; This is the main configuration file for OpenSimulator.
2;; then it will be loaded by OpenSimulator. If it's named OpenSim.ini.example then 2;; If it's named OpenSim.ini then it will be loaded by OpenSimulator.
3;; you will need to copy it to OpenSim.ini first (if that file does not already exist) 3;; If it's named OpenSim.ini.example then you will need to copy it to
4;; OpenSim.ini first (if that file does not already exist)
4;; 5;;
5;; If you are copying, then once you have copied OpenSim.ini.example to OpenSim.ini you will 6;; If you are copying, then once you have copied OpenSim.ini.example to
6;; need to pick an architecture in the [Architecture] section at the end of this file. 7;; OpenSim.ini you will need to pick an architecture in the [Architecture]
8;; section at the end of this file.
7;; 9;;
8;; The settings in this file are in the form "<key> = <value>". For example, save_crashes = false 10;; The settings in this file are in the form "<key> = <value>". For example,
9;; in the [Startup] section below. 11;; save_crashes = false in the [Startup] section below.
10;; 12;;
11;; All settings are initially commented out and the default value used, as found in 13;; All settings are initially commented out and the default value used, as
12;; OpenSimDefaults.ini. To change a setting, first uncomment it by deleting the initial semicolon (;) 14;; found in OpenSimDefaults.ini. To change a setting, first uncomment it by
13;; and then change the value. This will override the value in OpenSimDefaults.ini 15;; deleting the initial semicolon (;) and then change the value. This will
16;; override the value in OpenSimDefaults.ini
14;; 17;;
15;; If you want to find out what configuration OpenSimulator has finished with once all the configuration 18;; If you want to find out what configuration OpenSimulator has finished with
16;; files are loaded then type "config show" on the region console command line. 19;; once all the configuration files are loaded then type "config show" on the
20;; region console command line.
17;; 21;;
18;; 22;;
19;; NOTES FOR DEVELOPERS REGARDING THE FORMAT OF THIS FILE 23;; NOTES FOR DEVELOPERS REGARDING THE FORMAT OF THIS FILE
@@ -26,13 +30,16 @@
26;; formatted as: 30;; formatted as:
27;; {option} {depends on} {question to ask} {choices} default value 31;; {option} {depends on} {question to ask} {choices} default value
28;; Any text comments following the declaration, up to the next blank line. 32;; Any text comments following the declaration, up to the next blank line.
29;; will be copied to the generated file (NOTE: generation is not yet implemented) 33;; will be copied to the generated file (NOTE: generation is not yet
34;; implemented)
35;;
30;; A * in the choices list will allow an empty entry. 36;; A * in the choices list will allow an empty entry.
31;; An empty question will set the default if the dependencies are 37;; An empty question will set the default if the dependencies are
32;; satisfied. 38;; satisfied.
33;; 39;;
34;; ; denotes a commented out option. 40;; ; denotes a commented out option.
35;; Any options added to OpenSim.ini.example should be initially commented out. 41;; Any options added to OpenSim.ini.example should be initially commented
42;; out.
36 43
37 44
38[Startup] 45[Startup]
@@ -47,9 +54,12 @@
47 ;# {save_crashes} {} {Save crashes to disk?} {true false} false 54 ;# {save_crashes} {} {Save crashes to disk?} {true false} false
48 ;; Set this to true if you want to log crashes to disk 55 ;; Set this to true if you want to log crashes to disk
49 ;; this can be useful when submitting bug reports. 56 ;; this can be useful when submitting bug reports.
50 ;; However, this will only log crashes within OpenSimulator that cause the entire program to exit 57 ;; However, this will only log crashes within OpenSimulator that cause the
51 ;; It will not log crashes caused by virtual machine failures, which includes mono and ODE failures. 58 ;; entire program to exit
52 ;; You will need to capture these native stack traces by recording the session log itself. 59 ;; It will not log crashes caused by virtual machine failures, which
60 ;; includes mono and ODE failures.
61 ;; You will need to capture these native stack traces by recording the
62 ;; session log itself.
53 ; save_crashes = false 63 ; save_crashes = false
54 64
55 ;# {crash_dir} {save_crashes:true} {Directory to save crashes to?} {} crashes 65 ;# {crash_dir} {save_crashes:true} {Directory to save crashes to?} {} crashes
@@ -87,23 +97,47 @@
87 ;; from the selected region_info_source. 97 ;; from the selected region_info_source.
88 ; allow_regionless = false 98 ; allow_regionless = false
89 99
100 ;# {NonPhysicalPrimMin} {} {Minimum size of nonphysical prims?} {} 0.001
101 ;; Minimum size for non-physical prims. Affects resizing of existing
102 ;; prims. This can be overriden in the region config file (as
103 ;; NonPhysicalPrimMin!).
104 ; NonPhysicalPrimMin = 0.001
105
90 ;# {NonPhysicalPrimMax} {} {Maximum size of nonphysical prims?} {} 256 106 ;# {NonPhysicalPrimMax} {} {Maximum size of nonphysical prims?} {} 256
91 ;; Maximum size for non-physical prims. Affects resizing of existing prims. This can be overriden in the region config file (as NonphysicalPrimMax!). 107 ;; Maximum size for non-physical prims. Affects resizing of existing
92 ; NonphysicalPrimMax = 256 108 ;; prims. This can be overriden in the region config file (as
109 ;; NonPhysicalPrimMax!).
110 ; NonPhysicalPrimMax = 256
111
112 ;# {PhysicalPrimMin} {} {Minimum size of physical prims?} {} 10
113 ;; Maximum size where a prim can be physical. Affects resizing of
114 ;; existing prims. This can be overriden in the region config file.
115 ; PhysicalPrimMin = 0.01
93 116
94 ;# {PhysicalPrimMax} {} {Maximum size of physical prims?} {} 10 117 ;# {PhysicalPrimMax} {} {Maximum size of physical prims?} {} 10
95 ;; Maximum size where a prim can be physical. Affects resizing of existing prims. This can be overriden in the region config file. 118 ;; Maximum size where a prim can be physical. Affects resizing of
119 ;; existing prims. This can be overriden in the region config file.
96 ; PhysicalPrimMax = 10 120 ; PhysicalPrimMax = 10
97 121
98 ;# {ClampPrimSize} {} {Clamp viewer rezzed prims to max sizes?} {true false} false 122 ;# {ClampPrimSize} {} {Clamp viewer rezzed prims to max sizes?} {true false} false
99 ;; If a viewer attempts to rez a prim larger than the non-physical or physical prim max, clamp the dimensions to the appropriate maximum 123 ;; If a viewer attempts to rez a prim larger than the non-physical or
124 ;; physical prim max, clamp the dimensions to the appropriate maximum
100 ;; This can be overriden in the region config file. 125 ;; This can be overriden in the region config file.
101 ; ClampPrimSize = false 126 ; ClampPrimSize = false
127
128 ;# {LinksetPrims} {} {Max prims an object will hold?} {} 0
129 ;; Maximum number of prims allowable in a linkset. Affects creating new
130 ;; linksets. Ignored if less than or equal to zero.
131 ;; This can be overriden in the region config file.
132 ; LinksetPrims = 0
102 133
103 ;# {AllowScriptCrossing} {} {Allow scripts to cross into this region} {true false} true 134 ;# {AllowScriptCrossing} {} {Allow scripts to cross into this region} {true false} true
104 ;; Allow scripts to keep running when they cross region boundaries, rather than being restarted. State is reloaded on the destination region. 135 ;; Allow scripts to keep running when they cross region boundaries, rather
105 ;; This only applies when crossing to a region running in a different simulator. 136 ;; than being restarted. State is reloaded on the destination region.
106 ;; For crossings where the regions are on the same simulator the script is always kept running. 137 ;; This only applies when crossing to a region running in a different
138 ;; simulator.
139 ;; For crossings where the regions are on the same simulator the script is
140 ;; always kept running.
107 ; AllowScriptCrossing = true 141 ; AllowScriptCrossing = true
108 142
109 ;# {TrustBinaries} {AllowScriptCrossing:true} {Accept compiled binary script code? (DANGEROUS!)} {true false} false 143 ;# {TrustBinaries} {AllowScriptCrossing:true} {Accept compiled binary script code? (DANGEROUS!)} {true false} false
@@ -173,7 +207,8 @@
173 ;# {physics} {} {Select physics engine} {OpenDynamicsEngine BulletSim basicphysics POS} OpenDynamicsEngine 207 ;# {physics} {} {Select physics engine} {OpenDynamicsEngine BulletSim basicphysics POS} OpenDynamicsEngine
174 ;; OpenDynamicsEngine is by some distance the most developed physics engine 208 ;; OpenDynamicsEngine is by some distance the most developed physics engine
175 ;; BulletSim is incomplete and experimental but in active development 209 ;; BulletSim is incomplete and experimental but in active development
176 ;; basicphysics effectively does not model physics at all, making all objects phantom 210 ;; basicphysics effectively does not model physics at all, making all
211 ;; objects phantom
177 ;; Default is OpenDynamicsEngine 212 ;; Default is OpenDynamicsEngine
178 ; physics = OpenDynamicsEngine 213 ; physics = OpenDynamicsEngine
179 ; physics = BulletSim 214 ; physics = BulletSim
@@ -216,8 +251,9 @@
216 ;# {simple_build_permissions} {} {Allow building in parcel by access list (no groups)} {true false} false 251 ;# {simple_build_permissions} {} {Allow building in parcel by access list (no groups)} {true false} false
217 ;; More control over permissions 252 ;; More control over permissions
218 ;; This is definitely not SL! 253 ;; This is definitely not SL!
219 ;; Provides a simple control for land owners to give build rights to specific avatars 254 ;; Provides a simple control for land owners to give build rights to
220 ;; in publicly accessible parcels that disallow object creation in general. 255 ;; specific avatars in publicly accessible parcels that disallow object
256 ;; creation in general.
221 ;; Owners specific avatars by adding them to the Access List of the parcel 257 ;; Owners specific avatars by adding them to the Access List of the parcel
222 ;; without having to use the Groups feature 258 ;; without having to use the Groups feature
223 ; simple_build_permissions = false 259 ; simple_build_permissions = false
@@ -253,11 +289,14 @@
253 ; DrawPrimOnMapTile = true 289 ; DrawPrimOnMapTile = true
254 290
255 ;# {HttpProxy} {} {Proxy URL for llHTTPRequest and dynamic texture loading} {} http://proxy.com:8080 291 ;# {HttpProxy} {} {Proxy URL for llHTTPRequest and dynamic texture loading} {} http://proxy.com:8080
256 ;; Http proxy setting for llHTTPRequest and dynamic texture loading, if required 292 ;; Http proxy setting for llHTTPRequest and dynamic texture loading, if
293 ;; required
257 ; HttpProxy = "http://proxy.com:8080" 294 ; HttpProxy = "http://proxy.com:8080"
258 295
259 ;# {HttpProxyExceptions} {HttpProxy} {Set of regular expressions defining URL that should not be proxied} {} 296 ;# {HttpProxyExceptions} {HttpProxy} {Set of regular expressions defining URL that should not be proxied} {}
260 ;; If you're using HttpProxy, then you can set HttpProxyExceptions to a list of regular expressions for URLs that you don't want to go through the proxy 297 ;; If you're using HttpProxy, then you can set HttpProxyExceptions to a
298 ;; list of regular expressions for URLs that you don't want to go through
299 ;; the proxy.
261 ;; For example, servers inside your firewall. 300 ;; For example, servers inside your firewall.
262 ;; Separate patterns with a ';' 301 ;; Separate patterns with a ';'
263 ; HttpProxyExceptions = ".mydomain.com;localhost" 302 ; HttpProxyExceptions = ".mydomain.com;localhost"
@@ -276,13 +315,15 @@
276 ; SpawnPointRouting = closest 315 ; SpawnPointRouting = closest
277 316
278 ;# {TelehubAllowLandmark} {} {Allow users with landmarks to override telehub routing} {true false} false 317 ;# {TelehubAllowLandmark} {} {Allow users with landmarks to override telehub routing} {true false} false
279 ;; TelehubAllowLandmark allows users with landmarks to override telehub routing and land at the landmark coordinates when set to true 318 ;; TelehubAllowLandmark allows users with landmarks to override telehub
319 ;; routing and land at the landmark coordinates when set to true
280 ;; default is false 320 ;; default is false
281 ; TelehubAllowLandmark = false 321 ; TelehubAllowLandmark = false
282 322
283 ;# {AllowedClients} {} {Bar (|) separated list of allowed clients} {} 323 ;# {AllowedClients} {} {Bar (|) separated list of allowed clients} {}
284 ;; Bar (|) separated list of viewers which may gain access to the regions. 324 ;; Bar (|) separated list of viewers which may gain access to the regions.
285 ;; One can use a substring of the viewer name to enable only certain versions 325 ;; One can use a substring of the viewer name to enable only certain
326 ;; versions
286 ;; Example: Agent uses the viewer "Imprudence 1.3.2.0" 327 ;; Example: Agent uses the viewer "Imprudence 1.3.2.0"
287 ;; - "Imprudence" has access 328 ;; - "Imprudence" has access
288 ;; - "Imprudence 1.3" has access 329 ;; - "Imprudence 1.3" has access
@@ -291,7 +332,8 @@
291 332
292 ;# {BannedClients} {} {Bar (|) separated list of banned clients} {} 333 ;# {BannedClients} {} {Bar (|) separated list of banned clients} {}
293 ;# Bar (|) separated list of viewers which may not gain access to the regions. 334 ;# Bar (|) separated list of viewers which may not gain access to the regions.
294 ;; One can use a Substring of the viewer name to disable only certain versions 335 ;; One can use a Substring of the viewer name to disable only certain
336 ;; versions
295 ;; Example: Agent uses the viewer "Imprudence 1.3.2.0" 337 ;; Example: Agent uses the viewer "Imprudence 1.3.2.0"
296 ;; - "Imprudence" has no access 338 ;; - "Imprudence" has no access
297 ;; - "Imprudence 1.3" has no access 339 ;; - "Imprudence 1.3" has no access
@@ -437,7 +479,8 @@
437[SimulatorFeatures] 479[SimulatorFeatures]
438 480
439 ;# {MapImageServerURI} {} {URL for the map server} {} 481 ;# {MapImageServerURI} {} {URL for the map server} {}
440 ; Experimental new information sent in SimulatorFeatures cap for Kokua viewers 482 ; Experimental new information sent in SimulatorFeatures cap for Kokua
483 ; viewers
441 ; meant to override the MapImage and search server url given at login, and varying 484 ; meant to override the MapImage and search server url given at login, and varying
442 ; on a sim-basis. 485 ; on a sim-basis.
443 ; Viewers that don't understand it, will ignore it 486 ; Viewers that don't understand it, will ignore it
@@ -675,7 +718,9 @@
675 ;; Maximum number of events to queue for a script (excluding timers) 718 ;; Maximum number of events to queue for a script (excluding timers)
676 ; MaxScriptEventQueue = 300 719 ; MaxScriptEventQueue = 300
677 720
678 ;; Stack size per thread created 721 ;; Stack size per script engine thread in bytes.
722 ;; If you are experiencing StackOverflowExceptions you may want to increase this (e.g. double it).
723 ;; The trade-off may be increased memory usage by the script engine.
679 ; ThreadStackSize = 262144 724 ; ThreadStackSize = 262144
680 725
681 ;# {DeleteScriptsOnStartup} {} {Delete previously compiled script DLLs on startup?} (true false) true 726 ;# {DeleteScriptsOnStartup} {} {Delete previously compiled script DLLs on startup?} (true false) true
diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini
index 554aafa..ae5e788 100644
--- a/bin/OpenSimDefaults.ini
+++ b/bin/OpenSimDefaults.ini
@@ -85,8 +85,8 @@
85 ;; from the selected region_info_source. 85 ;; from the selected region_info_source.
86 allow_regionless = false 86 allow_regionless = false
87 87
88 ; Maximum size of non physical prims. Affects resizing of existing prims. This can be overriden in the region config file (as NonphysicalPrimMax!). 88 ; Maximum size of non physical prims. Affects resizing of existing prims. This can be overriden in the region config file (as NonPhysicalPrimMax!).
89 NonphysicalPrimMax = 256 89 NonPhysicalPrimMax = 256
90 90
91 ; Maximum size of physical prims. Affects resizing of existing prims. This can be overriden in the region config file. 91 ; Maximum size of physical prims. Affects resizing of existing prims. This can be overriden in the region config file.
92 PhysicalPrimMax = 10 92 PhysicalPrimMax = 10
@@ -94,6 +94,10 @@
94 ; If a viewer attempts to rez a prim larger than the non-physical or physical prim max, clamp the dimensions to the appropriate maximum 94 ; If a viewer attempts to rez a prim larger than the non-physical or physical prim max, clamp the dimensions to the appropriate maximum
95 ; This can be overriden in the region config file. 95 ; This can be overriden in the region config file.
96 ClampPrimSize = false 96 ClampPrimSize = false
97
98 ; Maximum number of prims allowable in a linkset. Affects creating new linksets. Ignored if less than or equal to zero.
99 ; This can be overriden in the region config file.
100 LinksetPrims = 0
97 101
98 ; Allow scripts to keep running when they cross region boundaries, rather than being restarted. State is reloaded on the destination region. 102 ; Allow scripts to keep running when they cross region boundaries, rather than being restarted. State is reloaded on the destination region.
99 ; This only applies when crossing to a region running in a different simulator. 103 ; This only applies when crossing to a region running in a different simulator.
@@ -419,6 +423,10 @@
419 ; " (Mozilla Compatible)" to the text where there are problems with a web server 423 ; " (Mozilla Compatible)" to the text where there are problems with a web server
420 ;user_agent = "OpenSim LSL (Mozilla Compatible)" 424 ;user_agent = "OpenSim LSL (Mozilla Compatible)"
421 425
426 ; OpenSim can send multiple simultaneous requests for services such as asset
427 ; retrieval. However, some versions of mono appear to hang when there are too
428 ; many simultaneous requests, default is 30 and is currently applied only to assets
429 ;MaxRequestConcurrency = 30
422 430
423[XMLRPC] 431[XMLRPC]
424 ; ## 432 ; ##
@@ -669,8 +677,7 @@
669 ; If true, avatar appearance information is resent to other avatars in the simulator every 60 seconds. 677 ; If true, avatar appearance information is resent to other avatars in the simulator every 60 seconds.
670 ; This may help with some situations where avatars are persistently grey, though it will not help 678 ; This may help with some situations where avatars are persistently grey, though it will not help
671 ; in other situations (e.g. appearance baking failures where the avatar only appears as a cloud to others). 679 ; in other situations (e.g. appearance baking failures where the avatar only appears as a cloud to others).
672 ; This setting is experimental. 680 ResendAppearanceUpdates = true
673 ResendAppearanceUpdates = false
674 681
675 682
676[Attachments] 683[Attachments]
@@ -693,6 +700,24 @@
693 ;LevelUpload = 0 700 ;LevelUpload = 0
694 701
695 702
703[Textures]
704 ; If true, textures generated dynamically (i.e. through osSetDynamicTextureData() and similar OSSL functions) are reused where possible
705 ; Chiefly, reuse occurs if a texture has already been generated with identical data and settings, and that texture contains no dynamic components
706 ; (e.g. images pulled from an external HTTP address).
707 ; Reusing previously generated textures results in a much faster update on the viewer but may cause issues if the viewer didn't receive all resolutions of the texture.
708 ; Currently, it will also increase asset cache use since temporary dynamic textures are no longer deleted.
709 ; Hence, currently considered experimental.
710 ; Default is false.
711 ReuseDynamicTextures = false
712
713 ; If true, then textures generated dynamically that have a low data size relative to their pixel size are not reused
714 ; This is to workaround an apparent LL 3.3.4 and earlier viewer bug where such textures are not redisplayed properly when pulled from the viewer cache.
715 ; Only set this to true if you are sure that all the viewers using your simulator will not suffer from this problem.
716 ; This setting only has an affect is ReuseDynamicTextures = true
717 ; Default is false
718 ReuseDynamicLowDataTextures = false
719
720
696[ODEPhysicsSettings] 721[ODEPhysicsSettings]
697 ; ## 722 ; ##
698 ; ## Physics stats settings 723 ; ## Physics stats settings
@@ -815,6 +840,15 @@
815 ; When the avatar flies, it will be moved up by this amount off the ground (in meters) 840 ; When the avatar flies, it will be moved up by this amount off the ground (in meters)
816 minimum_ground_flight_offset = 3.0 841 minimum_ground_flight_offset = 3.0
817 842
843 ; Plant avatar. This reduces the effect of physical contacts with the avatar.
844 ; If you have a group of unruly and rude visitors that bump each other, turn this on to make that less attractive.
845 ; The avatar still allows a small movement based on the PID settings above. Stronger PID settings AND this active
846 ; will lock the avatar in place
847 av_planted = false
848
849 ; No Avatar Avatar Collissions. This causes avatar to be able to walk through each other as if they're ghosts but still interact with the environment
850 av_av_collisions_off = false
851
818 ; ## 852 ; ##
819 ; ## Object options 853 ; ## Object options
820 ; ## 854 ; ##
@@ -911,10 +945,10 @@
911 MaxPersistantManifoldPoolSize = 0 945 MaxPersistantManifoldPoolSize = 0
912 ShouldDisableContactPoolDynamicAllocation = False 946 ShouldDisableContactPoolDynamicAllocation = False
913 ShouldForceUpdateAllAabbs = False 947 ShouldForceUpdateAllAabbs = False
914 ShouldRandomizeSolverOrder = False 948 ShouldRandomizeSolverOrder = True
915 ShouldSplitSimulationIslands = False 949 ShouldSplitSimulationIslands = True
916 ShouldEnableFrictionCaching = False 950 ShouldEnableFrictionCaching = False
917 NumberOfSolverIterations = 0; 951 NumberOfSolverIterations = 0
918 952
919 ; Linkset constraint parameters 953 ; Linkset constraint parameters
920 LinkConstraintUseFrameOffset = False 954 LinkConstraintUseFrameOffset = False
@@ -931,6 +965,9 @@
931 965
932 ; level of detail for physical meshes. 32,16,8 or 4 with 32 being full detail 966 ; level of detail for physical meshes. 32,16,8 or 4 with 32 being full detail
933 MeshLevelOfDetail = 8 967 MeshLevelOfDetail = 8
968 ; if mesh size is > threshold meters, we need to add more detail because people will notice
969 MeshLevelOfDetailMegaPrimThreshold = 10
970 MeshLevelOfDetailMegaPrim = 16
934 ; number^2 non-physical level of detail of the sculpt texture. 32x32 - 1024 verticies 971 ; number^2 non-physical level of detail of the sculpt texture. 32x32 - 1024 verticies
935 SculptLevelOfDetail = 32 972 SculptLevelOfDetail = 32
936 973
@@ -1009,30 +1046,31 @@
1009 ;default_appearance = default_appearance.xml 1046 ;default_appearance = default_appearance.xml
1010 1047
1011 1048
1012[RestPlugins] 1049; RestPlugins are not currently operational.
1013 ; Change this to true to enable REST Plugins. This must be true if you wish to use 1050;[RestPlugins]
1014 ; REST Region or REST Asset and Inventory Plugins 1051; ; Change this to true to enable REST Plugins. This must be true if you wish to use
1015 enabled = false 1052; ; REST Region or REST Asset and Inventory Plugins
1016 god_key = SECRET 1053; enabled = false
1017 prefix = /admin 1054; god_key = SECRET
1055; prefix = /admin
1018 1056
1019 1057
1020[RestRegionPlugin] 1058;[RestRegionPlugin]
1021 ; Change this to true to enable the REST Region Plugin 1059; ; Change this to true to enable the REST Region Plugin
1022 enabled = false 1060; enabled = false
1023 1061
1024 1062
1025[RestHandler] 1063;[RestHandler]
1026 ; Change this to true to enable the REST Asset and Inventory Plugin 1064; ; Change this to true to enable the REST Asset and Inventory Plugin
1027 enabled = false 1065; enabled = false
1028 authenticate = true 1066; authenticate = true
1029 secured = true 1067; secured = true
1030 extended-escape = true 1068; extended-escape = true
1031 realm = OpenSim REST 1069; realm = OpenSim REST
1032 dump-asset = false 1070; dump-asset = false
1033 path-fill = true 1071; path-fill = true
1034 dump-line-size = 32 1072; dump-line-size = 32
1035 flush-on-error = true 1073; flush-on-error = true
1036 1074
1037 1075
1038; IRC bridge is experimental, so if it breaks... keep both parts... yada yada 1076; IRC bridge is experimental, so if it breaks... keep both parts... yada yada
@@ -1535,6 +1573,11 @@
1535 ;MessagingModule = GroupsMessagingModule 1573 ;MessagingModule = GroupsMessagingModule
1536 ;MessagingEnabled = true 1574 ;MessagingEnabled = true
1537 1575
1576 ; Experimental option to only message cached online users rather than all users
1577 ; Should make large group with few online members messaging faster, as the expense of more calls to ROBUST presence service
1578 ; This currently only applies to the Flotsam XmlRpc backend
1579 MessageOnlineUsersOnly = false
1580
1538 ; Service connectors to the Groups Service. Select one depending on whether you're using a Flotsam XmlRpc backend or a SimianGrid backend 1581 ; Service connectors to the Groups Service. Select one depending on whether you're using a Flotsam XmlRpc backend or a SimianGrid backend
1539 1582
1540 ; SimianGrid Service for Groups 1583 ; SimianGrid Service for Groups
@@ -1560,10 +1603,14 @@
1560 1603
1561 1604
1562[PacketPool] 1605[PacketPool]
1563 ; Enables the experimental packet pool. Yes, we've been here before.
1564 ;RecyclePackets = true; 1606 ;RecyclePackets = true;
1565 ;RecycleDataBlocks = true; 1607 ;RecycleDataBlocks = true;
1566 1608
1609 ; If true, then the basic packet objects used to receive data are also recycled, not just the LLUDP packets.
1610 ; This reduces data churn
1611 ; This setting is currently experimental and defaults to false.
1612 RecycleBaseUDPPackets = false;
1613
1567 1614
1568[InterestManagement] 1615[InterestManagement]
1569 ; This section controls how state updates are prioritized for each client 1616 ; This section controls how state updates are prioritized for each client
@@ -1636,5 +1683,12 @@ Enabled = False
1636 ;; default is module is disabled at the top level 1683 ;; default is module is disabled at the top level
1637 AutoBackupModuleEnabled = false 1684 AutoBackupModuleEnabled = false
1638 1685
1686[Sounds]
1687 ;; {Module} {} {Implementation of ISoundModule to use.} {OpenSim.Region.CoreModules.dll:SoundModule}
1688 Module = OpenSim.Region.CoreModules.dll:SoundModule
1689
1690 ;; {MaxDistance} {} {Cut-off distance at which sounds will not be sent to users} {100.0}
1691 MaxDistance = 100.0
1692
1639[Modules] 1693[Modules]
1640 Include-modules = "addon-modules/*/config/*.ini" 1694 Include-modules = "addon-modules/*/config/*.ini"
diff --git a/bin/Robust.HG.ini.example b/bin/Robust.HG.ini.example
index 3eecdd9..4ecc6b0 100644
--- a/bin/Robust.HG.ini.example
+++ b/bin/Robust.HG.ini.example
@@ -21,7 +21,38 @@
21; * [[<ConfigName>@]<port>/]<dll name>[:<class name>] 21; * [[<ConfigName>@]<port>/]<dll name>[:<class name>]
22; * 22; *
23[Startup] 23[Startup]
24ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003/OpenSim.Server.Handlers.dll:XInventoryInConnector,8004/OpenSim.Server.Handlers.dll:FreeswitchServerConnector,8003/OpenSim.Server.Handlers.dll:GridServiceConnector,8002/OpenSim.Server.Handlers.dll:GridInfoServerInConnector,8003/OpenSim.Server.Handlers.dll:AuthenticationServiceConnector,8002/OpenSim.Server.Handlers.dll:OpenIdServerConnector,8003/OpenSim.Server.Handlers.dll:AvatarServiceConnector,8002/OpenSim.Server.Handlers.dll:LLLoginServiceInConnector,8003/OpenSim.Server.Handlers.dll:PresenceServiceConnector,8003/OpenSim.Server.Handlers.dll:UserAccountServiceConnector,8003/OpenSim.Server.Handlers.dll:GridUserServiceConnector,8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector,8002/OpenSim.Server.Handlers.dll:GatekeeperServiceInConnector,8002/OpenSim.Server.Handlers.dll:UserAgentServerConnector,HGInventoryService@8002/OpenSim.Server.Handlers.dll:XInventoryInConnector,HGAssetService@8002/OpenSim.Server.Handlers.dll:AssetServiceConnector,8002/OpenSim.Server.Handlers.dll:HeloServiceInConnector,8002/OpenSim.Server.Handlers.dll:HGFriendsServerConnector,8002/OpenSim.Server.Handlers.dll:InstantMessageServerConnector,8003/OpenSim.Server.Handlers.dll:MapAddServiceConnector,8002/OpenSim.Server.Handlers.dll:MapGetServiceConnector" 24
25[ServiceList]
26
27AssetServiceConnector = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector"
28InventoryInConnector = "8003/OpenSim.Server.Handlers.dll:XInventoryInConnector"
29VoiceConnector = "8004/OpenSim.Server.Handlers.dll:FreeswitchServerConnector"
30GridServiceConnector = "8003/OpenSim.Server.Handlers.dll:GridServiceConnector"
31GridInfoServerInConnector = "8002/OpenSim.Server.Handlers.dll:GridInfoServerInConnector"
32AuthenticationServiceConnector = "8003/OpenSim.Server.Handlers.dll:AuthenticationServiceConnector"
33OpenIdServerConnector = "8002/OpenSim.Server.Handlers.dll:OpenIdServerConnector"
34AvatarServiceConnector = "8003/OpenSim.Server.Handlers.dll:AvatarServiceConnector"
35LLLoginServiceInConnector = "8002/OpenSim.Server.Handlers.dll:LLLoginServiceInConnector"
36PresenceServiceConnector = "8003/OpenSim.Server.Handlers.dll:PresenceServiceConnector"
37UserAccountServiceConnector = "8003/OpenSim.Server.Handlers.dll:UserAccountServiceConnector"
38GridUserServiceConnector = "8003/OpenSim.Server.Handlers.dll:GridUserServiceConnector"
39FriendsServiceConnector = "8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector"
40MapAddServiceConnector = "8003/OpenSim.Server.Handlers.dll:MapAddServiceConnector"
41MapGetServiceConnector = "8002/OpenSim.Server.Handlers.dll:MapGetServiceConnector"
42
43;; Additions for Hypergrid
44
45GatekeeperServiceInConnector = "8002/OpenSim.Server.Handlers.dll:GatekeeperServiceInConnector"
46UserAgentServerConnector = "8002/OpenSim.Server.Handlers.dll:UserAgentServerConnector"
47HeloServiceInConnector = "8002/OpenSim.Server.Handlers.dll:HeloServiceInConnector"
48HGFriendsServerConnector = "8002/OpenSim.Server.Handlers.dll:HGFriendsServerConnector"
49InstantMessageServerConnector = "8002/OpenSim.Server.Handlers.dll:InstantMessageServerConnector"
50HGInventoryServiceConnector = "HGInventoryService@8002/OpenSim.Server.Handlers.dll:XInventoryInConnector"
51HGAssetServiceConnector = "HGAssetService@8002/OpenSim.Server.Handlers.dll:AssetServiceConnector"
52
53;; Additions for other add-on modules. For example:
54;; WifiServerConnector = "8002/Diva.Wifi.dll:WifiServerConnector"
55
25 56
26; * This is common for all services, it's the network setup for the entire 57; * This is common for all services, it's the network setup for the entire
27; * server instance, if none is specified above 58; * server instance, if none is specified above
@@ -104,6 +135,12 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003
104 ; Region_Welcome_Area = "DefaultRegion, FallbackRegion" 135 ; Region_Welcome_Area = "DefaultRegion, FallbackRegion"
105 ; (replace spaces with underscore) 136 ; (replace spaces with underscore)
106 137
138 ;; Allow Hyperlinks to be created at the console
139 HypergridLinker = true
140
141 Gatekeeper = "http://127.0.0.1:8002"
142
143
107; * This is the configuration for the freeswitch server in grid mode 144; * This is the configuration for the freeswitch server in grid mode
108[FreeswitchService] 145[FreeswitchService]
109 LocalServiceModule = "OpenSim.Services.FreeswitchService.dll:FreeswitchService" 146 LocalServiceModule = "OpenSim.Services.FreeswitchService.dll:FreeswitchService"
@@ -390,6 +427,18 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003
390 ;AllowedClients = "" 427 ;AllowedClients = ""
391 ;DeniedClients = "" 428 ;DeniedClients = ""
392 429
430 ;; Are foreign visitors allowed?
431 ;ForeignAgentsAllowed = true
432 ;;
433 ;; If ForeignAgentsAllowed is true, make exceptions using AllowExcept.
434 ;; Leave blank or commented for no exceptions.
435 ; AllowExcept = "http://griefer.com:8002, http://enemy.com:8002"
436 ;;
437 ;; If ForeignAgentsAllowed is false, make exceptions using DisallowExcept
438 ;; Leave blank or commented for no exceptions.
439 ; DisallowExcept = "http://myfriendgrid.com:8002, http://myboss.com:8002"
440
441
393[UserAgentService] 442[UserAgentService]
394 LocalServiceModule = "OpenSim.Services.HypergridService.dll:UserAgentService" 443 LocalServiceModule = "OpenSim.Services.HypergridService.dll:UserAgentService"
395 ;; for the service 444 ;; for the service
@@ -410,6 +459,24 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003
410 ; User level required to be contacted from other grids 459 ; User level required to be contacted from other grids
411 ;LevelOutsideContacts = 0 460 ;LevelOutsideContacts = 0
412 461
462 ;; Restrictions on destinations of local users.
463 ;; Are local users allowed to visit other grids?
464 ;; What user level? Use variables of this forrm:
465 ;; ForeignTripsAllowed_Level_<UserLevel> = true | false
466 ;; (the default is true)
467 ;; For example:
468 ; ForeignTripsAllowed_Level_0 = false
469 ; ForeignTripsAllowed_Level_200 = true ; true is default, no need to say it
470 ;;
471 ;; If ForeignTripsAllowed is false, make exceptions using DisallowExcept
472 ;; Leave blank or commented for no exceptions.
473 ; DisallowExcept_Level_0 = "http://myothergrid.com:8002, http://boss.com:8002"
474 ;;
475 ;; If ForeignTripsAllowed is true, make exceptions using AllowExcept.
476 ;; Leave blank or commented for no exceptions.
477 ; AllowExcept_Level_200 = "http://griefer.com:8002, http://enemy.com:8002"
478
479
413; * The interface that local users get when they are in other grids. 480; * The interface that local users get when they are in other grids.
414; * This restricts the inventory operations while in other grids. 481; * This restricts the inventory operations while in other grids.
415; * Still not completely safe, especially if users perform inventory operations 482; * Still not completely safe, especially if users perform inventory operations
@@ -418,8 +485,15 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003
418; * 485; *
419[HGInventoryService] 486[HGInventoryService]
420 ; For the InventoryServiceInConnector 487 ; For the InventoryServiceInConnector
421 LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGInventoryService" 488 LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGSuitcaseInventoryService"
489 ;; alternatives:
490 ;; HG1.5, more permissive, not recommended, but still supported
491 ;LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGInventoryService"
492 ;; HG1.0, totally permissive, not recommended, but OK for grids with 100% trust
493 ;LocalServiceModule = "OpenSim.Services.InventoryService.dll:XInventoryService"
494
422 UserAccountsService = "OpenSim.Services.UserAccountService.dll:UserAccountService" 495 UserAccountsService = "OpenSim.Services.UserAccountService.dll:UserAccountService"
496 AvatarService = "OpenSim.Services.AvatarService.dll:AvatarService"
423 HomeURI = "http://127.0.0.1:8002" 497 HomeURI = "http://127.0.0.1:8002"
424 498
425; * The interface that local users get when they are in other grids. 499; * The interface that local users get when they are in other grids.
@@ -431,6 +505,18 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003
431 UserAccountsService = "OpenSim.Services.UserAccountService.dll:UserAccountService" 505 UserAccountsService = "OpenSim.Services.UserAccountService.dll:UserAccountService"
432 HomeURI = "http://127.0.0.1:8002" 506 HomeURI = "http://127.0.0.1:8002"
433 507
508 ;; The asset types that this grid can export to / import from other grids.
509 ;; Comma separated.
510 ;; Valid values are all the asset types in OpenMetaverse.AssetType, namely:
511 ;; Unknown, Texture, Sound, CallingCard, Landmark, Clothing, Object, Notecard, LSLText,
512 ;; LSLBytecode, TextureTGA, Bodypart, SoundWAV, ImageTGA, ImageJPEG, Animation, Gesture, Mesh
513 ;;
514 ;; Leave blank or commented if you don't want to apply any restrictions.
515 ;; A more strict, but still reasonable, policy may be to disallow the exchange
516 ;; of scripts, like so:
517 ; DisallowExport ="LSLText"
518 ; DisallowImport ="LSLBytecode"
519
434[HGFriendsService] 520[HGFriendsService]
435 LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGFriendsService" 521 LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGFriendsService"
436 UserAgentService = "OpenSim.Services.HypergridService.dll:UserAgentService" 522 UserAgentService = "OpenSim.Services.HypergridService.dll:UserAgentService"
diff --git a/bin/Robust.ini.example b/bin/Robust.ini.example
index 5a9d613..7503c5e 100644
--- a/bin/Robust.ini.example
+++ b/bin/Robust.ini.example
@@ -13,7 +13,23 @@
13; * [[<ConfigName>@]<port>/]<dll name>[:<class name>] 13; * [[<ConfigName>@]<port>/]<dll name>[:<class name>]
14; * 14; *
15[Startup] 15[Startup]
16ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003/OpenSim.Server.Handlers.dll:XInventoryInConnector,8004/OpenSim.Server.Handlers.dll:FreeswitchServerConnector,8003/OpenSim.Server.Handlers.dll:GridServiceConnector,8002/OpenSim.Server.Handlers.dll:GridInfoServerInConnector,8003/OpenSim.Server.Handlers.dll:AuthenticationServiceConnector,8002/OpenSim.Server.Handlers.dll:OpenIdServerConnector,8003/OpenSim.Server.Handlers.dll:AvatarServiceConnector,8002/OpenSim.Server.Handlers.dll:LLLoginServiceInConnector,8003/OpenSim.Server.Handlers.dll:PresenceServiceConnector,8003/OpenSim.Server.Handlers.dll:UserAccountServiceConnector,8003/OpenSim.Server.Handlers.dll:GridUserServiceConnector,8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector,8003/OpenSim.Server.Handlers.dll:MapAddServiceConnector,8002/OpenSim.Server.Handlers.dll:MapGetServiceConnector" 16
17[ServiceList]
18AssetServiceConnector = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector"
19InventoryInConnector = "8003/OpenSim.Server.Handlers.dll:XInventoryInConnector"
20VoiceConnector = "8004/OpenSim.Server.Handlers.dll:FreeswitchServerConnector"
21GridServiceConnector = "8003/OpenSim.Server.Handlers.dll:GridServiceConnector"
22GridInfoServerInConnector = "8002/OpenSim.Server.Handlers.dll:GridInfoServerInConnector"
23AuthenticationServiceConnector = "8003/OpenSim.Server.Handlers.dll:AuthenticationServiceConnector"
24OpenIdServerConnector = "8002/OpenSim.Server.Handlers.dll:OpenIdServerConnector"
25AvatarServiceConnector = "8003/OpenSim.Server.Handlers.dll:AvatarServiceConnector"
26LLLoginServiceInConnector = "8002/OpenSim.Server.Handlers.dll:LLLoginServiceInConnector"
27PresenceServiceConnector = "8003/OpenSim.Server.Handlers.dll:PresenceServiceConnector"
28UserAccountServiceConnector = "8003/OpenSim.Server.Handlers.dll:UserAccountServiceConnector"
29GridUserServiceConnector = "8003/OpenSim.Server.Handlers.dll:GridUserServiceConnector"
30FriendsServiceConnector = "8003/OpenSim.Server.Handlers.dll:FriendsServiceConnector"
31MapAddServiceConnector = "8003/OpenSim.Server.Handlers.dll:MapAddServiceConnector"
32MapGetServiceConnector = "8002/OpenSim.Server.Handlers.dll:MapGetServiceConnector"
17 33
18; * This is common for all services, it's the network setup for the entire 34; * This is common for all services, it's the network setup for the entire
19; * server instance, if none is specified above 35; * server instance, if none is specified above
@@ -61,7 +77,19 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003
61 LocalServiceModule = "OpenSim.Services.AssetService.dll:AssetService" 77 LocalServiceModule = "OpenSim.Services.AssetService.dll:AssetService"
62 DefaultAssetLoader = "OpenSim.Framework.AssetLoader.Filesystem.dll" 78 DefaultAssetLoader = "OpenSim.Framework.AssetLoader.Filesystem.dll"
63 AssetLoaderArgs = "./assets/AssetSets.xml" 79 AssetLoaderArgs = "./assets/AssetSets.xml"
64 AllowRemoteDelete = "false" 80
81 ; Allow maptile assets to remotely deleted by remote calls to the asset service.
82 ; There is no harm in having this as false - it just means that historical maptile assets are not deleted.
83 ; This only applies to maptiles served via the version 1 viewer mechanisms
84 ; Default is false
85 AllowRemoteDelete = false
86
87 ; Allow all assets to be remotely deleted.
88 ; Only set this to true if you are operating a grid where you control all calls to the asset service
89 ; (where a necessary condition is that you control all simulators) and you need this for admin purposes.
90 ; If set to true, AllowRemoteDelete = true is required as well.
91 ; Default is false.
92 AllowRemoteDeleteAllTypes = false
65 93
66; * This configuration loads the inventory server modules. It duplicates 94; * This configuration loads the inventory server modules. It duplicates
67; * the function of the legacy inventory server 95; * the function of the legacy inventory server
diff --git a/bin/assets/CollisionSoundsAssetSet/CollisionSoundsAssetSet.xml b/bin/assets/CollisionSoundsAssetSet/CollisionSoundsAssetSet.xml
index 7498ae0..b570c55 100644
--- a/bin/assets/CollisionSoundsAssetSet/CollisionSoundsAssetSet.xml
+++ b/bin/assets/CollisionSoundsAssetSet/CollisionSoundsAssetSet.xml
@@ -303,37 +303,37 @@
303 <Key Name="fileName" Value="snd_TerrainStone.ogg" /> 303 <Key Name="fileName" Value="snd_TerrainStone.ogg" />
304 </Section> 304 </Section>
305 <Section Name="snd_TerrainMetal"> 305 <Section Name="snd_TerrainMetal">
306 <Key Name="assetID" Value="be7295c0-a158-11e1-b3dd-0807200c9a66" /> 306 <Key Name="assetID" Value="be7295c0-a158-11e1-b3dd-0807201c9a66" />
307 <Key Name="name" Value="snd_TerrainMetal" /> 307 <Key Name="name" Value="snd_TerrainMetal" />
308 <Key Name="assetType" Value="1" /> 308 <Key Name="assetType" Value="1" />
309 <Key Name="fileName" Value="snd_TerrainMetal.ogg" /> 309 <Key Name="fileName" Value="snd_TerrainMetal.ogg" />
310 </Section> 310 </Section>
311 <Section Name="snd_TerrainGlass"> 311 <Section Name="snd_TerrainGlass">
312 <Key Name="assetID" Value="be7295c0-a158-11e1-b3dd-0807200c9a66" /> 312 <Key Name="assetID" Value="be7295c0-a158-11e1-b3dd-0807202c9a66" />
313 <Key Name="name" Value="snd_TerrainGlass" /> 313 <Key Name="name" Value="snd_TerrainGlass" />
314 <Key Name="assetType" Value="1" /> 314 <Key Name="assetType" Value="1" />
315 <Key Name="fileName" Value="snd_TerrainGlass.ogg" /> 315 <Key Name="fileName" Value="snd_TerrainGlass.ogg" />
316 </Section> 316 </Section>
317 <Section Name="snd_TerrainWood"> 317 <Section Name="snd_TerrainWood">
318 <Key Name="assetID" Value="be7295c0-a158-11e1-b3dd-0807200c9a66" /> 318 <Key Name="assetID" Value="be7295c0-a158-11e1-b3dd-0807203c9a66" />
319 <Key Name="name" Value="snd_TerrainWood" /> 319 <Key Name="name" Value="snd_TerrainWood" />
320 <Key Name="assetType" Value="1" /> 320 <Key Name="assetType" Value="1" />
321 <Key Name="fileName" Value="snd_TerrainWood.ogg" /> 321 <Key Name="fileName" Value="snd_TerrainWood.ogg" />
322 </Section> 322 </Section>
323 <Section Name="snd_TerrainFlesh"> 323 <Section Name="snd_TerrainFlesh">
324 <Key Name="assetID" Value="be7295c0-a158-11e1-b3dd-0807200c9a66" /> 324 <Key Name="assetID" Value="be7295c0-a158-11e1-b3dd-0807204c9a66" />
325 <Key Name="name" Value="snd_TerrainFlesh" /> 325 <Key Name="name" Value="snd_TerrainFlesh" />
326 <Key Name="assetType" Value="1" /> 326 <Key Name="assetType" Value="1" />
327 <Key Name="fileName" Value="snd_TerrainFlesh.ogg" /> 327 <Key Name="fileName" Value="snd_TerrainFlesh.ogg" />
328 </Section> 328 </Section>
329 <Section Name="snd_TerrainPlastic"> 329 <Section Name="snd_TerrainPlastic">
330 <Key Name="assetID" Value="be7295c0-a158-11e1-b3dd-0807200c9a66" /> 330 <Key Name="assetID" Value="be7295c0-a158-11e1-b3dd-0807205c9a66" />
331 <Key Name="name" Value="snd_TerrainPlastic" /> 331 <Key Name="name" Value="snd_TerrainPlastic" />
332 <Key Name="assetType" Value="1" /> 332 <Key Name="assetType" Value="1" />
333 <Key Name="fileName" Value="snd_TerrainPlastic.ogg" /> 333 <Key Name="fileName" Value="snd_TerrainPlastic.ogg" />
334 </Section> 334 </Section>
335 <Section Name="snd_TerrainRubber"> 335 <Section Name="snd_TerrainRubber">
336 <Key Name="assetID" Value="be7295c0-a158-11e1-b3dd-0807200c9a66" /> 336 <Key Name="assetID" Value="be7295c0-a158-11e1-b3dd-0807206c9a66" />
337 <Key Name="name" Value="snd_TerrainRubber" /> 337 <Key Name="name" Value="snd_TerrainRubber" />
338 <Key Name="assetType" Value="1" /> 338 <Key Name="assetType" Value="1" />
339 <Key Name="fileName" Value="snd_TerrainRubber.ogg" /> 339 <Key Name="fileName" Value="snd_TerrainRubber.ogg" />
diff --git a/bin/config-include/FlotsamCache.ini.example b/bin/config-include/FlotsamCache.ini.example
index b9c6d84..ad74fc1 100644
--- a/bin/config-include/FlotsamCache.ini.example
+++ b/bin/config-include/FlotsamCache.ini.example
@@ -54,10 +54,3 @@
54 54
55 ; Warning level for cache directory size 55 ; Warning level for cache directory size
56 ;CacheWarnAt = 30000 56 ;CacheWarnAt = 30000
57
58 ; Perform a deep scan of all assets within all regions, looking for all assets
59 ; present or referenced. Mark all assets found that are already present in the
60 ; cache, and request all assets that are found that are not already cached (this
61 ; will cause those assets to be cached)
62 ;
63 DeepScanBeforePurge = true
diff --git a/bin/config-include/GridCommon.ini.example b/bin/config-include/GridCommon.ini.example
index 8d7f6fc..79f7ed6 100644
--- a/bin/config-include/GridCommon.ini.example
+++ b/bin/config-include/GridCommon.ini.example
@@ -137,6 +137,26 @@
137 ;; uncomment the next line. You may want to do this on sims that have licensed content. 137 ;; uncomment the next line. You may want to do this on sims that have licensed content.
138 ; OutboundPermission = False 138 ; OutboundPermission = False
139 139
140[HGAssetService]
141 ;
142 ; === HG ONLY ===
143 ; Change this to your server
144 ; accessible from other grids
145 ;
146 HomeURI = "http://mygridserver.com:8002"
147
148 ;; The asset types that this grid can export to / import from other grids.
149 ;; Comma separated.
150 ;; Valid values are all the asset types in OpenMetaverse.AssetType, namely:
151 ;; Unknown, Texture, Sound, CallingCard, Landmark, Clothing, Object, Notecard, LSLText,
152 ;; LSLBytecode, TextureTGA, Bodypart, SoundWAV, ImageTGA, ImageJPEG, Animation, Gesture, Mesh
153 ;;
154 ;; Leave blank or commented if you don't want to apply any restrictions.
155 ;; A more strict, but still reasonable, policy may be to disallow the exchange
156 ;; of scripts, like so:
157 ; DisallowExport ="LSLText"
158 ; DisallowImport ="LSLBytecode"
159
140[HGFriendsModule] 160[HGFriendsModule]
141 ; User level required to be able to send friendship invitations to foreign users 161 ; User level required to be able to send friendship invitations to foreign users
142 ;LevelHGFriends = 0; 162 ;LevelHGFriends = 0;
diff --git a/bin/config-include/StandaloneCommon.ini.example b/bin/config-include/StandaloneCommon.ini.example
index e4bc548..f28de43 100644
--- a/bin/config-include/StandaloneCommon.ini.example
+++ b/bin/config-include/StandaloneCommon.ini.example
@@ -47,23 +47,6 @@
47 DefaultAssetLoader = "OpenSim.Framework.AssetLoader.Filesystem.dll" 47 DefaultAssetLoader = "OpenSim.Framework.AssetLoader.Filesystem.dll"
48 AssetLoaderArgs = "assets/AssetSets.xml" 48 AssetLoaderArgs = "assets/AssetSets.xml"
49 49
50[HGInventoryService]
51 HomeURI = "http://127.0.0.1:9000"
52
53[HGAssetService]
54 HomeURI = "http://127.0.0.1:9000"
55
56[HGInventoryAccessModule]
57 HomeURI = "http://127.0.0.1:9000"
58 Gatekeeper = "http://127.0.0.1:9000"
59
60 ;; If you want to protect your assets from being copied by foreign visitors
61 ;; uncomment the next line. You may want to do this on sims that have licensed content.
62 ; OutboundPermission = False
63
64[HGFriendsModule]
65 ; User level required to be able to send friendship invitations to foreign users
66 ;LevelHGFriends = 0;
67 50
68[GridService] 51[GridService]
69 ;; For in-memory region storage (default) 52 ;; For in-memory region storage (default)
@@ -84,11 +67,6 @@
84 ;; change this to the address of your simulator 67 ;; change this to the address of your simulator
85 Gatekeeper="http://127.0.0.1:9000" 68 Gatekeeper="http://127.0.0.1:9000"
86 69
87[Messaging]
88 ; === HG ONLY ===
89 ;; change this to the address of your simulator
90 Gatekeeper = "http://127.0.0.1:9000"
91
92[LibraryModule] 70[LibraryModule]
93 ; Set this if you want to change the name of the OpenSim Library 71 ; Set this if you want to change the name of the OpenSim Library
94 ;LibraryName = "My World's Library" 72 ;LibraryName = "My World's Library"
@@ -127,32 +105,6 @@
127 ;AllowedClients = "" 105 ;AllowedClients = ""
128 ;DeniedClients = "" 106 ;DeniedClients = ""
129 107
130[GatekeeperService]
131 ExternalName = "http://127.0.0.1:9000"
132
133 ; Does this grid allow incoming links to any region in it?
134 ; If false, HG TPs happen only to the Default regions specified in [GridService] section
135 AllowTeleportsToAnyRegion = true
136
137 ;; Regular expressions for controlling which client versions are accepted/denied.
138 ;; An empty string means nothing is checked.
139 ;;
140 ;; Example 1: allow only these 3 types of clients (any version of them)
141 ;; AllowedClients = "Imprudence|Hippo|Second Life"
142 ;;
143 ;; Example 2: allow all clients except these
144 ;; DeniedClients = "Twisted|Crawler|Cryolife|FuckLife|StreetLife|GreenLife|AntiLife|KORE-Phaze|Synlyfe|Purple Second Life|SecondLi |Emerald"
145 ;;
146 ;; Note that these are regular expressions, so every character counts.
147 ;; Also note that this is very weak security and should not be trusted as a reliable means
148 ;; for keeping bad clients out; modified clients can fake their identifiers.
149 ;;
150 ;;
151 ;AllowedClients = ""
152 ;DeniedClients = ""
153
154 ;; Are foreign visitors allowed
155 ;ForeignAgentsAllowed = true
156 108
157[FreeswitchService] 109[FreeswitchService]
158 ;; If FreeSWITCH is not being used then you don't need to set any of these parameters 110 ;; If FreeSWITCH is not being used then you don't need to set any of these parameters
@@ -257,6 +209,115 @@
257 ; Example: 209 ; Example:
258 ; Region_Test_1 = "DisallowForeigners" 210 ; Region_Test_1 = "DisallowForeigners"
259 211
212;;
213;; HG configurations
214;;
215[GatekeeperService]
216 ExternalName = "http://127.0.0.1:9000"
217
218 ; Does this grid allow incoming links to any region in it?
219 ; If false, HG TPs happen only to the Default regions specified in [GridService] section
220 AllowTeleportsToAnyRegion = true
221
222 ;; Regular expressions for controlling which client versions are accepted/denied.
223 ;; An empty string means nothing is checked.
224 ;;
225 ;; Example 1: allow only these 3 types of clients (any version of them)
226 ;; AllowedClients = "Imprudence|Hippo|Second Life"
227 ;;
228 ;; Example 2: allow all clients except these
229 ;; DeniedClients = "Twisted|Crawler|Cryolife|FuckLife|StreetLife|GreenLife|AntiLife|KORE-Phaze|Synlyfe|Purple Second Life|SecondLi |Emerald"
230 ;;
231 ;; Note that these are regular expressions, so every character counts.
232 ;; Also note that this is very weak security and should not be trusted as a reliable means
233 ;; for keeping bad clients out; modified clients can fake their identifiers.
234 ;;
235 ;;
236 ;AllowedClients = ""
237 ;DeniedClients = ""
238
239 ;; Are foreign visitors allowed?
240 ;ForeignAgentsAllowed = true
241 ;;
242 ;; If ForeignAgentsAllowed is true, make exceptions using AllowExcept.
243 ;; Leave blank or commented for no exceptions.
244 ; AllowExcept = "http://griefer.com:8002, http://enemy.com:8002"
245 ;;
246 ;; If ForeignAgentsAllowed is false, make exceptions using DisallowExcept
247 ;; Leave blank or commented for no exceptions.
248 ; DisallowExcept = "http://myfriendgrid.com:8002, http://myboss.com:8002"
249
260[UserAgentService] 250[UserAgentService]
261 ; User level required to be contacted from other grids 251 ;; User level required to be contacted from other grids
262 ;LevelOutsideContacts = 0 252 ;LevelOutsideContacts = 0
253
254 ;; Restrictions on destinations of local users.
255 ;; Are local users allowed to visit other grids?
256 ;; What user level? Use variables of this forrm:
257 ;; ForeignTripsAllowed_Level_<UserLevel> = true | false
258 ;; (the default is true)
259 ;; For example:
260 ; ForeignTripsAllowed_Level_0 = false
261 ; ForeignTripsAllowed_Level_200 = true ; true is default, no need to say it
262 ;;
263 ;; If ForeignTripsAllowed is false, make exceptions using DisallowExcept
264 ;; Leave blank or commented for no exceptions.
265 ; DisallowExcept_Level_0 = "http://myothergrid.com:8002, http://boss.com:8002"
266 ;;
267 ;; If ForeignTripsAllowed is true, make exceptions using AllowExcept.
268 ;; Leave blank or commented for no exceptions.
269 ; AllowExcept_Level_200 = "http://griefer.com:8002, http://enemy.com:8002"
270
271[HGInventoryService]
272 HomeURI = "http://127.0.0.1:9000"
273
274[HGAssetService]
275 HomeURI = "http://127.0.0.1:9000"
276
277 ;; The asset types that this grid can export to / import from other grids.
278 ;; Comma separated.
279 ;; Valid values are all the asset types in OpenMetaverse.AssetType, namely:
280 ;; Unknown, Texture, Sound, CallingCard, Landmark, Clothing, Object, Notecard, LSLText,
281 ;; LSLBytecode, TextureTGA, Bodypart, SoundWAV, ImageTGA, ImageJPEG, Animation, Gesture, Mesh
282 ;;
283 ;; Leave blank or commented if you don't want to apply any restrictions.
284 ;; A more strict, but still reasonable, policy may be to disallow the exchange
285 ;; of scripts, like so:
286 ; DisallowExport ="LSLText"
287 ; DisallowImport ="LSLBytecode"
288
289
290[HGInventoryAccessModule]
291 HomeURI = "http://127.0.0.1:9000"
292 Gatekeeper = "http://127.0.0.1:9000"
293
294 ;; If you want to protect your assets from being copied by foreign visitors
295 ;; uncomment the next line. You may want to do this on sims that have licensed content.
296 ;; true = allow exports, false = disallow exports. True by default.
297 ; OutboundPermission = True
298
299 ;; Send visual reminder to local users that their inventories are unavailable while they are traveling
300 ;; and available when they return. True by default.
301 ;RestrictInventoryAccessAbroad = True
302
303[HGFriendsModule]
304 ; User level required to be able to send friendship invitations to foreign users
305 ;LevelHGFriends = 0;
306
307[Messaging]
308 ; === HG ONLY ===
309 ;; change this to the address of your simulator
310 Gatekeeper = "http://127.0.0.1:9000"
311
312
313[EntityTransfer]
314 ;; User level from which local users are allowed to HG teleport. Default 0 (all users)
315 ;LevelHGTeleport = 0
316
317 ;; Are local users restricted from taking their appearance abroad?
318 ;; Default is no restrictions
319 ;RestrictAppearanceAbroad = false
320
321 ;; If appearance is restricted, which accounts' appearances are allowed to be exported?
322 ;; Comma-separated list of account names
323 AccountForAppearance = "Test User, Astronaut Smith"
diff --git a/bin/config-include/StandaloneHypergrid.ini b/bin/config-include/StandaloneHypergrid.ini
index 75c4788..195e780 100644
--- a/bin/config-include/StandaloneHypergrid.ini
+++ b/bin/config-include/StandaloneHypergrid.ini
@@ -36,8 +36,6 @@
36 SimulationServiceInConnector = true 36 SimulationServiceInConnector = true
37 MapImageServiceInConnector = true 37 MapImageServiceInConnector = true
38 38
39[Profile]
40 Module = "BasicProfileModule"
41 39
42[Messaging] 40[Messaging]
43 MessageTransferModule = HGMessageTransferModule 41 MessageTransferModule = HGMessageTransferModule
@@ -97,6 +95,10 @@
97 GridUserService = "OpenSim.Services.UserAccountService.dll:GridUserService" 95 GridUserService = "OpenSim.Services.UserAccountService.dll:GridUserService"
98 GridService = "OpenSim.Services.GridService.dll:GridService" 96 GridService = "OpenSim.Services.GridService.dll:GridService"
99 InventoryService = "OpenSim.Services.InventoryService.dll:XInventoryService" 97 InventoryService = "OpenSim.Services.InventoryService.dll:XInventoryService"
98 AvatarService = "OpenSim.Services.AvatarService.dll:AvatarService"
99
100 ;; This switch creates the minimum set of body parts and avatar entries for a viewer 2 to show a default "Ruth" avatar rather than a cloud.
101 CreateDefaultAvatarEntries = true
100 102
101[GridUserService] 103[GridUserService]
102 LocalServiceModule = "OpenSim.Services.UserAccountService.dll:GridUserService" 104 LocalServiceModule = "OpenSim.Services.UserAccountService.dll:GridUserService"
@@ -128,6 +130,7 @@
128 LocalServiceModule = "OpenSim.Services.HypergridService.dll:GatekeeperService" 130 LocalServiceModule = "OpenSim.Services.HypergridService.dll:GatekeeperService"
129 ;; for the service 131 ;; for the service
130 UserAccountService = "OpenSim.Services.UserAccountService.dll:UserAccountService" 132 UserAccountService = "OpenSim.Services.UserAccountService.dll:UserAccountService"
133 GridUserService = "OpenSim.Services.UserAccountService.dll:GridUserService"
131 UserAgentService = "OpenSim.Services.HypergridService.dll:UserAgentService" 134 UserAgentService = "OpenSim.Services.HypergridService.dll:UserAgentService"
132 PresenceService = "OpenSim.Services.PresenceService.dll:PresenceService" 135 PresenceService = "OpenSim.Services.PresenceService.dll:PresenceService"
133 GridService = "OpenSim.Services.GridService.dll:GridService" 136 GridService = "OpenSim.Services.GridService.dll:GridService"
@@ -149,8 +152,15 @@
149;; This greatly restricts the inventory operations while in other grids 152;; This greatly restricts the inventory operations while in other grids
150[HGInventoryService] 153[HGInventoryService]
151 ; For the InventoryServiceInConnector 154 ; For the InventoryServiceInConnector
152 LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGInventoryService" 155 LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGSuitcaseInventoryService"
156 ;; alternatives:
157 ;; HG1.5, more permissive, not recommended, but still supported
158 ;LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGInventoryService"
159 ;; HG1.0, totally permissive, not recommended, but OK for grids with 100% trust
160 ;LocalServiceModule = "OpenSim.Services.InventoryService.dll:XInventoryService"
161
153 UserAccountsService = "OpenSim.Services.UserAccountService.dll:UserAccountService" 162 UserAccountsService = "OpenSim.Services.UserAccountService.dll:UserAccountService"
163 AvatarService = "OpenSim.Services.AvatarService.dll:AvatarService"
154 164
155;; The interface that local users get when they are in other grids 165;; The interface that local users get when they are in other grids
156;; This restricts/filters the asset operations from the outside 166;; This restricts/filters the asset operations from the outside
diff --git a/bin/config-include/storage/SQLiteStandalone.ini b/bin/config-include/storage/SQLiteStandalone.ini
index c1de71a..67d98ff 100644
--- a/bin/config-include/storage/SQLiteStandalone.ini
+++ b/bin/config-include/storage/SQLiteStandalone.ini
@@ -7,6 +7,16 @@
7[AssetService] 7[AssetService]
8 ConnectionString = "URI=file:Asset.db,version=3" 8 ConnectionString = "URI=file:Asset.db,version=3"
9 9
10; The HGAssetService section controls the connection given to the AssetService in a Hypergrid configuration.
11; This has to be separate from [AssetService] because the Hypergrid facing connector uses [HGAssetService] for its config data instead.
12; However, the internal asset service will still use the [AssetService] section.
13; Therefore, you will almost certainly want the ConnectionString in [HGAssetService] to be the same as in [AssetService]
14; so that they both access the same database.
15; This issue does not apply to normal MySQL/MSSQL configurations, since by default they use the settings in [DatabaseService] and
16; do not have separate connection strings for different services.
17[HGAssetService]
18 ConnectionString = "URI=file:Asset.db,version=3"
19
10[InventoryService] 20[InventoryService]
11 ;ConnectionString = "URI=file:inventory.db,version=3" 21 ;ConnectionString = "URI=file:inventory.db,version=3"
12 ; if you have a legacy inventory store use the connection string below 22 ; if you have a legacy inventory store use the connection string below
diff --git a/bin/lib32/BulletSim.dll b/bin/lib32/BulletSim.dll
index 0f2d522..fbc83e6 100755
--- a/bin/lib32/BulletSim.dll
+++ b/bin/lib32/BulletSim.dll
Binary files differ
diff --git a/bin/lib32/libBulletSim.so b/bin/lib32/libBulletSim.so
index 783c9a2..65d3805 100755
--- a/bin/lib32/libBulletSim.so
+++ b/bin/lib32/libBulletSim.so
Binary files differ
diff --git a/bin/lib32/libopenjpeg-dotnet-2.1.3.0-dotnet-1-i686.so b/bin/lib32/libopenjpeg-dotnet-2.1.3.0-dotnet-1-i686.so
deleted file mode 100644
index 0106b56..0000000
--- a/bin/lib32/libopenjpeg-dotnet-2.1.3.0-dotnet-1-i686.so
+++ /dev/null
Binary files differ
diff --git a/bin/lib32/libopenjpeg-dotnet-2.1.3.0-dotnet-1.so b/bin/lib32/libopenjpeg-dotnet-2.1.3.0-dotnet-1.so
deleted file mode 100644
index 53543e7..0000000
--- a/bin/lib32/libopenjpeg-dotnet-2.1.3.0-dotnet-1.so
+++ /dev/null
Binary files differ
diff --git a/bin/lib32/libopenjpeg-dotnet.so b/bin/lib32/libopenjpeg-dotnet.so
new file mode 100755
index 0000000..193eca4
--- /dev/null
+++ b/bin/lib32/libopenjpeg-dotnet.so
Binary files differ
diff --git a/bin/lib64/BulletSim.dll b/bin/lib64/BulletSim.dll
index c2a2bda..936368a 100755
--- a/bin/lib64/BulletSim.dll
+++ b/bin/lib64/BulletSim.dll
Binary files differ
diff --git a/bin/lib64/libBulletSim.so b/bin/lib64/libBulletSim.so
index 74d4f98..82fbad6 100755
--- a/bin/lib64/libBulletSim.so
+++ b/bin/lib64/libBulletSim.so
Binary files differ
diff --git a/bin/lib64/libopenjpeg-dotnet-2.1.3.0-dotnet-1-x86_64.so b/bin/lib64/libopenjpeg-dotnet-2.1.3.0-dotnet-1-x86_64.so
deleted file mode 100644
index be11bb4..0000000
--- a/bin/lib64/libopenjpeg-dotnet-2.1.3.0-dotnet-1-x86_64.so
+++ /dev/null
Binary files differ
diff --git a/bin/lib64/libopenjpeg-dotnet-2.1.3.0-dotnet-1.dylib b/bin/lib64/libopenjpeg-dotnet-2.1.3.0-dotnet-1.dylib
deleted file mode 100644
index dc50775..0000000
--- a/bin/lib64/libopenjpeg-dotnet-2.1.3.0-dotnet-1.dylib
+++ /dev/null
Binary files differ
diff --git a/bin/lib64/libopenjpeg-dotnet-x86_64.so b/bin/lib64/libopenjpeg-dotnet-x86_64.so
new file mode 100755
index 0000000..7a9bdfc
--- /dev/null
+++ b/bin/lib64/libopenjpeg-dotnet-x86_64.so
Binary files differ
diff --git a/bin/lib64/libopenjpeg-dotnet.dylib b/bin/lib64/libopenjpeg-dotnet.dylib
new file mode 100755
index 0000000..91f7264
--- /dev/null
+++ b/bin/lib64/libopenjpeg-dotnet.dylib
Binary files differ
diff --git a/bin/openjpeg-dotnet-x86_64.dll b/bin/openjpeg-dotnet-x86_64.dll
index 97729ff..9e8cd21 100755
--- a/bin/openjpeg-dotnet-x86_64.dll
+++ b/bin/openjpeg-dotnet-x86_64.dll
Binary files differ
diff --git a/bin/openjpeg-dotnet.dll b/bin/openjpeg-dotnet.dll
index 64b2557..6377b8d 100755
--- a/bin/openjpeg-dotnet.dll
+++ b/bin/openjpeg-dotnet.dll
Binary files differ
diff --git a/bin/openmetaverse_data/avatar_lad.xml b/bin/openmetaverse_data/avatar_lad.xml
new file mode 100644
index 0000000..3bd7ba7
--- /dev/null
+++ b/bin/openmetaverse_data/avatar_lad.xml
@@ -0,0 +1,12308 @@
1<?xml version="1.0" encoding="US-ASCII" standalone="yes"?>
2<linden_avatar
3 version="1.0" wearable_definition_version="22">
4 <!-- The wearable_definition_version is checked during asset upload. -->
5 <!-- If you increment it, check indra/lib/python/indra/assetutil.py. -->
6 <skeleton
7 file_name="avatar_skeleton.xml">
8 <attachment_point
9 id="1"
10 group="6"
11 pie_slice="2"
12 name="Chest"
13 joint="mChest"
14 position="0.15 0 -0.1"
15 rotation="0 90 90"
16 visible_in_first_person="true" />
17
18 <attachment_point
19 id="2"
20 group="2"
21 pie_slice="2"
22 name="Skull"
23 joint="mHead"
24 position="0 0 0.15"
25 rotation="0 0 90"
26 visible_in_first_person="false" />
27
28 <attachment_point
29 id="3"
30 group="3"
31 pie_slice="3"
32 name="Left Shoulder"
33 joint="mCollarLeft"
34 position="0 0 0.08"
35 rotation="0 0 0"
36 visible_in_first_person="true" />
37
38 <attachment_point
39 id="4"
40 group="1"
41 pie_slice="1"
42 name="Right Shoulder"
43 joint="mCollarRight"
44 position="0 0 0.08"
45 rotation="0 0 0"
46 visible_in_first_person="true"/>
47
48 <attachment_point
49 id="5"
50 group="4"
51 name="Left Hand"
52 joint="mWristLeft"
53 position="0 0.08 -0.02"
54 rotation="0 0 0"
55 visible_in_first_person="true"
56 max_attachment_offset="1.5" />
57
58 <attachment_point
59 id="6"
60 group="0"
61 name="Right Hand"
62 joint="mWristRight"
63 position="0 -0.08 -0.02"
64 rotation="0 0 0"
65 visible_in_first_person="true"
66 max_attachment_offset="1.5" />
67
68 <attachment_point
69 id="7"
70 group="5"
71 pie_slice="6"
72 name="Left Foot"
73 joint="mFootLeft"
74 position="0 0.0 0.0"
75 rotation="0 0 0"
76 visible_in_first_person="true"/>
77
78 <attachment_point
79 id="8"
80 group="7"
81 pie_slice="6"
82 name="Right Foot"
83 joint="mFootRight"
84 position="0 0.0 0.0"
85 rotation="0 0 0"
86 visible_in_first_person="true"/>
87
88 <attachment_point
89 id="9"
90 group="6"
91 pie_slice="7"
92 name="Spine"
93 joint="mChest"
94 position="-0.15 0 -0.1"
95 rotation="0 -90 90"
96 visible_in_first_person="true" />
97
98 <attachment_point
99 id="10"
100 group="6"
101 pie_slice="6"
102 name="Pelvis"
103 joint="mPelvis"
104 position="0 0 -0.15"
105 rotation="0 0 0"
106 visible_in_first_person="true" />
107
108 <attachment_point
109 id="11"
110 group="2"
111 pie_slice="6"
112 name="Mouth"
113 joint="mHead"
114 position="0.12 0 0.001"
115 rotation="0 0 0"
116 visible_in_first_person="false"/>
117
118 <attachment_point
119 id="12"
120 group="2"
121 pie_slice="7"
122 name="Chin"
123 joint="mHead"
124 position="0.12 0 -0.04"
125 rotation="0 0 0"
126 visible_in_first_person="false" />
127
128 <attachment_point
129 id="13"
130 group="2"
131 pie_slice="4"
132 name="Left Ear"
133 joint="mHead"
134 position="0.015 0.08 0.017"
135 rotation="0 0 0"
136 visible_in_first_person="false" />
137
138 <attachment_point
139 id="14"
140 group="2"
141 pie_slice="0"
142 name="Right Ear"
143 joint="mHead"
144 position="0.015 -0.08 0.017"
145 rotation="0 0 0"
146 visible_in_first_person="false" />
147
148 <attachment_point
149 id="15"
150 group="2"
151 pie_slice="3"
152 name="Left Eyeball"
153 joint="mEyeLeft"
154 position="0 0 0"
155 rotation="0 0 0"
156 visible_in_first_person="false"/>
157
158 <attachment_point
159 id="16"
160 group="2"
161 pie_slice="1"
162 name="Right Eyeball"
163 joint="mEyeRight"
164 position="0 0 0"
165 rotation="0 0 0"
166 visible_in_first_person="false" />
167
168 <attachment_point
169 id="17"
170 group="2"
171 pie_slice="5"
172 name="Nose"
173 joint="mHead"
174 position="0.1 0 0.05"
175 rotation="0 0 0"
176 visible_in_first_person="false"/>
177
178 <attachment_point
179 id="18"
180 group="1"
181 pie_slice="0"
182 name="R Upper Arm"
183 joint="mShoulderRight"
184 position="0.01 -0.13 0.01"
185 rotation="0 0 0"
186 visible_in_first_person="true" />
187
188 <attachment_point
189 id="19"
190 group="1"
191 pie_slice="7"
192 name="R Forearm"
193 joint="mElbowRight"
194 position="0 -0.12 0"
195 rotation="0 0 0"
196 visible_in_first_person="true"/>
197
198 <attachment_point
199 id="20"
200 group="3"
201 pie_slice="4"
202 name="L Upper Arm"
203 joint="mShoulderLeft"
204 position="0.01 0.15 -0.01"
205 rotation="0 0 0"
206 visible_in_first_person="true" />
207
208 <attachment_point
209 id="21"
210 group="3"
211 pie_slice="5"
212 name="L Forearm"
213 joint="mElbowLeft"
214 position="0 0.113 0"
215 rotation="0 0 0"
216 visible_in_first_person="true" />
217
218 <attachment_point
219 id="22"
220 group="7"
221 pie_slice="1"
222 name="Right Hip"
223 joint="mHipRight"
224 position="0 0 0"
225 rotation="0 0 0"
226 visible_in_first_person="true" />
227
228 <attachment_point
229 id="23"
230 group="7"
231 pie_slice="0"
232 name="R Upper Leg"
233 joint="mHipRight"
234 position="-0.017 0.041 -0.310"
235 rotation="0 0 0"
236 visible_in_first_person="true" />
237
238 <attachment_point
239 id="24"
240 group="7"
241 pie_slice="7"
242 name="R Lower Leg"
243 joint="mKneeRight"
244 position="-0.044 -0.007 -0.262"
245 rotation="0 0 0"
246 visible_in_first_person="true" />
247
248 <attachment_point
249 id="25"
250 group="5"
251 pie_slice="3"
252 name="Left Hip"
253 joint="mHipLeft"
254 position="0 0 0"
255 rotation="0 0 0"
256 visible_in_first_person="true" />
257
258 <attachment_point
259 id="26"
260 group="5"
261 pie_slice="4"
262 name="L Upper Leg"
263 joint="mHipLeft"
264 position="-0.019 -0.034 -0.310"
265 rotation="0 0 0"
266 visible_in_first_person="true"/>
267
268 <attachment_point
269 id="27"
270 group="5"
271 pie_slice="5"
272 name="L Lower Leg"
273 joint="mKneeLeft"
274 position="-0.044 -0.007 -0.261"
275 rotation="0 0 0"
276 visible_in_first_person="true" />
277
278 <attachment_point
279 id="28"
280 group="6"
281 pie_slice="5"
282 name="Stomach"
283 joint="mPelvis"
284 position="0.092 0.0 0.088"
285 rotation="0 0 0"
286 visible_in_first_person="true" />
287
288 <attachment_point
289 id="29"
290 group="6"
291 pie_slice="3"
292 name="Left Pec"
293 joint="mTorso"
294 position="0.104 0.082 0.247"
295 rotation="0 0 0"
296 visible_in_first_person="true" />
297
298 <attachment_point
299 id="30"
300 group="6"
301 pie_slice="1"
302 name="Right Pec"
303 joint="mTorso"
304 position="0.104 -0.082 0.247"
305 rotation="0 0 0"
306 visible_in_first_person="true" />
307
308 <attachment_point
309 id="31"
310 group="8"
311 name="Center 2"
312 joint="mScreen"
313 position="0 0 0"
314 rotation="0 0 0"
315 hud="true"
316 max_attachment_offset="2.0"
317 visible_in_first_person="true" />
318
319 <attachment_point
320 id="32"
321 group="8"
322 name="Top Right"
323 joint="mScreen"
324 position="0 -0.5 0.5"
325 rotation="0 0 0"
326 hud="true"
327 max_attachment_offset="2.0"
328 visible_in_first_person="true" />
329
330 <attachment_point
331 id="33"
332 group="8"
333 name="Top"
334 joint="mScreen"
335 position="0 0 0.5"
336 rotation="0 0 0"
337 hud="true"
338 max_attachment_offset="2.0"
339 visible_in_first_person="true" />
340
341 <attachment_point
342 id="34"
343 group="8"
344 name="Top Left"
345 joint="mScreen"
346 position="0 0.5 0.5"
347 rotation="0 0 0"
348 hud="true"
349 max_attachment_offset="2.0"
350 visible_in_first_person="true" />
351
352 <attachment_point
353 id="35"
354 group="8"
355 name="Center"
356 joint="mScreen"
357 position="0 0 0"
358 rotation="0 0 0"
359 hud="true"
360 max_attachment_offset="2.0"
361 visible_in_first_person="true" />
362
363 <attachment_point
364 id="36"
365 group="8"
366 name="Bottom Left"
367 joint="mScreen"
368 position="0 0.5 -0.5"
369 rotation="0 0 0"
370 hud="true"
371 max_attachment_offset="2.0"
372 visible_in_first_person="true" />
373
374 <attachment_point
375 id="37"
376 group="8"
377 name="Bottom"
378 joint="mScreen"
379 position="0 0 -0.5"
380 rotation="0 0 0"
381 hud="true"
382 max_attachment_offset="2.0"
383 visible_in_first_person="true" />
384
385 <attachment_point
386 id="38"
387 group="8"
388 name="Bottom Right"
389 joint="mScreen"
390 position="0 -0.5 -0.5"
391 rotation="0 0 0"
392 hud="true"
393 max_attachment_offset="2.0"
394 visible_in_first_person="true" />
395
396
397 <param
398 id="32"
399 group="1"
400 wearable="shape"
401 name="Male_Skeleton"
402 label_min="Female"
403 label_max="Male"
404 value_min="0"
405 value_max="1">
406 <param_skeleton>
407 <bone
408 name="mNeck"
409 scale="0 0 .2" />
410
411 <bone
412 name="mCollarLeft"
413 scale="0 .4 0" />
414
415 <bone
416 name="mCollarRight"
417 scale="0 .4 0" />
418
419 <bone
420 name="mShoulderLeft"
421 scale="0 .35 0" />
422
423 <bone
424 name="mShoulderRight"
425 scale="0 .35 0" />
426
427 <bone
428 name="mElbowLeft"
429 scale="0 .1 0" />
430
431 <bone
432 name="mElbowRight"
433 scale="0 .1 0" />
434
435 <bone
436 name="mChest"
437 scale=".05 .05 .05" />
438
439 <bone
440 name="mTorso"
441 scale="0 0 .05" />
442
443 <bone
444 name="mPelvis"
445 scale="0 0 0" />
446
447 <bone
448 name="mHipLeft"
449 scale=".05 .05 0" />
450
451 <bone
452 name="mHipRight"
453 scale=".05 .05 0" />
454
455 <bone
456 name="mKneeLeft"
457 scale=".05 .05 .1" />
458
459 <bone
460 name="mKneeRight"
461 scale=".05 .05 .1" />
462 </param_skeleton>
463 </param>
464
465 <param
466 id="33"
467 group="0"
468 name="Height"
469 label="Height"
470 wearable="shape"
471 edit_group="shape_body"
472 edit_group_order="1"
473 label_min="Short"
474 label_max="Tall"
475 show_simple="true"
476 value_min="-2.3"
477 value_max="2"
478 camera_distance="2.2">
479 <param_skeleton>
480 <bone
481 name="mNeck"
482 scale="0 0 .02" />
483
484 <bone
485 name="mCollarLeft"
486 scale="0 0 0" />
487
488 <bone
489 name="mCollarRight"
490 scale="0 0 0" />
491
492 <bone
493 name="mShoulderLeft"
494 scale="0 0.08 0" />
495
496 <bone
497 name="mShoulderRight"
498 scale="0 0.08 0" />
499
500 <bone
501 name="mElbowLeft"
502 scale="0 0.06 0" />
503
504 <bone
505 name="mElbowRight"
506 scale="0 0.06 0" />
507
508 <bone
509 name="mChest"
510 scale="0 0 0.05" />
511
512 <bone
513 name="mTorso"
514 scale="0 0 0.05" />
515
516 <bone
517 name="mPelvis"
518 scale="0 0 0" />
519
520 <bone
521 name="mHipLeft"
522 scale="0 0 0.1" />
523
524 <bone
525 name="mHipRight"
526 scale="0 0 0.1" />
527
528 <bone
529 name="mKneeLeft"
530 scale="0 0 0.1" />
531
532 <bone
533 name="mKneeRight"
534 scale="0 0 0.1" />
535 </param_skeleton>
536 </param>
537
538 <param
539 id="34"
540 group="0"
541 name="Thickness"
542 label="Body Thickness"
543 wearable="shape"
544 edit_group="shape_body"
545 edit_group_order="2"
546 label_min="Body Thin"
547 label_max="Body Thick"
548 show_simple="true"
549 value_min="-0.7"
550 value_max="1.5"
551 camera_distance="1.8">
552 <param_skeleton>
553 <bone
554 name="mNeck"
555 scale="0.1 0.1 0" />
556
557 <bone
558 name="mCollarLeft"
559 scale="0 0.2 0" />
560
561 <bone
562 name="mCollarRight"
563 scale="0 0.2 0" />
564
565 <bone
566 name="mShoulderLeft"
567 scale="0.1 0 0.1" />
568
569 <bone
570 name="mShoulderRight"
571 scale="0.1 0 0.1" />
572
573 <bone
574 name="mElbowLeft"
575 scale="0.1 0 0.1" />
576
577 <bone
578 name="mElbowRight"
579 scale="0.1 0 0.1" />
580
581 <bone
582 name="mChest"
583 scale="0.1 0.1 0" />
584
585 <bone
586 name="mTorso"
587 scale="0.1 0.1 0" />
588
589 <bone
590 name="mPelvis"
591 scale="0.1 0.1 0" />
592
593 <bone
594 name="mHipLeft"
595 scale="0.13 0.13 0" />
596
597 <bone
598 name="mHipRight"
599 scale="0.13 0.13 0" />
600
601 <bone
602 name="mKneeLeft"
603 scale="0.12 0.12 0" />
604
605 <bone
606 name="mKneeRight"
607 scale="0.12 0.12 0" />
608 </param_skeleton>
609 </param>
610
611 <param
612 id="36"
613 group="0"
614 name="Shoulders"
615 label="Shoulders"
616 wearable="shape"
617 edit_group="shape_torso"
618 edit_group_order="4"
619 label_min="Narrow"
620 label_max="Broad"
621 show_simple="true"
622 value_min="-1.8"
623 value_max="1.4"
624 value_default="-0.5"
625 camera_elevation=".1"
626 camera_distance="1.2"
627 camera_angle="0">
628 <param_skeleton>
629 <bone
630 name="mNeck"
631 scale="0.01 0.03 0" />
632
633 <bone
634 name="mCollarLeft"
635 scale="0 0 0"
636 offset="0 .02 0" />
637
638 <bone
639 name="mCollarRight"
640 scale="0 0 0"
641 offset="0 -.02 0" />
642
643 <bone
644 name="mChest"
645 scale="0.02 0.08 0" />
646 </param_skeleton>
647 </param>
648
649 <param
650 id="37"
651 group="0"
652 name="Hip Width"
653 label="Hip Width"
654 wearable="shape"
655 edit_group="shape_legs"
656 edit_group_order="3"
657 label_min="Narrow"
658 label_max="Wide"
659 show_simple="true"
660 value_min="-3.2"
661 value_max="2.8"
662 camera_distance="1.8">
663 <param_skeleton>
664 <bone
665 name="mPelvis"
666 scale="0 0.1 0" />
667
668 <bone
669 name="mHipLeft"
670 scale="0 0 0"
671 offset="0 .004 0" />
672
673 <bone
674 name="mHipRight"
675 scale="0 0 0"
676 offset="0 -.004 0" />
677 </param_skeleton>
678 </param>
679
680 <param
681 id="842"
682 group="0"
683 name="Hip Length"
684 wearable="shape"
685 edit_group="shape_legs"
686 edit_group_order="3.2"
687 label_min="Short hips"
688 label_max="Long Hips"
689 value_min="-1"
690 value_max="1"
691 camera_distance="1.8">
692 <param_skeleton>
693 <bone
694 name="mPelvis"
695 scale="0 0 0.3" />
696 </param_skeleton>
697 </param>
698
699 <param
700 id="38"
701 group="0"
702 name="Torso Length"
703 wearable="shape"
704 edit_group="shape_torso"
705 edit_group_order="11"
706 label_min="Short Torso"
707 label_max="Long Torso"
708 value_min="-1"
709 value_max="1"
710 camera_distance="1.8">
711 <param_skeleton>
712 <bone
713 name="mTorso"
714 scale="0 0 .3" />
715
716 <bone
717 name="mPelvis"
718 scale="0 0 .1" />
719
720 <bone
721 name="mHipLeft"
722 scale="0 0 -.1" />
723
724 <bone
725 name="mHipRight"
726 scale="0 0 -.1" />
727
728 <bone
729 name="mKneeRight"
730 scale="0 0 -.05" />
731
732 <bone
733 name="mKneeLeft"
734 scale="0 0 -.05" />
735 </param_skeleton>
736 </param>
737
738 <param
739 id="195"
740 group="1"
741 name="EyeBone_Spread"
742 wearable="shape"
743 edit_group="shape_eyes"
744 label_min="Eyes Together"
745 label_max="Eyes Spread"
746 value_min="-1"
747 value_max="1">
748 <param_skeleton>
749 <bone
750 name="mEyeLeft"
751 scale="0 0 0"
752 offset="0 .009 0" />
753
754 <bone
755 name="mEyeRight"
756 scale="0 0 0"
757 offset="0 -.009 0" />
758 </param_skeleton>
759 </param>
760
761 <param
762 id="661"
763 group="1"
764 name="EyeBone_Head_Shear"
765 wearable="shape"
766 edit_group="shape_eyes"
767 label_min="Eyes Shear Left Up"
768 label_max="Eyes Shear Right Up"
769 value_min="-2"
770 value_max="2">
771 <param_skeleton>
772 <bone
773 name="mEyeLeft"
774 scale="0 0 0"
775 offset="0 0 .004" />
776
777 <bone
778 name="mEyeRight"
779 scale="0 0 0"
780 offset="0 0 -.004" />
781 </param_skeleton>
782 </param>
783
784 <param
785 id="772"
786 group="1"
787 name="EyeBone_Head_Elongate"
788 wearable="shape"
789 edit_group="shape_eyes"
790 label_min="Eyes Short Head"
791 label_max="Eyes Long Head"
792 value_min="-1"
793 value_max="1">
794 <param_skeleton>
795 <bone
796 name="mEyeLeft"
797 scale="0 0 0"
798 offset=".016 0 0" />
799
800 <bone
801 name="mEyeRight"
802 scale="0 0 0"
803 offset=".016 0 0" />
804 </param_skeleton>
805 </param>
806
807 <param
808 id="768"
809 group="1"
810 name="EyeBone_Bug"
811 wearable="shape"
812 edit_group="shape_eyes"
813 label_min="Eyes Sunken"
814 label_max="Eyes Bugged"
815 value_min="-2"
816 value_max="2">
817 <param_skeleton>
818 <bone
819 name="mEyeLeft"
820 scale="0 0 0"
821 offset=".005 0 0" />
822
823 <bone
824 name="mEyeRight"
825 scale="0 0 0"
826 offset=".005 0 0" />
827 </param_skeleton>
828 </param>
829
830 <param
831 id="655"
832 group="1"
833 name="Head Size"
834 label="Head Size"
835 wearable="shape"
836 edit_group="shape_head"
837 label_min="Small Head"
838 label_max="Big Head"
839 show_simple="true"
840 value_min="-.25"
841 value_max=".10">
842 <param_skeleton>
843 <bone
844 name="mSkull"
845 scale="1 1 1"
846 offset="0 0 0.1" />
847
848 <bone
849 name="mHead"
850 scale="1 1 1"
851 offset="0 0 0" />
852
853 <bone
854 name="mEyeLeft"
855 scale="1 1 1"
856 offset="0 0 0" />
857
858 <bone
859 name="mEyeRight"
860 scale="1 1 1"
861 offset="0 0 0" />
862 </param_skeleton>
863 </param>
864
865 <param
866 id="197"
867 group="1"
868 wearable="shoes"
869 name="Shoe_Heels"
870 edit_group="shoes"
871 label_min="No Heels"
872 label_max="High Heels"
873 value_min="0"
874 value_max="1">
875 <param_skeleton>
876 <bone
877 name="mFootRight"
878 scale="0 0 0"
879 offset="0 0 -.08" />
880
881 <bone
882 name="mFootLeft"
883 scale="0 0 0"
884 offset="0 0 -.08" />
885 </param_skeleton>
886 </param>
887
888 <param
889 id="502"
890 group="1"
891 wearable="shoes"
892 name="Shoe_Platform"
893 edit_group="shoes"
894 label_min="No Heels"
895 label_max="High Heels"
896 value_min="0"
897 value_max="1">
898 <param_skeleton>
899 <bone
900 name="mFootRight"
901 scale="0 0 0"
902 offset="0 0 -.07" />
903
904 <bone
905 name="mFootLeft"
906 scale="0 0 0"
907 offset="0 0 -.07" />
908 </param_skeleton>
909 </param>
910
911 <param
912 id="675"
913 group="0"
914 name="Hand Size"
915 wearable="shape"
916 edit_group="shape_torso"
917 edit_group_order="10"
918 label_min="Small Hands"
919 label_max="Large Hands"
920 value_min="-.3"
921 value_max=".3"
922 camera_elevation=".1"
923 camera_distance="1.4"
924 camera_angle="0">
925 <param_skeleton>
926 <bone
927 name="mWristRight"
928 scale="1 1 1"
929 offset="0 0 0" />
930
931 <bone
932 name="mWristLeft"
933 scale="1 1 1"
934 offset="0 0 0" />
935 </param_skeleton>
936 </param>
937
938 <param
939 id="683"
940 group="0"
941 name="Neck Thickness"
942 wearable="shape"
943 edit_group="shape_torso"
944 edit_group_order="2"
945 label_min="Skinny Neck"
946 label_max="Thick Neck"
947 value_min="-.4"
948 value_max=".2"
949 value_default="-.15"
950 camera_elevation=".3"
951 camera_distance=".8"
952 camera_angle="15">
953 <param_skeleton>
954 <bone
955 name="mNeck"
956 scale="1 1 0"
957 offset="0 0 0" />
958 </param_skeleton>
959 </param>
960
961 <param
962 id="689"
963 group="1"
964 wearable="shape"
965 name="EyeBone_Big_Eyes"
966 edit_group="shape_eyes"
967 label_min="Eyes Back"
968 label_max="Eyes Forward"
969 value_min="-1"
970 value_max="1">
971 <param_skeleton>
972 <bone
973 name="mEyeLeft"
974 scale="0 0 0"
975 offset="-.005 0 0" />
976
977 <bone
978 name="mEyeRight"
979 scale="0 0 0"
980 offset="-.005 0 0" />
981 </param_skeleton>
982 </param>
983
984 <param
985 id="692"
986 group="0"
987 name="Leg Length"
988 wearable="shape"
989 edit_group="shape_legs"
990 edit_group_order="2"
991 label_min="Short Legs"
992 label_max="Long Legs"
993 value_min="-1"
994 value_max="1"
995 camera_distance="2.5">
996 <param_skeleton>
997 <bone
998 name="mHipLeft"
999 scale="0 0 .2" />
1000
1001 <bone
1002 name="mHipRight"
1003 scale="0 0 .2" />
1004
1005 <bone
1006 name="mKneeRight"
1007 scale="0 0 .2" />
1008
1009 <bone
1010 name="mKneeLeft"
1011 scale="0 0 .2" />
1012 </param_skeleton>
1013 </param>
1014
1015 <param
1016 id="693"
1017 group="0"
1018 name="Arm Length"
1019 wearable="shape"
1020 edit_group="shape_torso"
1021 edit_group_order="9"
1022 label_min="Short Arms"
1023 label_max="Long arms"
1024 value_min="-1"
1025 value_max="1"
1026 value_default=".6"
1027 camera_distance="1.5">
1028 <param_skeleton>
1029 <bone
1030 name="mShoulderLeft"
1031 scale="0 .2 0" />
1032
1033 <bone
1034 name="mShoulderRight"
1035 scale="0 .2 0" />
1036
1037 <bone
1038 name="mElbowRight"
1039 scale="0 .3 0" />
1040
1041 <bone
1042 name="mElbowLeft"
1043 scale="0 .3 0" />
1044 </param_skeleton>
1045 </param>
1046
1047 <param
1048 id="756"
1049 group="0"
1050 name="Neck Length"
1051 wearable="shape"
1052 edit_group="shape_torso"
1053 edit_group_order="3"
1054 label_min="Short Neck"
1055 label_max="Long Neck"
1056 value_min="-1"
1057 value_max="1"
1058 value_default="0"
1059 camera_elevation=".3"
1060 camera_distance=".8"
1061 camera_angle="15">
1062 <param_skeleton>
1063 <bone
1064 name="mNeck"
1065 scale="0 0 .5" />
1066 </param_skeleton>
1067 </param>
1068 </skeleton>
1069
1070 <mesh
1071 type="hairMesh"
1072 lod="0"
1073 file_name="avatar_hair.llm"
1074 min_pixel_width="320">
1075 <!-- begin morph targets -->
1076 <param
1077 id="180"
1078 group="1"
1079 name="Hair_Volume"
1080 label="Hair Volume"
1081 show_simple="true"
1082 wearable="hair"
1083 clothing_morph="true"
1084 edit_group="hair_style"
1085 label_min="Less"
1086 label_max="More"
1087 value_min="0"
1088 value_max="1.3"
1089 camera_elevation=".1"
1090 camera_distance=".5"
1091 camera_angle="20">
1092 <param_morph />
1093 </param>
1094
1095 <param
1096 id="761"
1097 group="1"
1098 name="Hair_Volume_Small"
1099 label="Hair Volume"
1100 show_simple="true"
1101 wearable="hair"
1102 edit_group="hair_style"
1103 label_min="Less"
1104 label_max="More"
1105 value_min="0"
1106 value_max="1.3"
1107 camera_elevation=".1"
1108 camera_distance=".5"
1109 camera_angle="20">
1110 <param_morph />
1111 </param>
1112
1113 <param
1114 id="181"
1115 group="0"
1116 name="Hair_Big_Front"
1117 label="Big Hair Front"
1118 wearable="hair"
1119 edit_group="hair_style"
1120 edit_group_order="5"
1121 label_min="Less"
1122 label_max="More"
1123 value_min="-1"
1124 value_max="1"
1125 value_default="0.14"
1126 camera_elevation=".1"
1127 camera_distance=".5"
1128 camera_angle="90">
1129 <param_morph />
1130 </param>
1131
1132 <param
1133 id="182"
1134 group="0"
1135 name="Hair_Big_Top"
1136 label="Big Hair Top"
1137 wearable="hair"
1138 edit_group="hair_style"
1139 edit_group_order="6"
1140 label_min="Less"
1141 label_max="More"
1142 value_min="-1"
1143 value_max="1"
1144 value_default=".7"
1145 camera_elevation=".1"
1146 camera_distance=".5"
1147 camera_angle="90">
1148 <param_morph />
1149 </param>
1150
1151 <param
1152 id="183"
1153 group="0"
1154 name="Hair_Big_Back"
1155 clothing_morph="true"
1156 label="Big Hair Back"
1157 wearable="hair"
1158 edit_group="hair_style"
1159 edit_group_order="7"
1160 label_min="Less"
1161 label_max="More"
1162 value_min="-1"
1163 value_max="1"
1164 value_default="0.05"
1165 camera_elevation=".1"
1166 camera_distance=".7"
1167 camera_angle="90">
1168 <param_morph />
1169 </param>
1170
1171 <param
1172 id="184"
1173 group="0"
1174 name="Hair_Spiked"
1175 label="Spiked Hair"
1176 show_simple="true"
1177 wearable="hair"
1178 clothing_morph="true"
1179 edit_group="hair_style"
1180 edit_group_order="15"
1181 label_min="No Spikes"
1182 label_max="Big Spikes"
1183 value_min="0"
1184 value_max="1"
1185 camera_elevation=".1"
1186 camera_distance=".5"
1187 camera_angle="20">
1188 <param_morph />
1189 </param>
1190
1191 <param
1192 id="140"
1193 group="0"
1194 name="Hair_Part_Middle"
1195 label="Middle Part"
1196 wearable="hair"
1197 edit_group="hair_style"
1198 edit_group_order="17"
1199 label_min="No Part"
1200 label_max="Part"
1201 value_min="0"
1202 value_max="2"
1203 camera_elevation=".1"
1204 camera_distance=".5"
1205 camera_angle="0">
1206 <param_morph />
1207 </param>
1208
1209 <param
1210 id="141"
1211 group="0"
1212 name="Hair_Part_Right"
1213 label="Right Part"
1214 wearable="hair"
1215 edit_group="hair_style"
1216 edit_group_order="18"
1217 label_min="No Part"
1218 label_max="Part"
1219 value_min="0"
1220 value_max="2"
1221 camera_elevation=".1"
1222 camera_distance=".5"
1223 camera_angle="0">
1224 <param_morph />
1225 </param>
1226
1227 <param
1228 id="142"
1229 group="0"
1230 name="Hair_Part_Left"
1231 label="Left Part"
1232 wearable="hair"
1233 edit_group="hair_style"
1234 edit_group_order="19"
1235 label_min="No Part"
1236 label_max="Part"
1237 value_min="0"
1238 value_max="2"
1239 camera_elevation=".1"
1240 camera_distance=".5"
1241 camera_angle="0">
1242 <param_morph />
1243 </param>
1244
1245 <param
1246 id="143"
1247 group="0"
1248 name="Hair_Sides_Full"
1249 label="Full Hair Sides"
1250 show_simple="true"
1251 wearable="hair"
1252 edit_group="hair_style"
1253 edit_group_order="11"
1254 label_min="Mowhawk"
1255 label_max="Full Sides"
1256 value_min="-4"
1257 value_max="1.5"
1258 value_default="0.125"
1259 camera_elevation=".1"
1260 camera_distance=".5"
1261 camera_angle="20">
1262 <param_morph />
1263 </param>
1264
1265 <param
1266 id="144"
1267 group="1"
1268 name="Bangs_Front_Up"
1269 label="Front Bangs Up"
1270 wearable="hair"
1271 edit_group="hair_style"
1272 label_min="Bangs"
1273 label_max="Bangs Up"
1274 value_min="0"
1275 value_max="1"
1276 camera_elevation=".1"
1277 camera_distance=".5"
1278 camera_angle="20">
1279 <param_morph />
1280 </param>
1281
1282 <param
1283 id="145"
1284 group="1"
1285 clothing_morph="true"
1286 name="Bangs_Front_Down"
1287 label="Front Bangs Down"
1288 wearable="hair"
1289 edit_group="hair_style"
1290 label_min="Bangs"
1291 label_max="Bangs Down"
1292 value_min="0"
1293 value_max="5"
1294 camera_elevation=".1"
1295 camera_distance=".5"
1296 camera_angle="20">
1297 <param_morph />
1298 </param>
1299
1300 <param
1301 id="146"
1302 group="1"
1303 name="Bangs_Sides_Up"
1304 label="Side Bangs Up"
1305 wearable="hair"
1306 edit_group="hair_style"
1307 label_min="Side Bangs"
1308 label_max="Side Bangs Up"
1309 value_min="0"
1310 value_max="1"
1311 camera_elevation=".1"
1312 camera_distance=".5"
1313 camera_angle="20">
1314 <param_morph />
1315 </param>
1316
1317 <param
1318 id="147"
1319 group="1"
1320 clothing_morph="true"
1321 name="Bangs_Sides_Down"
1322 label="Side Bangs Down"
1323 wearable="hair"
1324 edit_group="hair_style"
1325 label_min="Side Bangs"
1326 label_max="Side Bangs Down"
1327 value_min="0"
1328 value_max="2"
1329 camera_elevation=".1"
1330 camera_distance=".5"
1331 camera_angle="20">
1332 <param_morph />
1333 </param>
1334
1335 <param
1336 id="148"
1337 group="1"
1338 name="Bangs_Back_Up"
1339 label="Back Bangs Up"
1340 wearable="hair"
1341 edit_group="hair_style"
1342 label_min="Back Bangs"
1343 label_max="Back Bangs Up"
1344 value_min="0"
1345 value_max="1"
1346 camera_elevation=".1"
1347 camera_distance=".5"
1348 camera_angle="150">
1349 <param_morph />
1350 </param>
1351
1352 <param
1353 id="149"
1354 group="1"
1355 name="Bangs_Back_Down"
1356 label="Back Bangs Down"
1357 clothing_morph="true"
1358 wearable="hair"
1359 edit_group="hair_style"
1360 label_min="Back Bangs"
1361 label_max="Back Bangs Down"
1362 value_min="0"
1363 value_max="2"
1364 camera_elevation=".1"
1365 camera_distance=".5"
1366 camera_angle="150">
1367 <param_morph />
1368 </param>
1369
1370 <param
1371 id="171"
1372 group="1"
1373 name="Hair_Front_Down"
1374 label="Front Hair Down"
1375 wearable="hair"
1376 edit_group="hair_style"
1377 label_min="Front Hair"
1378 label_max="Front Hair Down"
1379 value_min="0"
1380 value_max="1"
1381 camera_elevation=".1"
1382 camera_distance=".5"
1383 camera_angle="20">
1384 <param_morph />
1385 </param>
1386
1387 <param
1388 id="172"
1389 group="1"
1390 name="Hair_Front_Up"
1391 label="Front Hair Up"
1392 wearable="hair"
1393 edit_group="hair_style"
1394 label_min="Front Hair"
1395 label_max="Front Hair Up"
1396 value_min="0"
1397 value_max="1"
1398 camera_elevation=".1"
1399 camera_distance=".5"
1400 camera_angle="20">
1401 <param_morph />
1402 </param>
1403
1404 <param
1405 id="173"
1406 group="1"
1407 name="Hair_Sides_Down"
1408 label="Sides Hair Down"
1409 wearable="hair"
1410 edit_group="hair_style"
1411 label_min="Sides Hair"
1412 label_max="Sides Hair Down"
1413 value_min="0"
1414 value_max="1"
1415 camera_elevation=".1"
1416 camera_distance=".5"
1417 camera_angle="20">
1418 <param_morph />
1419 </param>
1420
1421 <param
1422 id="174"
1423 group="1"
1424 name="Hair_Sides_Up"
1425 label="Sides Hair Up"
1426 wearable="hair"
1427 edit_group="hair_style"
1428 label_min="Sides Hair"
1429 label_max="Sides Hair Up"
1430 value_min="0"
1431 value_max="1"
1432 camera_elevation=".1"
1433 camera_distance=".5"
1434 camera_angle="20">
1435 <param_morph />
1436 </param>
1437
1438 <param
1439 id="175"
1440 group="1"
1441 name="Hair_Back_Down"
1442 label="Back Hair Down"
1443 clothing_morph="true"
1444 wearable="hair"
1445 edit_group="hair_style"
1446 label_min="Back Hair"
1447 label_max="Back Hair Down"
1448 value_min="0"
1449 value_max="3"
1450 camera_elevation=".1"
1451 camera_distance=".5"
1452 camera_angle="150">
1453 <param_morph />
1454 </param>
1455
1456 <param
1457 id="176"
1458 group="1"
1459 name="Hair_Back_Up"
1460 label="Back Hair Up"
1461 wearable="hair"
1462 edit_group="hair_style"
1463 label_min="Back Hair"
1464 label_max="Back Hair Up"
1465 value_min="0"
1466 value_max="1"
1467 camera_elevation=".1"
1468 camera_distance=".5"
1469 camera_angle="150">
1470 <param_morph />
1471 </param>
1472
1473 <param
1474 id="177"
1475 group="0"
1476 name="Hair_Rumpled"
1477 label="Rumpled Hair"
1478 show_simple="true"
1479 wearable="hair"
1480 clothing_morph="true"
1481 edit_group="hair_style"
1482 edit_group_order="14.5"
1483 label_min="Smooth Hair"
1484 label_max="Rumpled Hair"
1485 value_min="0"
1486 value_max="1"
1487 camera_elevation=".1"
1488 camera_distance=".5"
1489 camera_angle="20">
1490 <param_morph />
1491 </param>
1492
1493 <param
1494 id="178"
1495 group="1"
1496 name="Hair_Swept_Back"
1497 label="Swept Back Hair"
1498 wearable="hair"
1499 edit_group="hair_style"
1500 label_min="NotHair"
1501 label_max="Swept Back"
1502 value_min="0"
1503 value_max="1"
1504 camera_elevation=".1"
1505 camera_distance=".5"
1506 camera_angle="90">
1507 <param_morph />
1508 </param>
1509
1510 <param
1511 id="179"
1512 group="1"
1513 name="Hair_Swept_Forward"
1514 label="Swept Forward Hair"
1515 wearable="hair"
1516 edit_group="hair_style"
1517 label_min="Hair"
1518 label_max="Swept Forward"
1519 value_min="0"
1520 value_max="1"
1521 camera_elevation=".1"
1522 camera_distance=".5"
1523 camera_angle="90">
1524 <param_morph />
1525 </param>
1526
1527 <param
1528 id="190"
1529 group="1"
1530 name="Hair_Tilt_Right"
1531 label="Hair Tilted Right"
1532 wearable="hair"
1533 edit_group="hair_style"
1534 label_min="Hair"
1535 label_max="Tilt Right"
1536 value_min="0"
1537 value_max="1"
1538 camera_elevation=".1"
1539 camera_distance=".5"
1540 camera_angle="0">
1541 <param_morph />
1542 </param>
1543
1544 <param
1545 id="191"
1546 group="1"
1547 name="Hair_Tilt_Left"
1548 label="Hair Tilted Left"
1549 wearable="hair"
1550 edit_group="hair_style"
1551 label_min="Hair"
1552 label_max="Tilt Left"
1553 value_min="0"
1554 value_max="1"
1555 camera_elevation=".1"
1556 camera_distance=".5"
1557 camera_angle="0">
1558 <param_morph />
1559 </param>
1560
1561 <param
1562 id="192"
1563 group="0"
1564 name="Bangs_Part_Middle"
1565 label="Part Bangs"
1566 wearable="hair"
1567 edit_group="hair_style"
1568 edit_group_order="20"
1569 label_min="No Part"
1570 label_max="Part Bangs"
1571 value_min="0"
1572 value_max="1"
1573 camera_elevation=".1"
1574 camera_distance=".5"
1575 camera_angle="0">
1576 <param_morph />
1577 </param>
1578
1579 <param
1580 id="640"
1581 group="1"
1582 name="Hair_Egg_Head"
1583 wearable="hair"
1584 edit_group="hair_style"
1585 cross_wearable="true"
1586 value_min="-1.3"
1587 value_max="1">
1588 <param_morph />
1589 </param>
1590
1591 <param
1592 id="641"
1593 group="1"
1594 name="Hair_Squash_Stretch_Head"
1595 wearable="hair"
1596 edit_group="hair_style"
1597 cross_wearable="true"
1598 value_min="-.5"
1599 value_max="1">
1600 <param_morph />
1601 </param>
1602
1603 <param
1604 id="642"
1605 group="1"
1606 name="Hair_Square_Head"
1607 wearable="hair"
1608 edit_group="hair_style"
1609 cross_wearable="true"
1610 value_min="0"
1611 value_max="1">
1612 <param_morph />
1613 </param>
1614
1615 <param
1616 id="643"
1617 group="1"
1618 name="Hair_Round_Head"
1619 wearable="hair"
1620 edit_group="hair_style"
1621 cross_wearable="true"
1622 value_min="0"
1623 value_max="1">
1624 <param_morph />
1625 </param>
1626
1627 <param
1628 id="644"
1629 group="1"
1630 name="Hair_Forehead_Round"
1631 wearable="hair"
1632 edit_group="hair_style"
1633 cross_wearable="true"
1634 value_min="0"
1635 value_max="1">
1636 <param_morph />
1637 </param>
1638
1639 <param
1640 id="645"
1641 group="1"
1642 name="Hair_Forehead_Slant"
1643 wearable="hair"
1644 edit_group="hair_style"
1645 cross_wearable="true"
1646 value_min="0"
1647 value_max="1">
1648 <param_morph />
1649 </param>
1650
1651 <param
1652 id="774"
1653 group="1"
1654 name="Shear_Head_Hair"
1655 wearable="hair"
1656 edit_group="hair_style"
1657 cross_wearable="true"
1658 value_min="-2"
1659 value_max="2">
1660 <param_morph />
1661 </param>
1662
1663 <param
1664 id="771"
1665 group="1"
1666 name="Elongate_Head_Hair"
1667 wearable="hair"
1668 edit_group="hair_style"
1669 cross_wearable="true"
1670 value_min="-1"
1671 value_max="1">
1672 <param_morph />
1673 </param>
1674
1675 <param
1676 id="674"
1677 group="0"
1678 name="Hair_Shear_Back"
1679 wearable="hair"
1680 edit_group="hair_style"
1681 edit_group_order="12"
1682 label="Shear Back"
1683 label_min="Full Back"
1684 label_max="Sheared Back"
1685 value_min="-1"
1686 value_max="2"
1687 value_default="-0.3"
1688 camera_elevation=".1"
1689 camera_distance=".5"
1690 camera_angle="100">
1691 <param_morph />
1692 </param>
1693
1694 <param
1695 id="762"
1696 group="0"
1697 name="Hair_Shear_Front"
1698 wearable="hair"
1699 edit_group="hair_style"
1700 edit_group_order="11.8"
1701 label="Shear Front"
1702 show_simple="true"
1703 label_min="Full Front"
1704 label_max="Sheared Front"
1705 value_min="0"
1706 value_max="3"
1707 camera_elevation=".1"
1708 camera_distance=".5"
1709 camera_angle="30">
1710 <param_morph />
1711 </param>
1712
1713 <param
1714 id="754"
1715 group="0"
1716 name="Hair_Taper_Back"
1717 wearable="hair"
1718 edit_group="hair_style"
1719 edit_group_order="14"
1720 label="Taper Back"
1721 label_min="Wide Back"
1722 label_max="Narrow Back"
1723 value_min="-1"
1724 value_max="2"
1725 value_default="0"
1726 camera_elevation=".1"
1727 camera_distance=".5"
1728 camera_angle="160">
1729 <param_morph />
1730 </param>
1731
1732 <param
1733 id="755"
1734 group="0"
1735 name="Hair_Taper_Front"
1736 wearable="hair"
1737 edit_group="hair_style"
1738 edit_group_order="13"
1739 label="Taper Front"
1740 label_min="Wide Front"
1741 label_max="Narrow Front"
1742 value_min="-1.5"
1743 value_max="1.5"
1744 value_default="0.05"
1745 camera_elevation=".1"
1746 camera_distance=".5"
1747 camera_angle="20">
1748 <param_morph />
1749 </param>
1750
1751 <param
1752 id="782"
1753 group="1"
1754 clothing_morph="true"
1755 name="Hair_Pigtails_Short"
1756 wearable="hair"
1757 edit_group="hair_style"
1758 value_min="0"
1759 value_max="1">
1760 <param_morph />
1761 </param>
1762
1763 <param
1764 id="783"
1765 group="1"
1766 clothing_morph="true"
1767 name="Hair_Pigtails_Med"
1768 wearable="hair"
1769 edit_group="hair_style"
1770 value_min="0"
1771 value_max="1">
1772 <param_morph />
1773 </param>
1774
1775 <param
1776 id="790"
1777 group="1"
1778 clothing_morph="true"
1779 name="Hair_Pigtails_Medlong"
1780 wearable="hair"
1781 edit_group="hair_style"
1782 value_min="0"
1783 value_max="1">
1784 <param_morph />
1785 </param>
1786
1787 <param
1788 id="784"
1789 group="1"
1790 clothing_morph="true"
1791 name="Hair_Pigtails_Long"
1792 wearable="hair"
1793 edit_group="hair_style"
1794 value_min="0"
1795 value_max="1">
1796 <param_morph />
1797 </param>
1798
1799 <param
1800 id="786"
1801 group="1"
1802 name="Hair_Ponytail_Short"
1803 wearable="hair"
1804 edit_group="hair_style"
1805 value_min="0"
1806 value_max="1">
1807 <param_morph />
1808 </param>
1809
1810 <param
1811 id="787"
1812 group="1"
1813 name="Hair_Ponytail_Med"
1814 wearable="hair"
1815 edit_group="hair_style"
1816 value_min="0"
1817 value_max="1">
1818 <param_morph />
1819 </param>
1820
1821 <param
1822 id="788"
1823 group="1"
1824 name="Hair_Ponytail_Long"
1825 clothing_morph="true"
1826 wearable="hair"
1827 edit_group="hair_style"
1828 value_min="0"
1829 value_max="1">
1830 <param_morph />
1831 </param>
1832
1833 <!-- #end morph targets -->
1834 </mesh>
1835
1836 <mesh
1837 type="hairMesh"
1838 lod="1"
1839 file_name="avatar_hair_1.llm"
1840 min_pixel_width="160"
1841 reference="avatar_hair.llm">
1842 </mesh>
1843
1844 <mesh
1845 type="hairMesh"
1846 lod="2"
1847 file_name="avatar_hair_2.llm"
1848 min_pixel_width="80"
1849 reference="avatar_hair.llm">
1850 </mesh>
1851
1852 <mesh
1853 type="hairMesh"
1854 lod="3"
1855 file_name="avatar_hair_3.llm"
1856 min_pixel_width="40"
1857 reference="avatar_hair.llm">
1858 </mesh>
1859
1860 <mesh
1861 type="hairMesh"
1862 lod="4"
1863 file_name="avatar_hair_4.llm"
1864 min_pixel_width="20"
1865 reference="avatar_hair.llm">
1866 </mesh>
1867
1868 <mesh
1869 type="hairMesh"
1870 lod="5"
1871 file_name="avatar_hair_5.llm"
1872 min_pixel_width="0"
1873 reference="avatar_hair.llm">
1874 </mesh>
1875
1876 <mesh
1877 type="headMesh"
1878 lod="0"
1879 file_name="avatar_head.llm"
1880 min_pixel_width="320">
1881 <!--
1882 begin morph targets
1883 #############
1884 tweakable morphs
1885 #############
1886 -->
1887 <param
1888 id="1"
1889 group="0"
1890 name="Big_Brow"
1891 label="Brow Size"
1892 wearable="shape"
1893 edit_group="shape_head"
1894 edit_group_order="7"
1895 label_min="Small"
1896 label_max="Large"
1897 value_min="-.3"
1898 value_max="2"
1899 camera_elevation=".1"
1900 camera_distance=".4"
1901 camera_angle="45">
1902 <param_morph />
1903 </param>
1904
1905 <param
1906 id="2"
1907 group="0"
1908 name="Nose_Big_Out"
1909 label="Nose Size"
1910 wearable="shape"
1911 edit_group="shape_nose"
1912 edit_group_order="1"
1913 label_min="Small"
1914 label_max="Large"
1915 show_simple="true"
1916 value_min="-0.8"
1917 value_max="2.5"
1918 camera_elevation=".1"
1919 camera_distance=".35"
1920 camera_angle="50">
1921 <param_morph />
1922 </param>
1923
1924 <param
1925 id="4"
1926 group="0"
1927 name="Broad_Nostrils"
1928 label="Nostril Width"
1929 wearable="shape"
1930 edit_group="shape_nose"
1931 edit_group_order="3"
1932 label_min="Narrow"
1933 label_max="Broad"
1934 value_min="-.5"
1935 value_max="1"
1936 camera_elevation=".1"
1937 camera_distance=".3"
1938 camera_angle="-20">
1939 <param_morph />
1940 </param>
1941
1942 <param
1943 id="759"
1944 group="0"
1945 name="Low_Septum_Nose"
1946 label="Nostril Division"
1947 wearable="shape"
1948 edit_group="shape_nose"
1949 edit_group_order="3.5"
1950 label_min="High"
1951 label_max="Low"
1952 value_min="-1"
1953 value_max="1.5"
1954 value_default="0.5"
1955 camera_elevation=".1"
1956 camera_distance=".3"
1957 camera_angle="-20">
1958 <param_morph />
1959 </param>
1960
1961 <param
1962 id="517"
1963 group="0"
1964 name="Wide_Nose"
1965 label="Nose Width"
1966 wearable="shape"
1967 edit_group="shape_nose"
1968 edit_group_order="2"
1969 label_min="Narrow"
1970 label_max="Wide"
1971 show_simple="true"
1972 value_min="-.5"
1973 value_max="1"
1974 camera_elevation=".1"
1975 camera_distance=".3"
1976 camera_angle="-20">
1977 <param_morph />
1978 </param>
1979
1980 <param
1981 id="5"
1982 group="0"
1983 name="Cleft_Chin"
1984 label="Chin Cleft"
1985 wearable="shape"
1986 edit_group="shape_chin"
1987 edit_group_order="6"
1988 label_min="Round"
1989 label_max="Cleft"
1990 value_min="-.1"
1991 value_max="1"
1992 camera_elevation="0"
1993 camera_distance=".28"
1994 camera_angle="-20">
1995 <param_morph />
1996 </param>
1997
1998 <param
1999 id="6"
2000 group="0"
2001 name="Bulbous_Nose_Tip"
2002 label="Nose Tip Shape"
2003 wearable="shape"
2004 edit_group="shape_nose"
2005 edit_group_order="8"
2006 label_min="Pointy"
2007 label_max="Bulbous"
2008 value_min="-.3"
2009 value_max="1"
2010 camera_elevation=".1"
2011 camera_distance=".35"
2012 camera_angle="15">
2013 <param_morph />
2014 </param>
2015
2016 <param
2017 id="7"
2018 group="0"
2019 name="Weak_Chin"
2020 label="Chin Angle"
2021 wearable="shape"
2022 edit_group="shape_chin"
2023 edit_group_order="1"
2024 label_min="Chin Out"
2025 label_max="Chin In"
2026 value_min="-.5"
2027 value_max=".5"
2028 camera_elevation=".1"
2029 camera_distance=".4"
2030 camera_angle="45">
2031 <param_morph />
2032 </param>
2033
2034 <param
2035 id="8"
2036 group="0"
2037 name="Double_Chin"
2038 label="Chin-Neck"
2039 wearable="shape"
2040 edit_group="shape_chin"
2041 edit_group_order="8"
2042 label_min="Tight Chin"
2043 label_max="Double Chin"
2044 value_min="-.5"
2045 value_max="1.5"
2046 camera_elevation="-.1"
2047 camera_distance=".3"
2048 camera_angle="60">
2049 <param_morph />
2050 </param>
2051
2052 <param
2053 id="10"
2054 group="0"
2055 name="Sunken_Cheeks"
2056 label="Lower Cheeks"
2057 wearable="shape"
2058 edit_group="shape_head"
2059 edit_group_order="9"
2060 label_min="Well-Fed"
2061 label_max="Sunken"
2062 show_simple="true"
2063 value_min="-1.5"
2064 value_max="3"
2065 camera_elevation=".1"
2066 camera_distance=".4"
2067 camera_angle="5">
2068 <param_morph />
2069 </param>
2070
2071 <param
2072 id="11"
2073 group="0"
2074 name="Noble_Nose_Bridge"
2075 label="Upper Bridge"
2076 wearable="shape"
2077 edit_group="shape_nose"
2078 edit_group_order="5"
2079 label_min="Low"
2080 label_max="High"
2081 value_min="-.5"
2082 value_max="1.5"
2083 camera_elevation=".1"
2084 camera_distance=".35"
2085 camera_angle="70">
2086 <param_morph />
2087 </param>
2088
2089 <param
2090 id="758"
2091 group="0"
2092 name="Lower_Bridge_Nose"
2093 label="Lower Bridge"
2094 wearable="shape"
2095 edit_group="shape_nose"
2096 edit_group_order="5.5"
2097 label_min="Low"
2098 label_max="High"
2099 value_min="-1.5"
2100 value_max="1.5"
2101 camera_elevation=".1"
2102 camera_distance=".35"
2103 camera_angle="70">
2104 <param_morph />
2105 </param>
2106
2107 <param
2108 id="12"
2109 group="0"
2110 name="Jowls"
2111 wearable="shape"
2112 edit_group="shape_chin"
2113 edit_group_order="5"
2114 label_min="Less"
2115 label_max="More"
2116 value_min="-.5"
2117 value_max="2.5"
2118 camera_elevation=".1"
2119 camera_distance=".4"
2120 camera_angle="0">
2121 <param_morph />
2122 </param>
2123
2124 <param
2125 id="13"
2126 group="0"
2127 name="Cleft_Chin_Upper"
2128 label="Upper Chin Cleft"
2129 wearable="shape"
2130 edit_group="shape_chin"
2131 edit_group_order="7"
2132 label_min="Round"
2133 label_max="Cleft"
2134 value_min="0"
2135 value_max="1.5"
2136 camera_elevation="0"
2137 camera_distance=".28"
2138 camera_angle="-20">
2139 <param_morph />
2140 </param>
2141
2142 <param
2143 id="14"
2144 group="0"
2145 name="High_Cheek_Bones"
2146 label="Cheek Bones"
2147 wearable="shape"
2148 edit_group="shape_head"
2149 edit_group_order="10"
2150 label_min="Low"
2151 label_max="High"
2152 value_min="-.5"
2153 value_max="1"
2154 camera_elevation=".1"
2155 camera_distance=".3"
2156 camera_angle="-20">
2157 <param_morph />
2158 </param>
2159
2160 <param
2161 id="15"
2162 group="0"
2163 name="Ears_Out"
2164 label="Ear Angle"
2165 wearable="shape"
2166 edit_group="shape_ears"
2167 edit_group_order="2"
2168 label_min="In"
2169 label_max="Out"
2170 value_min="-.5"
2171 value_max="1.5"
2172 camera_elevation=".1"
2173 camera_distance=".3"
2174 camera_angle="-20">
2175 <param_morph />
2176 </param>
2177
2178 <!--Pointy eyebrows became a driver/driven param with new max value for backwards compatibility between 1.0 and 1.1-->
2179 <param
2180 id="870"
2181 group="1"
2182 name="Pointy_Eyebrows"
2183 label="Eyebrow Points"
2184 wearable="hair"
2185 edit_group="hair_eyebrows"
2186 edit_group_order="4"
2187 label_min="Smooth"
2188 label_max="Pointy"
2189 value_min="-.5"
2190 value_max="1"
2191 camera_elevation=".1"
2192 camera_distance=".3">
2193 <param_morph />
2194 </param>
2195
2196 <param
2197 id="17"
2198 group="0"
2199 name="Square_Jaw"
2200 label="Jaw Shape"
2201 wearable="shape"
2202 edit_group="shape_chin"
2203 edit_group_order="2"
2204 label_min="Pointy"
2205 label_max="Square"
2206 value_min="-.5"
2207 value_max="1"
2208 camera_distance=".3"
2209 camera_elevation=".04"
2210 camera_angle="-20">
2211 <param_morph />
2212 </param>
2213
2214 <param
2215 id="18"
2216 group="0"
2217 name="Puffy_Upper_Cheeks"
2218 label="Upper Cheeks"
2219 wearable="shape"
2220 edit_group="shape_head"
2221 edit_group_order="8"
2222 label_min="Thin"
2223 label_max="Puffy"
2224 value_min="-1.5"
2225 value_max="2.5"
2226 camera_elevation=".1"
2227 camera_distance=".3"
2228 camera_angle="-20">
2229 <param_morph />
2230 </param>
2231
2232 <param
2233 id="19"
2234 group="0"
2235 name="Upturned_Nose_Tip"
2236 label="Nose Tip Angle"
2237 wearable="shape"
2238 edit_group="shape_nose"
2239 edit_group_order="7"
2240 label_min="Downturned"
2241 label_max="Upturned"
2242 value_min="-1.5"
2243 value_max="1"
2244 camera_elevation=".1"
2245 camera_distance=".35"
2246 camera_angle="15">
2247 <param_morph />
2248 </param>
2249
2250 <param
2251 id="20"
2252 group="0"
2253 name="Bulbous_Nose"
2254 label="Nose Thickness"
2255 wearable="shape"
2256 edit_group="shape_nose"
2257 edit_group_order="4"
2258 label_min="Thin Nose"
2259 label_max="Bulbous Nose"
2260 show_simple="true"
2261 value_min="-.5"
2262 value_max="1.5"
2263 camera_elevation=".1"
2264 camera_distance=".3">
2265 <param_morph />
2266 </param>
2267
2268 <param
2269 id="21"
2270 group="0"
2271 name="Upper_Eyelid_Fold"
2272 label="Upper Eyelid Fold"
2273 wearable="shape"
2274 edit_group="shape_eyes"
2275 edit_group_order="5"
2276 label_min="Uncreased"
2277 label_max="Creased"
2278 value_min="-0.2"
2279 value_max="1.3"
2280 camera_elevation=".1"
2281 camera_distance=".35">
2282 <param_morph />
2283 </param>
2284
2285 <param
2286 id="22"
2287 group="0"
2288 name="Attached_Earlobes"
2289 label="Attached Earlobes"
2290 wearable="shape"
2291 edit_group="shape_ears"
2292 edit_group_order="3"
2293 label_min="Unattached"
2294 label_max="Attached"
2295 value_min="0"
2296 value_max="1"
2297 camera_elevation=".1"
2298 camera_distance=".3"
2299 camera_angle="45">
2300 <param_morph />
2301 </param>
2302
2303 <param
2304 id="23"
2305 group="0"
2306 name="Baggy_Eyes"
2307 label="Eye Bags"
2308 wearable="shape"
2309 edit_group="shape_eyes"
2310 edit_group_order="6"
2311 label_min="Smooth"
2312 label_max="Baggy"
2313 value_min="-.5"
2314 value_max="1.5"
2315 camera_elevation=".1"
2316 camera_distance=".35">
2317 <param_morph />
2318 </param>
2319
2320 <param
2321 id="765"
2322 group="0"
2323 name="Puffy_Lower_Lids"
2324 label="Puffy Eyelids"
2325 wearable="shape"
2326 edit_group="shape_eyes"
2327 edit_group_order="6.1"
2328 label_min="Flat"
2329 label_max="Puffy"
2330 value_min="-.3"
2331 value_max="2.5"
2332 camera_elevation=".1"
2333 camera_distance=".35">
2334 <param_morph />
2335 </param>
2336
2337 <param
2338 id="24"
2339 group="0"
2340 name="Wide_Eyes"
2341 label="Eye Opening"
2342 wearable="shape"
2343 edit_group="shape_eyes"
2344 edit_group_order="1.1"
2345 label_min="Narrow"
2346 label_max="Wide"
2347 value_min="-1.5"
2348 value_max="2"
2349 show_simple="true"
2350 camera_elevation=".1"
2351 camera_distance=".35">
2352 <param_morph />
2353 </param>
2354
2355 <param
2356 id="25"
2357 group="0"
2358 name="Wide_Lip_Cleft"
2359 label="Lip Cleft"
2360 wearable="shape"
2361 edit_group="shape_mouth"
2362 edit_group_order="6"
2363 label_min="Narrow"
2364 label_max="Wide"
2365 value_min="-.8"
2366 value_max="1.5"
2367 camera_elevation="0"
2368 camera_distance=".28">
2369 <param_morph />
2370 </param>
2371
2372 <param
2373 id="764"
2374 group="0"
2375 name="Lip_Cleft_Deep"
2376 label="Lip Cleft Depth"
2377 wearable="shape"
2378 edit_group="shape_mouth"
2379 edit_group_order="5.8"
2380 label_min="Shallow"
2381 label_max="Deep"
2382 value_min="-.5"
2383 value_max="1.2"
2384 camera_elevation="0"
2385 camera_distance=".28">
2386 <param_morph />
2387 </param>
2388
2389 <param
2390 id="26"
2391 group="1"
2392 wearable="shape"
2393 name="Lips_Thin"
2394 edit_group="driven"
2395 value_min="0"
2396 value_max=".7">
2397 <param_morph />
2398 </param>
2399
2400 <param
2401 id="27"
2402 group="0"
2403 name="Wide_Nose_Bridge"
2404 label="Bridge Width"
2405 wearable="shape"
2406 edit_group="shape_nose"
2407 edit_group_order="6"
2408 label_min="Narrow"
2409 label_max="Wide"
2410 value_min="-1.3"
2411 value_max="1.2"
2412 camera_elevation=".1"
2413 camera_distance=".3"
2414 camera_angle="-20">
2415 <param_morph />
2416 </param>
2417
2418 <param
2419 id="28"
2420 group="1"
2421 name="Lips_Fat"
2422 wearable="shape"
2423 edit_group="driven"
2424 value_min="0"
2425 value_max="2">
2426 <param_morph />
2427 </param>
2428
2429 <param
2430 id="29"
2431 group="1"
2432 name="Wide_Upper_Lip"
2433 wearable="shape"
2434 edit_group="driven"
2435 value_min="-.7"
2436 value_max="1.3">
2437 <param_morph />
2438 </param>
2439
2440 <param
2441 id="30"
2442 group="1"
2443 name="Wide_Lower_Lip"
2444 wearable="shape"
2445 edit_group="driven"
2446 value_min="-.7"
2447 value_max="1.3">
2448 <param_morph />
2449 </param>
2450
2451 <!--Arced eyebrows became a driver/driven param with new max value for backwards compatibility between 1.0 and 1.1-->
2452 <param
2453 id="872"
2454 group="1"
2455 name="Arced_Eyebrows"
2456 label="Eyebrow Arc"
2457 wearable="hair"
2458 edit_group="hair_eyebrows"
2459 edit_group_order="3"
2460 label_min="Flat"
2461 label_max="Arced"
2462 value_min="0"
2463 value_max="1">
2464 <param_morph />
2465 </param>
2466
2467 <!--Lower eyebrows became a driver/driven param with new min value for backwards compatibility between 1.0 and 1.1-->
2468 <param
2469 id="871"
2470 group="1"
2471 name="Lower_Eyebrows"
2472 label="Eyebrow Height"
2473 show_simple="true"
2474 wearable="hair"
2475 edit_group="hair_eyebrows"
2476 edit_group_order="2.5"
2477 label_min="Higher"
2478 label_max="Lower"
2479 value_min="-2"
2480 value_max="2">
2481 <param_morph />
2482 </param>
2483
2484 <param
2485 id="35"
2486 group="0"
2487 name="Big_Ears"
2488 label="Ear Size"
2489 wearable="shape"
2490 edit_group="shape_ears"
2491 edit_group_order="1"
2492 label_min="Small"
2493 label_max="Large"
2494 value_min="-1"
2495 value_max="2"
2496 camera_elevation=".1"
2497 camera_distance=".3"
2498 camera_angle="45">
2499 <param_morph />
2500 </param>
2501
2502 <param
2503 id="796"
2504 group="0"
2505 name="Pointy_Ears"
2506 label="Ear Tips"
2507 wearable="shape"
2508 edit_group="shape_ears"
2509 edit_group_order="4"
2510 label_min="Flat"
2511 label_max="Pointy"
2512 value_min="-.4"
2513 value_max="3"
2514 camera_elevation=".1"
2515 camera_distance=".3"
2516 camera_angle="45">
2517 <param_morph />
2518 </param>
2519
2520 <param
2521 id="185"
2522 group="0"
2523 name="Deep_Chin"
2524 label="Chin Depth"
2525 wearable="shape"
2526 edit_group="shape_chin"
2527 edit_group_order="3"
2528 label_min="Shallow"
2529 label_max="Deep"
2530 value_min="-1"
2531 value_max="1"
2532 camera_elevation=".1"
2533 camera_distance=".4"
2534 camera_angle="30">
2535 <param_morph />
2536 </param>
2537
2538 <param
2539 id="186"
2540 group="1"
2541 name="Egg_Head"
2542 label="Egg Head"
2543 wearable="shape"
2544 edit_group="shape_head"
2545 label_min="Chin Heavy"
2546 label_max="Forehead Heavy"
2547 value_min="-1.3"
2548 value_max="1"
2549 camera_elevation=".1"
2550 camera_distance=".5"
2551 camera_angle="20">
2552 <param_morph />
2553 </param>
2554
2555 <param
2556 id="187"
2557 group="1"
2558 name="Squash_Stretch_Head"
2559 label="Squash/Stretch Head"
2560 wearable="shape"
2561 edit_group="shape_head"
2562 label_min="Squash Head"
2563 label_max="Stretch Head"
2564 value_min="-.5"
2565 value_max="1"
2566 camera_elevation=".1"
2567 camera_distance=".5"
2568 camera_angle="20">
2569 <param_morph>
2570 <volume_morph
2571 name="HEAD"
2572 scale="-0.008 -0.006 0.015"/>
2573 </param_morph>
2574 </param>
2575
2576 <param
2577 id="188"
2578 group="1"
2579 name="Square_Head"
2580 wearable="shape"
2581 label_min="Less Square"
2582 label_max="More Square"
2583 value_min="0"
2584 value_max=".7"
2585 camera_elevation=".1"
2586 camera_distance=".5"
2587 camera_angle="20">
2588 <param_morph />
2589 </param>
2590
2591 <param
2592 id="189"
2593 group="1"
2594 wearable="shape"
2595 name="Round_Head"
2596 label_min="Less Round"
2597 label_max="More Round"
2598 value_min="0"
2599 value_max="1"
2600 camera_elevation=".1"
2601 camera_distance=".5"
2602 camera_angle="20">
2603 <param_morph />
2604 </param>
2605
2606 <param
2607 id="194"
2608 group="1"
2609 name="Eye_Spread"
2610 wearable="shape"
2611 edit_group="shape_eyes"
2612 label_min="Eyes Together"
2613 label_max="Eyes Spread"
2614 value_min="-2"
2615 value_max="2">
2616 <param_morph />
2617 </param>
2618
2619 <param
2620 id="400"
2621 sex="male"
2622 group="1"
2623 name="Displace_Hair_Facial"
2624 label="Hair Thickess"
2625 wearable="hair"
2626 edit_group="hair_facial"
2627 label_min="Cropped Hair"
2628 label_max="Bushy Hair"
2629 value_min="0"
2630 value_max="2">
2631 <param_morph />
2632 </param>
2633
2634 <param
2635 id="506"
2636 group="0"
2637 name="Mouth_Height"
2638 wearable="shape"
2639 label="Mouth Position"
2640 show_simple="true"
2641 edit_group="shape_mouth"
2642 edit_group_order="4"
2643 label_min="High"
2644 label_max="Low"
2645 value_min="-2"
2646 value_max="2"
2647 camera_distance=".3"
2648 camera_elevation=".04">
2649 <param_morph />
2650 </param>
2651
2652 <param
2653 id="633"
2654 group="1"
2655 name="Fat_Head"
2656 label="Fat Head"
2657 wearable="shape"
2658 edit_group="shape_body"
2659 label_min="Skinny"
2660 label_max="Fat"
2661 value_min="0"
2662 value_max="1"
2663 camera_elevation=".3">
2664 <param_morph/>
2665 </param>
2666
2667 <param
2668 id="630"
2669 group="1"
2670 name="Forehead_Round"
2671 label="Round Forehead"
2672 wearable="shape"
2673 label_min="Less"
2674 label_max="More"
2675 value_min="0"
2676 value_max="1">
2677 <param_morph />
2678 </param>
2679
2680 <param
2681 id="631"
2682 group="1"
2683 name="Forehead_Slant"
2684 label="Slanted Forehead"
2685 wearable="shape"
2686 label_min="Less"
2687 label_max="More"
2688 value_min="0"
2689 value_max="1">
2690 <param_morph />
2691 </param>
2692
2693 <param
2694 id="650"
2695 group="0"
2696 name="Eyelid_Corner_Up"
2697 label="Outer Eye Corner"
2698 wearable="shape"
2699 edit_group="shape_eyes"
2700 edit_group_order="4"
2701 label_min="Corner Down"
2702 label_max="Corner Up"
2703 value_min="-1.3"
2704 value_max="1.2"
2705 camera_elevation=".1"
2706 camera_distance=".30">
2707 <param_morph />
2708 </param>
2709
2710 <param
2711 id="880"
2712 group="0"
2713 name="Eyelid_Inner_Corner_Up"
2714 label="Inner Eye Corner"
2715 wearable="shape"
2716 edit_group="shape_eyes"
2717 edit_group_order="4.2"
2718 label_min="Corner Down"
2719 label_max="Corner Up"
2720 value_min="-1.3"
2721 value_max="1.2"
2722 camera_elevation=".1"
2723 camera_distance=".30">
2724 <param_morph />
2725 </param>
2726
2727
2728 <param
2729 id="653"
2730 group="0"
2731 name="Tall_Lips"
2732 wearable="shape"
2733 label="Lip Fullness"
2734 show_simple="true"
2735 edit_group="shape_mouth"
2736 edit_group_order="2"
2737 label_min="Less Full"
2738 label_max="More Full"
2739 value_min="-1"
2740 value_max="2"
2741 camera_distance=".3"
2742 camera_elevation=".04">
2743 <param_morph />
2744 </param>
2745
2746 <param
2747 id="656"
2748 group="0"
2749 name="Crooked_Nose"
2750 wearable="shape"
2751 label="Crooked Nose"
2752 edit_group="shape_nose"
2753 edit_group_order="9"
2754 label_min="Nose Left"
2755 label_max="Nose Right"
2756 value_min="-2"
2757 value_max="2"
2758 camera_distance=".3"
2759 camera_elevation=".04"
2760 camera_angle="-20">
2761 <param_morph />
2762 </param>
2763
2764 <param
2765 id="657"
2766 group="1"
2767 name="Smile_Mouth"
2768 wearable="shape"
2769 label="Mouth Corner"
2770 edit_group="shape_mouth"
2771 label_min="Corner Normal"
2772 label_max="Corner Up"
2773 value_min="0"
2774 value_max="1.4"
2775 camera_distance=".3"
2776 camera_elevation=".04">
2777 <param_morph />
2778 </param>
2779
2780 <param
2781 id="658"
2782 group="1"
2783 name="Frown_Mouth"
2784 wearable="shape"
2785 label="Mouth Corner"
2786 edit_group="shape_mouth"
2787 label_min="Corner Normal"
2788 label_max="Corner Down"
2789 value_min="0"
2790 value_max="1.2"
2791 camera_distance=".3"
2792 camera_elevation=".04">
2793 <param_morph />
2794 </param>
2795
2796 <param
2797 id="797"
2798 group="1"
2799 name="Fat_Upper_Lip"
2800 wearable="shape"
2801 label="Fat Upper Lip"
2802 edit_group="shape_mouth"
2803 label_min="Normal Upper"
2804 label_max="Fat Upper"
2805 value_min="0"
2806 value_max="1.5"
2807 camera_distance=".3"
2808 camera_elevation=".04">
2809 <param_morph />
2810 </param>
2811
2812 <param
2813 id="798"
2814 group="1"
2815 name="Fat_Lower_Lip"
2816 wearable="shape"
2817 label="Fat Lower Lip"
2818 edit_group="shape_mouth"
2819 label_min="Normal Lower"
2820 label_max="Fat Lower"
2821 value_min="0"
2822 value_max="1.5"
2823 camera_distance=".3"
2824 camera_elevation=".04">
2825 <param_morph />
2826 </param>
2827
2828 <param
2829 id="660"
2830 group="1"
2831 name="Shear_Head"
2832 wearable="shape"
2833 label="Shear Face"
2834 edit_group="shape_head"
2835 label_min="Shear Left"
2836 label_max="Shear Right"
2837 value_min="-2"
2838 value_max="2"
2839 value_default="0"
2840 camera_distance=".5"
2841 camera_elevation=".04">
2842 <param_morph />
2843 </param>
2844
2845 <param
2846 id="770"
2847 group="1"
2848 name="Elongate_Head"
2849 wearable="shape"
2850 label="Shear Face"
2851 edit_group="shape_head"
2852 label_min="Flat Head"
2853 label_max="Long Head"
2854 value_min="-1"
2855 value_max="1"
2856 value_default="0"
2857 camera_distance=".5"
2858 camera_elevation=".04">
2859 <param_morph>
2860 <volume_morph
2861 name="HEAD"
2862 scale="0.02 0.0 0.0"/>
2863 </param_morph>
2864 </param>
2865
2866 <param
2867 id="663"
2868 group="0"
2869 name="Shift_Mouth"
2870 wearable="shape"
2871 label="Shift Mouth"
2872 edit_group="shape_mouth"
2873 edit_group_order="7"
2874 label_min="Shift Left"
2875 label_max="Shift Right"
2876 value_min="-2"
2877 value_max="2"
2878 value_default="0"
2879 camera_distance=".35"
2880 camera_elevation=".04"
2881 camera_angle="-20">
2882 <param_morph />
2883 </param>
2884
2885 <param
2886 id="664"
2887 group="0"
2888 name="Pop_Eye"
2889 wearable="shape"
2890 label="Eye Pop"
2891 edit_group="shape_eyes"
2892 edit_group_order="8"
2893 label_min="Pop Right Eye"
2894 label_max="Pop Left Eye"
2895 value_min="-1.3"
2896 value_max="1.3"
2897 value_default="0"
2898 camera_elevation=".1"
2899 camera_distance=".35">
2900 <param_morph />
2901 </param>
2902
2903 <param
2904 id="760"
2905 group="0"
2906 name="Jaw_Angle"
2907 wearable="shape"
2908 label="Jaw Angle"
2909 edit_group="shape_chin"
2910 edit_group_order="3.5"
2911 label_min="Low Jaw"
2912 label_max="High Jaw"
2913 value_min="-1.2"
2914 value_max="2"
2915 value_default="0"
2916 camera_distance=".5"
2917 camera_elevation=".04"
2918 camera_angle="70">
2919 <param_morph />
2920 </param>
2921
2922 <param
2923 id="665"
2924 group="0"
2925 name="Jaw_Jut"
2926 wearable="shape"
2927 label="Jaw Jut"
2928 edit_group="shape_chin"
2929 edit_group_order="4"
2930 label_min="Overbite"
2931 label_max="Underbite"
2932 value_min="-2"
2933 value_max="2"
2934 value_default="0"
2935 camera_distance=".5"
2936 camera_elevation=".04"
2937 camera_angle="70">
2938 <param_morph />
2939 </param>
2940
2941 <param
2942 id="686"
2943 group="1"
2944 name="Head_Eyes_Big"
2945 wearable="shape"
2946 label="Eye Size"
2947 edit_group="shape_eyes"
2948 label_min="Beady Eyes"
2949 label_max="Anime Eyes"
2950 show_simple="true"
2951 value_min="-2"
2952 value_max="2"
2953 value_default="0">
2954 <param_morph />
2955 </param>
2956
2957 <param
2958 id="767"
2959 group="1"
2960 name="Bug_Eyed_Head"
2961 wearable="shape"
2962 label="Eye Depth"
2963 edit_group="shape_eyes"
2964 edit_group_order="4.5"
2965 label_min="Sunken Eyes"
2966 label_max="Bug Eyes"
2967 value_min="-2"
2968 value_max="2"
2969 value_default="0">
2970 <param_morph />
2971 </param>
2972
2973 <!--
2974 #Fat_Lips = Fat_Lips 34 1 0 1
2975 #Wide_Lips = Wide_Lips 35 1 0 1
2976 #Wide_Nose = Wide_Nose 36 1 0 1
2977 -->
2978 <!--
2979 ##############
2980 # Facial Expression morphs
2981 ##############
2982 -->
2983 <param
2984 id="300"
2985 group="1"
2986 name="Express_Closed_Mouth"
2987 value_default="1"
2988 value_min="0"
2989 value_max="1">
2990 <param_morph />
2991 </param>
2992
2993 <param
2994 id="301"
2995 group="1"
2996 name="Express_Tongue_Out"
2997 value_min="0"
2998 value_max="1">
2999 <param_morph />
3000 </param>
3001
3002 <param
3003 id="302"
3004 group="1"
3005 name="Express_Surprise_Emote"
3006 value_min="0"
3007 value_max="1">
3008 <param_morph />
3009 </param>
3010
3011 <param
3012 id="303"
3013 group="1"
3014 name="Express_Wink_Emote"
3015 value_min="0"
3016 value_max="1">
3017 <param_morph />
3018 </param>
3019
3020 <param
3021 id="304"
3022 group="1"
3023 name="Express_Embarrassed_Emote"
3024 value_min="0"
3025 value_max="1">
3026 <param_morph />
3027 </param>
3028
3029 <param
3030 id="305"
3031 group="1"
3032 name="Express_Shrug_Emote"
3033 value_min="0"
3034 value_max="1">
3035 <param_morph />
3036 </param>
3037
3038 <param
3039 id="306"
3040 group="1"
3041 name="Express_Kiss"
3042 value_min="0"
3043 value_max="1">
3044 <param_morph />
3045 </param>
3046
3047 <param
3048 id="307"
3049 group="1"
3050 name="Express_Bored_Emote"
3051 value_min="0"
3052 value_max="1">
3053 <param_morph />
3054 </param>
3055
3056 <param
3057 id="308"
3058 group="1"
3059 name="Express_Repulsed_Emote"
3060 value_min="0"
3061 value_max="1">
3062 <param_morph />
3063 </param>
3064
3065 <param
3066 id="309"
3067 group="1"
3068 name="Express_Disdain"
3069 value_min="0"
3070 value_max="1">
3071 <param_morph />
3072 </param>
3073
3074 <param
3075 id="310"
3076 group="1"
3077 name="Express_Afraid_Emote"
3078 value_min="0"
3079 value_max="1">
3080 <param_morph />
3081 </param>
3082
3083 <param
3084 id="311"
3085 group="1"
3086 name="Express_Worry_Emote"
3087 value_min="0"
3088 value_max="1">
3089 <param_morph />
3090 </param>
3091
3092 <param
3093 id="312"
3094 group="1"
3095 name="Express_Cry_Emote"
3096 value_min="0"
3097 value_max="1">
3098 <param_morph />
3099 </param>
3100
3101 <param
3102 id="313"
3103 group="1"
3104 name="Express_Sad_Emote"
3105 value_min="0"
3106 value_max="1">
3107 <param_morph />
3108 </param>
3109
3110 <param
3111 id="314"
3112 group="1"
3113 name="Express_Anger_Emote"
3114 value_min="0"
3115 value_max="1">
3116 <param_morph />
3117 </param>
3118
3119 <param
3120 id="315"
3121 group="1"
3122 name="Express_Frown"
3123 value_min="0"
3124 value_max="1">
3125 <param_morph />
3126 </param>
3127
3128 <param
3129 id="316"
3130 group="1"
3131 name="Express_Laugh_Emote"
3132 value_min="0"
3133 value_max="1">
3134 <param_morph />
3135 </param>
3136
3137 <param
3138 id="317"
3139 group="1"
3140 name="Express_Toothsmile"
3141 value_min="0"
3142 value_max="1">
3143 <param_morph />
3144 </param>
3145
3146 <param
3147 id="318"
3148 group="1"
3149 name="Express_Smile"
3150 value_min="0"
3151 value_max="1">
3152 <param_morph />
3153 </param>
3154
3155 <param
3156 id="632"
3157 group="1"
3158 name="Express_Open_Mouth"
3159 value_min="0"
3160 value_max="1">
3161 <param_morph />
3162 </param>
3163
3164 <!--
3165 ##############
3166 # Lipsync morphs
3167 ##############
3168 -->
3169
3170 <param
3171 id="70"
3172 group="1"
3173 name="Lipsync_Aah"
3174 value_min="0"
3175 value_max="1">
3176 <param_morph />
3177 </param>
3178
3179 <param
3180 id="71"
3181 group="1"
3182 name="Lipsync_Ooh"
3183 value_min="0"
3184 value_max="1">
3185 <param_morph />
3186 </param>
3187
3188 <!--
3189 ##############
3190 # other morphs (not user controlled)
3191 ##############
3192 -->
3193 <param
3194 id="40"
3195 group="1"
3196 name="Male_Head"
3197 wearable="shape"
3198 edit_group="driven"
3199 value_min="0"
3200 value_max="1">
3201 <param_morph />
3202 </param>
3203
3204 <param
3205 id="41"
3206 group="1"
3207 name="Old"
3208 value_min="0"
3209 value_max="1">
3210 <param_morph />
3211 </param>
3212
3213 <!--
3214 ##############
3215 # animatable morphs
3216 ##############
3217 -->
3218 <param
3219 id="51"
3220 group="1"
3221 name="Furrowed_Eyebrows"
3222 value_min="0"
3223 value_max="1">
3224 <param_morph />
3225 </param>
3226
3227 <param
3228 id="53"
3229 group="1"
3230 name="Surprised_Eyebrows"
3231 value_min="0"
3232 value_max="1">
3233 <param_morph />
3234 </param>
3235
3236 <param
3237 id="54"
3238 group="1"
3239 name="Worried_Eyebrows"
3240 value_min="0"
3241 value_max="1">
3242 <param_morph />
3243 </param>
3244
3245 <param
3246 id="55"
3247 group="1"
3248 name="Frown_Mouth"
3249 value_min="0"
3250 value_max="1">
3251 <param_morph />
3252 </param>
3253
3254 <param
3255 id="57"
3256 group="1"
3257 name="Smile_Mouth"
3258 value_min="0"
3259 value_max="1">
3260 <param_morph />
3261 </param>
3262
3263 <param
3264 id="58"
3265 group="1"
3266 name="Blink_Left"
3267 value_min="0"
3268 value_max="1">
3269 <param_morph />
3270 </param>
3271
3272 <param
3273 id="59"
3274 group="1"
3275 name="Blink_Right"
3276 value_min="0"
3277 value_max="1">
3278 <param_morph />
3279 </param>
3280
3281 <!--
3282 #end morph targets
3283 -->
3284 </mesh>
3285
3286 <mesh
3287 type="headMesh"
3288 lod="1"
3289 file_name="avatar_head_1.llm"
3290 min_pixel_width="160"
3291 reference="avatar_head.llm">
3292 </mesh>
3293
3294 <mesh
3295 type="headMesh"
3296 lod="2"
3297 file_name="avatar_head_2.llm"
3298 min_pixel_width="80"
3299 reference="avatar_head.llm">
3300 </mesh>
3301
3302 <mesh
3303 type="headMesh"
3304 lod="3"
3305 file_name="avatar_head_3.llm"
3306 min_pixel_width="40"
3307 reference="avatar_head.llm">
3308 </mesh>
3309
3310 <mesh
3311 type="headMesh"
3312 lod="4"
3313 file_name="avatar_head_4.llm"
3314 min_pixel_width="0"
3315 reference="avatar_head.llm">
3316 </mesh>
3317
3318 <mesh
3319 type="eyelashMesh"
3320 lod="0"
3321 file_name="avatar_eyelashes.llm"
3322 min_pixel_width="320">
3323 <param
3324 shared="1"
3325 id="660"
3326 group="1"
3327 name="Shear_Head"
3328 wearable="shape"
3329 label="Shear Face"
3330 edit_group="shape_head"
3331 label_min="Shear Left"
3332 label_max="Shear Right"
3333 value_min="-2"
3334 value_max="2"
3335 value_default="0"
3336 camera_distance=".5"
3337 camera_elevation=".04">
3338 <param_morph />
3339 </param>
3340
3341 <param
3342 shared="1"
3343 id="770"
3344 group="1"
3345 name="Elongate_Head"
3346 wearable="shape"
3347 label="Shear Face"
3348 edit_group="shape_head"
3349 label_min="Flat Head"
3350 label_max="Long Head"
3351 value_min="-1"
3352 value_max="1"
3353 value_default="0"
3354 camera_distance=".5"
3355 camera_elevation=".04">
3356 <param_morph />
3357 </param>
3358
3359 <param
3360 shared="1"
3361 id="664"
3362 group="0"
3363 name="Pop_Eye"
3364 wearable="shape"
3365 label="Eye Pop"
3366 edit_group="shape_eyes"
3367 edit_group_order="8"
3368 label_min="Pop Right Eye"
3369 label_max="Pop Left Eye"
3370 value_min="-2"
3371 value_max="2"
3372 value_default="0"
3373 camera_distance=".5"
3374 camera_elevation=".04"
3375 camera_angle="-20">
3376 <param_morph />
3377 </param>
3378
3379 <param
3380 shared="1"
3381 id="21"
3382 group="0"
3383 name="Upper_Eyelid_Fold"
3384 label="Upper Eyelid Fold"
3385 wearable="shape"
3386 edit_group="shape_eyes"
3387 label_min="Uncreased"
3388 label_max="Creased"
3389 value_min="-0.2"
3390 value_max="1.3"
3391 camera_elevation=".1"
3392 camera_distance=".35">
3393 <param_morph />
3394 </param>
3395
3396 <param
3397 shared="1"
3398 id="24"
3399 group="0"
3400 name="Wide_Eyes"
3401 label="Eye Opening"
3402 wearable="shape"
3403 edit_group="shape_eyes"
3404 label_min="Narrow"
3405 label_max="Wide"
3406 show_simple="true"
3407 value_min="-1.5"
3408 value_max="2"
3409 camera_elevation=".1"
3410 camera_distance=".3">
3411 <param_morph />
3412 </param>
3413
3414 <param
3415 shared="1"
3416 id="186"
3417 group="1"
3418 name="Egg_Head"
3419 label="Egg Head"
3420 wearable="shape"
3421 edit_group="shape_head"
3422 label_min="Chin Heavy"
3423 label_max="Forehead Heavy"
3424 value_min="-1.3"
3425 value_max="1"
3426 camera_elevation=".1"
3427 camera_distance=".5"
3428 camera_angle="20">
3429 <param_morph />
3430 </param>
3431
3432 <param
3433 shared="1"
3434 id="187"
3435 group="1"
3436 name="Squash_Stretch_Head"
3437 label="Squash/Stretch Head"
3438 wearable="shape"
3439 edit_group="shape_head"
3440 label_min="Squash Head"
3441 label_max="Stretch Head"
3442 value_min="-.5"
3443 value_max="1"
3444 camera_elevation=".1"
3445 camera_distance=".5"
3446 camera_angle="20">
3447 <param_morph />
3448 </param>
3449
3450 <param
3451 shared="1"
3452 id="194"
3453 group="1"
3454 name="Eye_Spread"
3455 edit_group="shape_eyes"
3456 label_min="Eyes Together"
3457 label_max="Eyes Spread"
3458 value_min="-2"
3459 value_max="2">
3460 <param_morph />
3461 </param>
3462
3463 <param
3464 id="518"
3465 group="0"
3466 name="Eyelashes_Long"
3467 wearable="shape"
3468 label="Eyelash Length"
3469 edit_group="shape_eyes"
3470 edit_group_order="7"
3471 label_min="Short"
3472 label_max="Long"
3473 value_min="-.3"
3474 value_max="1.5"
3475 camera_elevation=".1"
3476 camera_distance=".30"
3477 camera_angle="-20">
3478 <param_morph />
3479 </param>
3480
3481 <param
3482 shared="1"
3483 id="650"
3484 group="0"
3485 name="Eyelid_Corner_Up"
3486 label="Outer Eye Corner"
3487 wearable="shape"
3488 edit_group="shape_eyes"
3489 label_min="Corner Down"
3490 label_max="Corner Up"
3491 value_min="-1.3"
3492 value_max="1.2"
3493 camera_elevation=".1"
3494 camera_distance=".3">
3495 <param_morph />
3496 </param>
3497
3498
3499 <param
3500 shared="1"
3501 id="880"
3502 group="0"
3503 name="Eyelid_Inner_Corner_Up"
3504 label="Inner Eye Corner"
3505 wearable="shape"
3506 edit_group="shape_eyes"
3507 label_min="Corner Down"
3508 label_max="Corner Up"
3509 value_min="-1.3"
3510 value_max="1.2"
3511 camera_elevation=".1"
3512 camera_distance=".3">
3513 <param_morph />
3514 </param>
3515
3516 <param
3517 shared="1"
3518 id="686"
3519 group="1"
3520 name="Head_Eyes_Big"
3521 wearable="shape"
3522 label="Eye Size"
3523 edit_group="shape_eyes"
3524 label_min="Beady Eyes"
3525 label_max="Anime Eyes"
3526 value_min="-2"
3527 value_max="2"
3528 show_simple="true"
3529 value_default="0">
3530 <param_morph />
3531 </param>
3532
3533 <param
3534 shared="1"
3535 id="767"
3536 group="1"
3537 name="Bug_Eyed_Head"
3538 wearable="shape"
3539 label="Eye Depth"
3540 edit_group="shape_eyes"
3541 edit_group_order="4.5"
3542 label_min="Sunken Eyes"
3543 label_max="Bug Eyes"
3544 value_min="-2"
3545 value_max="2"
3546 value_default="0">
3547 <param_morph />
3548 </param>
3549
3550 <!--
3551 ##############
3552 # Facial Expression morphs
3553 ##############
3554 -->
3555 <param
3556 shared="1"
3557 id="301"
3558 group="1"
3559 name="Express_Tongue_Out"
3560 value_min="0"
3561 value_max="1">
3562 <param_morph />
3563 </param>
3564
3565 <param
3566 shared="1"
3567 id="302"
3568 group="1"
3569 name="Express_Surprise_Emote"
3570 value_min="0"
3571 value_max="1">
3572 <param_morph />
3573 </param>
3574
3575 <param
3576 shared="1"
3577 id="303"
3578 group="1"
3579 name="Express_Wink_Emote"
3580 value_min="0"
3581 value_max="1">
3582 <param_morph />
3583 </param>
3584
3585 <param
3586 shared="1"
3587 id="304"
3588 group="1"
3589 name="Express_Embarrassed_Emote"
3590 value_min="0"
3591 value_max="1">
3592 <param_morph />
3593 </param>
3594
3595 <param
3596 shared="1"
3597 id="305"
3598 group="1"
3599 name="Express_Shrug_Emote"
3600 value_min="0"
3601 value_max="1">
3602 <param_morph />
3603 </param>
3604
3605 <param
3606 shared="1"
3607 id="306"
3608 group="1"
3609 name="Express_Kiss"
3610 value_min="0"
3611 value_max="1">
3612 <param_morph />
3613 </param>
3614
3615 <param
3616 shared="1"
3617 id="307"
3618 group="1"
3619 name="Express_Bored_Emote"
3620 value_min="0"
3621 value_max="1">
3622 <param_morph />
3623 </param>
3624
3625 <param
3626 shared="1"
3627 id="308"
3628 group="1"
3629 name="Express_Repulsed_Emote"
3630 value_min="0"
3631 value_max="1">
3632 <param_morph />
3633 </param>
3634
3635 <param
3636 shared="1"
3637 id="309"
3638 group="1"
3639 name="Express_Disdain"
3640 value_min="0"
3641 value_max="1">
3642 <param_morph />
3643 </param>
3644
3645 <param
3646 shared="1"
3647 id="310"
3648 group="1"
3649 name="Express_Afraid_Emote"
3650 value_min="0"
3651 value_max="1">
3652 <param_morph />
3653 </param>
3654
3655 <param
3656 shared="1"
3657 id="312"
3658 group="1"
3659 name="Express_Cry_Emote"
3660 value_min="0"
3661 value_max="1">
3662 <param_morph />
3663 </param>
3664
3665 <param
3666 shared="1"
3667 id="313"
3668 group="1"
3669 name="Express_Sad_Emote"
3670 value_min="0"
3671 value_max="1">
3672 <param_morph />
3673 </param>
3674
3675 <param
3676 shared="1"
3677 id="314"
3678 group="1"
3679 name="Express_Anger_Emote"
3680 value_min="0"
3681 value_max="1">
3682 <param_morph />
3683 </param>
3684
3685 <param
3686 shared="1"
3687 id="315"
3688 group="1"
3689 name="Express_Frown"
3690 value_min="0"
3691 value_max="1">
3692 <param_morph />
3693 </param>
3694
3695 <param
3696 shared="1"
3697 id="316"
3698 group="1"
3699 name="Express_Laugh_Emote"
3700 value_min="0"
3701 value_max="1">
3702 <param_morph />
3703 </param>
3704
3705 <param
3706 shared="1"
3707 id="317"
3708 group="1"
3709 name="Express_Toothsmile"
3710 value_min="0"
3711 value_max="1">
3712 <param_morph />
3713 </param>
3714
3715 <param
3716 shared="1"
3717 id="318"
3718 group="1"
3719 name="Express_Smile"
3720 value_min="0"
3721 value_max="1">
3722 <param_morph />
3723 </param>
3724
3725 <!--
3726 ##############
3727 # other morphs (not user controlled)
3728 ##############
3729 -->
3730 <param
3731 shared="1"
3732 id="41"
3733 group="1"
3734 name="Old"
3735 value_min="0"
3736 value_max="1">
3737 <param_morph />
3738 </param>
3739
3740 <!--
3741 ##############
3742 # animatable morphs
3743 ##############
3744 -->
3745 <param
3746 shared="1"
3747 id="58"
3748 group="1"
3749 name="Blink_Left"
3750 value_min="0"
3751 value_max="1">
3752 <param_morph />
3753 </param>
3754
3755 <param
3756 shared="1"
3757 id="59"
3758 group="1"
3759 name="Blink_Right"
3760 value_min="0"
3761 value_max="1">
3762 <param_morph />
3763 </param>
3764 </mesh>
3765
3766 <!--
3767 #headMesh2 =
3768 #headMesh3 =
3769 -->
3770 <mesh
3771 type="upperBodyMesh"
3772 lod="0"
3773 file_name="avatar_upper_body.llm"
3774 min_pixel_width="320">
3775 <!--
3776 #begin morph targets
3777 #############
3778 # tweakable morphs
3779 #############
3780 -->
3781 <param
3782 id="104"
3783 group="1"
3784 name="Big_Belly_Torso"
3785 wearable="shape"
3786 edit_group="driven"
3787 value_min="0"
3788 value_max="1">
3789 <param_morph>
3790 <volume_morph
3791 name="BELLY"
3792 scale="0.075 0.04 0.03"
3793 pos="0.07 0 -0.07"/>
3794 </param_morph>
3795 </param>
3796
3797 <param
3798 id="626"
3799 sex="female"
3800 group="1"
3801 name="Big_Chest"
3802 label="Chest Size"
3803 wearable="shape"
3804 edit_group="shape_torso"
3805 label_min="Small"
3806 label_max="Large"
3807 value_min="0"
3808 value_max="1"
3809 camera_elevation=".1"
3810 camera_distance="1"
3811 camera_angle="15">
3812 <param_morph />
3813 </param>
3814
3815 <param
3816 id="627"
3817 sex="female"
3818 group="1"
3819 name="Small_Chest"
3820 label="Chest Size"
3821 wearable="shape"
3822 edit_group="shape_torso"
3823 label_min="Large"
3824 label_max="Small"
3825 value_min="0"
3826 value_max="1"
3827 camera_elevation="0"
3828 camera_distance=".28">
3829 <param_morph />
3830 </param>
3831
3832 <param
3833 id="843"
3834 sex="female"
3835 group="1"
3836 name="No_Chest"
3837 label="Chest Size"
3838 wearable="shape"
3839 edit_group="shape_torso"
3840 label_min="Some"
3841 label_max="None"
3842 value_min="0"
3843 value_max="1"
3844 camera_elevation="0"
3845 camera_distance=".28">
3846 <param_morph />
3847 </param>
3848
3849 <param
3850 id="106"
3851 group="1"
3852 name="Muscular_Torso"
3853 label="Torso Muscles"
3854 show_simple="true"
3855 wearable="shape"
3856 edit_group="shape_torso"
3857 label_min="Regular"
3858 label_max="Muscular"
3859 value_min="0"
3860 value_max="1.4"
3861 camera_elevation=".3"
3862 camera_distance="1.2">
3863 <param_morph>
3864 <volume_morph
3865 name="L_CLAVICLE"
3866 scale="0.02 0.0 0.005"
3867 pos="0.0 0 0.005"/>
3868 <volume_morph
3869 name="L_UPPER_ARM"
3870 scale="0.015 0.0 0.005"
3871 pos="0.015 0 0"/>
3872 <volume_morph
3873 name="L_LOWER_ARM"
3874 scale="0.005 0.0 0.005"
3875 pos="0.005 0 0"/>
3876 <volume_morph
3877 name="R_CLAVICLE"
3878 scale="0.02 0.0 0.005"
3879 pos="0.0 0 0.005"/>
3880 <volume_morph
3881 name="R_UPPER_ARM"
3882 scale="0.015 0.0 0.005"
3883 pos="0.015 0 0"/>
3884 <volume_morph
3885 name="R_LOWER_ARM"
3886 scale="0.005 0.0 0.005"
3887 pos="0.005 0 0"/>
3888 </param_morph>
3889 </param>
3890
3891 <param
3892 id="648"
3893 group="1"
3894 sex="female"
3895 name="Scrawny_Torso"
3896 label="Torso Muscles"
3897 show_simple="true"
3898 wearable="shape"
3899 edit_group="shape_torso"
3900 label_min="Regular"
3901 label_max="Scrawny"
3902 value_min="0"
3903 value_max="1.3"
3904 camera_elevation=".3"
3905 camera_distance="1.2">
3906 <param_morph>
3907 <volume_morph
3908 name="BELLY"
3909 scale="0.0 -0.01 0.0"
3910 pos="0.0 0.0 0"/>
3911 <volume_morph
3912 name="CHEST"
3913 scale="-0.01 -0.01 0.0"
3914 pos="0.01 0.0 0"/>
3915 <volume_morph
3916 name="L_CLAVICLE"
3917 scale="0.0 -0.03 -0.005"
3918 pos="0.0 0 -0.005"/>
3919 <volume_morph
3920 name="L_UPPER_ARM"
3921 scale="-0.01 -0.01 -0.02"
3922 pos="0 0 0"/>
3923 <volume_morph
3924 name="L_LOWER_ARM"
3925 scale="-0.005 0.0 -0.01"
3926 pos="-0.005 0 0"/>
3927 <volume_morph
3928 name="R_CLAVICLE"
3929 scale="0.0 -0.03 -0.005"
3930 pos="0.0 0 -0.005"/>
3931 <volume_morph
3932 name="R_UPPER_ARM"
3933 scale="-0.01 -0.01 -0.02"
3934 pos="0 0 0"/>
3935 <volume_morph
3936 name="R_LOWER_ARM"
3937 scale="-0.005 0.0 -0.01"
3938 pos="-0.005 0 0"/>
3939 </param_morph>
3940 </param>
3941
3942 <param
3943 id="677"
3944 group="1"
3945 sex="male"
3946 name="Scrawny_Torso_Male"
3947 label="Torso Scrawny"
3948 wearable="shape"
3949 edit_group="shape_torso"
3950 label_min="Regular"
3951 label_max="Scrawny"
3952 value_min="0"
3953 value_max="1.3"
3954 camera_elevation=".3"
3955 camera_distance="1.2">
3956 <param_morph>
3957 <volume_morph
3958 name="BELLY"
3959 scale="-0.01 -0.01 0.0"
3960 pos="0.01 0.0 0"/>
3961 <volume_morph
3962 name="CHEST"
3963 scale="-0.02 -0.02 0.0"
3964 pos="0.01 0.0 0"/>
3965 <volume_morph
3966 name="L_CLAVICLE"
3967 scale="0.0 -0.03 -0.005"
3968 pos="0.0 0 -0.005"/>
3969 <volume_morph
3970 name="L_UPPER_ARM"
3971 scale="-0.01 -0.01 -0.02"
3972 pos="0 0 0"/>
3973 <volume_morph
3974 name="L_LOWER_ARM"
3975 scale="-0.005 0.0 -0.01"
3976 pos="-0.005 0 0"/>
3977 <volume_morph
3978 name="R_CLAVICLE"
3979 scale="0.0 -0.03 -0.005"
3980 pos="0.0 0 -0.005"/>
3981 <volume_morph
3982 name="R_UPPER_ARM"
3983 scale="-0.01 -0.01 -0.02"
3984 pos="0 0 0"/>
3985 <volume_morph
3986 name="R_LOWER_ARM"
3987 scale="-0.005 0.0 -0.01"
3988 pos="-0.005 0 0"/>
3989 </param_morph>
3990 </param>
3991
3992 <param
3993 id="634"
3994 group="1"
3995 name="Fat_Torso"
3996 label="Fat Torso"
3997 wearable="shape"
3998 edit_group="shape_body"
3999 label_min="skinny"
4000 label_max="fat"
4001 value_min="0"
4002 value_max="1"
4003 camera_elevation=".3">
4004 <param_morph>
4005 <volume_morph
4006 name="CHEST"
4007 scale="0.02 0.03 0.03"
4008 pos="0 0 -0.03"/>
4009 <volume_morph
4010 name="BELLY"
4011 scale="0.09 0.08 0.07"
4012 pos="0 0 -0.05"/>
4013 <volume_morph
4014 name="L_CLAVICLE"
4015 scale="0.0 0.0 0.015"/>
4016 <volume_morph
4017 name="L_UPPER_ARM"
4018 scale="0.02 0.0 0.02"
4019 pos="0.0 0.0 -0.02"/>
4020 <volume_morph
4021 name="L_LOWER_ARM"
4022 scale="0.01 0.0 0.01"
4023 pos="0.0 0.0 -0.01"/>
4024 <volume_morph
4025 name="R_CLAVICLE"
4026 scale="0.0 0.0 0.015"/>
4027 <volume_morph
4028 name="R_UPPER_ARM"
4029 scale="0.02 0.0 0.02"
4030 pos="0.0 0.0 -0.02"/>
4031 <volume_morph
4032 name="R_LOWER_ARM"
4033 scale="0.01 0.0 0.01"
4034 pos="0.0 0.0 -0.01"/>
4035 <volume_morph
4036 name="NECK"
4037 scale="0.015 0.01 0.0"/>
4038 <volume_morph
4039 name="HEAD"
4040 scale="0.0 0.0 0.01"
4041 pos="0 0 -0.01"/>
4042 </param_morph>
4043 </param>
4044
4045 <param
4046 id="507"
4047 group="0"
4048 sex="female"
4049 name="Breast_Gravity"
4050 label="Breast Buoyancy"
4051 wearable="shape"
4052 edit_group="shape_torso"
4053 edit_group_order="7"
4054 label_min="Less Gravity"
4055 label_max="More Gravity"
4056 value_default="0"
4057 value_min="-1.5"
4058 value_max="2"
4059 camera_elevation=".3"
4060 camera_distance=".8">
4061 <param_morph />
4062 </param>
4063
4064 <param
4065 id="628"
4066 group="1"
4067 name="Displace_Loose_Upperbody"
4068 label="Shirt Fit"
4069 wearable="shirt"
4070 edit_group="driven"
4071 clothing_morph="true"
4072 value_min="0"
4073 value_max="1"
4074 value_default="0">
4075 <param_morph />
4076 </param>
4077
4078 <param
4079 id="840"
4080 group="0"
4081 name="Shirtsleeve_flair"
4082 label="Sleeve Looseness"
4083 show_simple="true"
4084 wearable="shirt"
4085 edit_group="shirt"
4086 edit_group_order="6"
4087 clothing_morph="true"
4088 label_min="Tight Sleeves"
4089 label_max="Loose Sleeves"
4090 value_min="0"
4091 value_max="1.5"
4092 camera_distance="1.8"
4093 camera_angle="30"
4094 camera_elevation="-.3">
4095 <param_morph />
4096 </param>
4097
4098 <param
4099 id="855"
4100 group="1"
4101 name="Love_Handles"
4102 wearable="shape"
4103 edit_group="driven"
4104 value_default="0"
4105 value_min="-1"
4106 value_max="2">
4107 <param_morph>
4108 <volume_morph
4109 name="BELLY"
4110 scale="0.0 0.02 0.0"/>
4111 </param_morph>
4112 </param>
4113
4114 <param
4115 id="684"
4116 group="0"
4117 sex="female"
4118 name="Breast_Female_Cleavage"
4119 label="Breast Cleavage"
4120 wearable="shape"
4121 edit_group="shape_torso"
4122 edit_group_order="8"
4123 label_min="Separate"
4124 label_max="Join"
4125 value_default="0"
4126 value_min="-.3"
4127 value_max="1.3"
4128 camera_elevation=".3"
4129 camera_distance=".8">
4130 <param_morph />
4131 </param>
4132
4133 <param
4134 id="685"
4135 group="0"
4136 sex="male"
4137 name="Chest_Male_No_Pecs"
4138 label="Pectorals"
4139 wearable="shape"
4140 edit_group="shape_torso"
4141 edit_group_order="5"
4142 label_min="Big Pectorals"
4143 label_max="Sunken Chest"
4144 value_default="0"
4145 value_min="-.5"
4146 value_max="1.1"
4147 camera_elevation=".3"
4148 camera_distance="1.2">
4149 <param_morph />
4150 </param>
4151
4152 <!-- ############# #
4153 other morphs (not user controlled)
4154 ############# -->
4155 <param
4156 id="100"
4157 group="1"
4158 name="Male_Torso"
4159 wearable="shape"
4160 edit_group="driven"
4161 label_min="Male_Torso"
4162 value_min="0"
4163 value_max="1">
4164 <param_morph>
4165 <volume_morph
4166 name="CHEST"
4167 scale="0.03 0.04 0.02"
4168 pos="-0.03 0 -0.01"/>
4169 <volume_morph
4170 name="BELLY"
4171 scale="0.03 0.03 0.0"
4172 pos="-0.03 0 0.02"/>
4173 <volume_morph
4174 name="L_CLAVICLE"
4175 scale="0.02 0.0 0.01"
4176 pos="-0.02 0 0"/>
4177 <volume_morph
4178 name="L_UPPER_ARM"
4179 scale="0.01 0.0 0.01"
4180 pos="0.0 0.0 -0.01"/>
4181 <volume_morph
4182 name="L_LOWER_ARM"
4183 scale="0.005 0.0 0.005"
4184 pos="0.0 0.0 -0.005"/>
4185 <volume_morph
4186 name="R_CLAVICLE"
4187 scale="0.02 0.0 0.01"
4188 pos="-0.02 0 0"/>
4189 <volume_morph
4190 name="R_UPPER_ARM"
4191 scale="0.01 0.0 0.01"
4192 pos="0.0 0.0 -0.01"/>
4193 <volume_morph
4194 name="R_LOWER_ARM"
4195 scale="0.005 0.0 0.005"
4196 pos="0.0 0.0 -0.005"/>
4197 <volume_morph
4198 name="NECK"
4199 scale="0.015 0.01 0.0"/>
4200 <volume_morph
4201 name="HEAD"
4202 scale="0.0 0.0 0.01"
4203 pos="0 0 -0.01"/>
4204 </param_morph>
4205 </param>
4206
4207 <!--
4208 ##############
4209 # animatable morphs
4210 ##############
4211 -->
4212 <param
4213 id="101"
4214 group="1"
4215 name="Hands_Relaxed"
4216 value_min="0"
4217 value_max="1">
4218 <param_morph />
4219 </param>
4220
4221 <param
4222 id="102"
4223 group="1"
4224 name="Hands_Point"
4225 value_min="0"
4226 value_max="1">
4227 <param_morph />
4228 </param>
4229
4230 <param
4231 id="103"
4232 group="1"
4233 name="Hands_Fist"
4234 value_min="0"
4235 value_max="1">
4236 <param_morph />
4237 </param>
4238
4239 <param
4240 id="666"
4241 group="1"
4242 name="Hands_Relaxed_L"
4243 value_min="0"
4244 value_max="1">
4245 <param_morph />
4246 </param>
4247
4248 <param
4249 id="667"
4250 group="1"
4251 name="Hands_Point_L"
4252 value_min="0"
4253 value_max="1">
4254 <param_morph />
4255 </param>
4256
4257 <param
4258 id="668"
4259 group="1"
4260 name="Hands_Fist_L"
4261 value_min="0"
4262 value_max="1">
4263 <param_morph />
4264 </param>
4265
4266 <param
4267 id="669"
4268 group="1"
4269 name="Hands_Relaxed_R"
4270 value_min="0"
4271 value_max="1">
4272 <param_morph />
4273 </param>
4274
4275 <param
4276 id="670"
4277 group="1"
4278 name="Hands_Point_R"
4279 value_min="0"
4280 value_max="1">
4281 <param_morph />
4282 </param>
4283
4284 <param
4285 id="671"
4286 group="1"
4287 name="Hands_Fist_R"
4288 value_min="0"
4289 value_max="1">
4290 <param_morph />
4291 </param>
4292
4293 <param
4294 id="672"
4295 group="1"
4296 name="Hands_Typing"
4297 value_min="0"
4298 value_max="1">
4299 <param_morph />
4300 </param>
4301
4302 <param
4303 id="766"
4304 group="1"
4305 name="Hands_Salute_R"
4306 value_min="0"
4307 value_max="1">
4308 <param_morph />
4309 </param>
4310
4311 <param
4312 id="791"
4313 group="1"
4314 name="Hands_Peace_R"
4315 value_min="0"
4316 value_max="1">
4317 <param_morph />
4318 </param>
4319
4320 <param
4321 id="792"
4322 group="1"
4323 name="Hands_Spread_R"
4324 value_min="0"
4325 value_max="1">
4326 <param_morph />
4327 </param>
4328
4329 <!--
4330 #############
4331 # physics morphs (not user controlled)
4332 #############
4333 -->
4334 <param
4335 id="1200"
4336 group="1"
4337 sex="female"
4338 name="Breast_Physics_UpDown_Driven"
4339 wearable="shape"
4340 edit_group="driven"
4341 value_default="0"
4342 value_min="-3"
4343 value_max="3">
4344 <param_morph />
4345 </param>
4346
4347 <param
4348 id="1201"
4349 group="1"
4350 sex="female"
4351 name="Breast_Physics_InOut_Driven"
4352 wearable="shape"
4353 edit_group="driven"
4354 value_default="0"
4355 value_min="-1.25"
4356 value_max="1.25">
4357 <param_morph />
4358 </param>
4359
4360 <param
4361 id="1204"
4362 group="1"
4363 name="Belly_Physics_Torso_UpDown_Driven"
4364 wearable="physics"
4365 cross_wearable="true"
4366 edit_group="driven"
4367 value_default="0"
4368 value_min="-1"
4369 value_max="1">
4370 <param_morph />
4371 </param>
4372
4373 <param
4374 id="1207"
4375 group="1"
4376 name="Breast_Physics_LeftRight_Driven"
4377 wearable="physics"
4378 cross_wearable="true"
4379 edit_group="driven"
4380 value_default="0"
4381 value_min="-2"
4382 value_max="2">
4383 <param_morph />
4384 </param>
4385
4386 <!--
4387 #end morph targets
4388 -->
4389
4390 </mesh>
4391
4392 <mesh
4393 type="upperBodyMesh"
4394 lod="1"
4395 file_name="avatar_upper_body_1.llm"
4396 min_pixel_width="160"
4397 reference="avatar_upper_body.llm">
4398 </mesh>
4399
4400 <mesh
4401 type="upperBodyMesh"
4402 lod="2"
4403 file_name="avatar_upper_body_2.llm"
4404 min_pixel_width="80"
4405 reference="avatar_upper_body.llm">
4406 </mesh>
4407
4408 <mesh
4409 type="upperBodyMesh"
4410 lod="3"
4411 file_name="avatar_upper_body_3.llm"
4412 min_pixel_width="40"
4413 reference="avatar_upper_body.llm">
4414 </mesh>
4415
4416 <mesh
4417 type="upperBodyMesh"
4418 lod="4"
4419 file_name="avatar_upper_body_4.llm"
4420 min_pixel_width="0"
4421 reference="avatar_upper_body.llm">
4422 </mesh>
4423
4424 <!--
4425 #upperBodyMesh2 =
4426 #upperBodyMesh3 =
4427 -->
4428 <mesh
4429 type="lowerBodyMesh"
4430 lod="0"
4431 file_name="avatar_lower_body.llm"
4432 min_pixel_width="320">
4433 <!--
4434 #begin morph targets
4435 #############
4436 # tweakable morphs
4437 #############
4438 -->
4439 <param
4440 id="156"
4441 group="1"
4442 name="Big_Belly_Legs"
4443 wearable="shape"
4444 edit_group="driven"
4445 value_min="0"
4446 value_max="1">
4447 <param_morph />
4448 </param>
4449
4450
4451 <param
4452 id="151"
4453 group="1"
4454 name="Big_Butt_Legs"
4455 label="Butt Size"
4456 wearable="shape"
4457 edit_group="shape_legs"
4458 label_min="Regular"
4459 label_max="Large"
4460 value_min="0"
4461 value_max="1">
4462 <param_morph>
4463 <volume_morph
4464 name="PELVIS"
4465 scale="0.03 0.0 0.02"
4466 pos="-0.03 0 -0.025"/>
4467 </param_morph>
4468 </param>
4469
4470 <param
4471 id="794"
4472 group="1"
4473 name="Small_Butt"
4474 label="Butt Size"
4475 wearable="shape"
4476 edit_group="shape_legs"
4477 label_min="Regular"
4478 label_max="Small"
4479 value_min="0"
4480 value_max="1">
4481 <param_morph>
4482 <volume_morph
4483 name="PELVIS"
4484 scale="-0.01 0.0 0.0"
4485 pos="0.01 0 0.0"/>
4486 </param_morph>
4487 </param>
4488
4489 <param
4490 id="152"
4491 group="1"
4492 name="Muscular_Legs"
4493 label="Leg Muscles"
4494 show_simple="true"
4495 wearable="shape"
4496 edit_group="shape_legs"
4497 label_min="Regular Muscles"
4498 label_max="More Muscles"
4499 value_min="0"
4500 value_max="1.5"
4501 camera_distance="1.3"
4502 camera_elevation="-.5">
4503 <param_morph>
4504 <volume_morph
4505 name="L_UPPER_LEG"
4506 scale="0.015 0.015 0.0"
4507 pos="0.0 0 0.0"/>
4508 <volume_morph
4509 name="L_LOWER_LEG"
4510 scale="0.01 0.01 0.0"
4511 pos="0.0 0 0.0"/>
4512 <volume_morph
4513 name="R_UPPER_LEG"
4514 scale="0.015 0.015 0.0"
4515 pos="0.0 0 0.0"/>
4516 <volume_morph
4517 name="R_LOWER_LEG"
4518 scale="0.01 0.01 0.0"
4519 pos="0.0 0 0.0"/>
4520 </param_morph>
4521 </param>
4522
4523 <param
4524 id="651"
4525 group="1"
4526 name="Scrawny_Legs"
4527 label="Scrawny Leg"
4528 wearable="shape"
4529 edit_group="shape_legs"
4530 label_min="Regular Muscles"
4531 label_max="Less Muscles"
4532 value_min="0"
4533 value_max="1.5"
4534 camera_distance="1.3"
4535 camera_elevation="-.5">
4536 <param_morph>
4537 <volume_morph
4538 name="L_UPPER_LEG"
4539 scale="-0.03 -0.03 0.0"
4540 pos="0.0 0 0.0"/>
4541 <volume_morph
4542 name="L_LOWER_LEG"
4543 scale="-0.015 -0.015 0.0"
4544 pos="0.0 0 0.0"/>
4545 <volume_morph
4546 name="R_UPPER_LEG"
4547 scale="-0.03 -0.03 0.0"
4548 pos="0.0 0 0.0"/>
4549 <volume_morph
4550 name="R_LOWER_LEG"
4551 scale="-0.015 -0.015 0.0"
4552 pos="0.0 0 0.0"/>
4553 </param_morph>
4554 </param>
4555
4556 <param
4557 id="853"
4558 group="1"
4559 name="Bowed_Legs"
4560 label="Knee Angle"
4561 wearable="shape"
4562 value_min="-1"
4563 value_max="1">
4564 <param_morph>
4565 <volume_morph
4566 name="L_UPPER_LEG"
4567 pos="0.0 0.03 0.0"/>
4568 <volume_morph
4569 name="L_LOWER_LEG"
4570 pos="0.0 0.03 0.0"/>
4571 <volume_morph
4572 name="R_UPPER_LEG"
4573 pos="0.0 -0.03 0.0"/>
4574 <volume_morph
4575 name="R_LOWER_LEG"
4576 pos="0.0 -0.03 0.0"/>
4577 </param_morph>
4578 </param>
4579
4580 <param
4581 id="500"
4582 group="1"
4583 name="Shoe_Heel_Height"
4584 label="Heel Height"
4585 wearable="shoes"
4586 edit_group="shoes"
4587 label_min="Low Heels"
4588 label_max="High Heels"
4589 value_min="0"
4590 value_max="1"
4591 camera_distance="1.5"
4592 camera_elevation="-.5">
4593 <param_morph />
4594 </param>
4595
4596 <param
4597 id="501"
4598 group="1"
4599 name="Shoe_Platform_Height"
4600 label="Platform Height"
4601 wearable="shoes"
4602 edit_group="shoes"
4603 label_min="Low Platforms"
4604 label_max="High Platforms"
4605 value_min="0"
4606 value_max="1"
4607 camera_distance="1.5"
4608 camera_elevation="-.5">
4609 <param_morph />
4610 </param>
4611
4612 <param
4613 id="508"
4614 group="0"
4615 name="Shoe_Platform_Width"
4616 label="Platform Width"
4617 wearable="shoes"
4618 edit_group="shoes"
4619 edit_group_order="7"
4620 label_min="Narrow"
4621 label_max="Wide"
4622 value_min="-1"
4623 value_max="2"
4624 camera_angle="15"
4625 camera_distance="1.5"
4626 camera_elevation="-1">
4627 <param_morph />
4628 </param>
4629
4630 <param
4631 id="509"
4632 group="1"
4633 name="Shoe_Heel_Point"
4634 label="Heel Shape"
4635 wearable="shoes"
4636 edit_group="shoes"
4637 label_min="Default Heels"
4638 label_max="Pointy Heels"
4639 value_min="0"
4640 value_max="1"
4641 camera_distance="1.3"
4642 camera_elevation="-.5">
4643 <param_morph />
4644 </param>
4645
4646 <param
4647 id="510"
4648 group="1"
4649 name="Shoe_Heel_Thick"
4650 label="Heel Shape"
4651 wearable="shoes"
4652 edit_group="shoes"
4653 label_min="default Heels"
4654 label_max="Thick Heels"
4655 value_min="0"
4656 value_max="1"
4657 camera_distance="1.3"
4658 camera_elevation="-.5">
4659 <param_morph />
4660 </param>
4661
4662 <param
4663 id="511"
4664 group="1"
4665 name="Shoe_Toe_Point"
4666 label="Toe Shape"
4667 wearable="shoes"
4668 edit_group="shoes"
4669 label_min="Default Toe"
4670 label_max="Pointy Toe"
4671 value_min="0"
4672 value_max="1"
4673 camera_distance="1.3"
4674 camera_elevation="-.5">
4675 <param_morph />
4676 </param>
4677
4678 <param
4679 id="512"
4680 group="1"
4681 name="Shoe_Toe_Square"
4682 label="Toe Shape"
4683 wearable="shoes"
4684 edit_group="shoes"
4685 label_min="Default Toe"
4686 label_max="Square Toe"
4687 value_min="0"
4688 value_max="1"
4689 camera_distance="1.5"
4690 camera_elevation="-.5">
4691 <param_morph />
4692 </param>
4693
4694 <param
4695 id="654"
4696 group="0"
4697 name="Shoe_Toe_Thick"
4698 label="Toe Thickness"
4699 wearable="shoes"
4700 edit_group="shoes"
4701 edit_group_order="5"
4702 label_min="Flat Toe"
4703 label_max="Thick Toe"
4704 value_min="0"
4705 value_max="2"
4706 camera_angle="15"
4707 camera_distance="1.5"
4708 camera_elevation="-1">
4709 <param_morph />
4710 </param>
4711
4712 <param
4713 id="515"
4714 group="0"
4715 name="Foot_Size"
4716 label="Foot Size"
4717 wearable="shape"
4718 edit_group="shape_legs"
4719 edit_group_order="6"
4720 label_min="Small"
4721 label_max="Big"
4722 value_min="-1"
4723 value_max="3"
4724 camera_angle="45"
4725 camera_distance="1.1"
4726 camera_elevation="-1">
4727 <param_morph>
4728 <volume_morph
4729 name="L_FOOT"
4730 scale="0.02 0.01 0.0"
4731 pos="0.01 0 0"/>
4732 <volume_morph
4733 name="R_FOOT"
4734 scale="0.02 0.01 0.0"
4735 pos="0.01 0 0"/>
4736 </param_morph>
4737 </param>
4738
4739 <param
4740 id="516"
4741 group="1"
4742 name="Displace_Loose_Lowerbody"
4743 label="Pants Fit"
4744 wearable="pants"
4745 edit_group="driven"
4746 clothing_morph="true"
4747 value_min="0"
4748 value_max="1"
4749 value_default="0">
4750 <param_morph />
4751 </param>
4752
4753 <param
4754 id="625"
4755 group="0"
4756 name="Leg_Pantflair"
4757 label="Cuff Flare"
4758 show_simple="true"
4759 wearable="pants"
4760 edit_group="pants"
4761 edit_group_order="3"
4762 clothing_morph="true"
4763 label_min="Tight Cuffs"
4764 label_max="Flared Cuffs"
4765 value_min="0"
4766 value_max="1.5"
4767 camera_distance="1.8"
4768 camera_angle="30"
4769 camera_elevation="-.3">
4770 <param_morph />
4771 </param>
4772
4773 <param
4774 id="793"
4775 group="1"
4776 name="Leg_Longcuffs"
4777 label="Longcuffs"
4778 wearable="pants"
4779 edit_group="driven"
4780 clothing_morph="true"
4781 value_min="0"
4782 value_max="3"
4783 value_default="0">
4784 <param_morph />
4785 </param>
4786
4787 <param
4788 id="638"
4789 group="0"
4790 name="Low_Crotch"
4791 label="Pants Crotch"
4792 wearable="pants"
4793 clothing_morph="true"
4794 edit_group="pants"
4795 edit_group_order="4"
4796 label_min="High and Tight"
4797 label_max="Low and Loose"
4798 value_min="0"
4799 value_max="1.3"
4800 camera_distance="1.2"
4801 camera_angle="-20"
4802 camera_elevation="-.3">
4803 <param_morph />
4804 </param>
4805
4806 <param
4807 id="635"
4808 group="1"
4809 name="Fat_Legs"
4810 label="Fat Torso"
4811 wearable="shape"
4812 edit_group="shape_body"
4813 label_min="skinny"
4814 label_max="fat"
4815 value_min="0"
4816 value_max="1">
4817 <param_morph>
4818 <volume_morph
4819 name="PELVIS"
4820 scale="0.03 0.06 0.0"/>
4821 <volume_morph
4822 name="R_UPPER_LEG"
4823 scale="0.02 0.02 0.0"
4824 pos="0.0 -0.02 0.0"/>
4825 <volume_morph
4826 name="R_LOWER_LEG"
4827 scale="0.01 0.01 0.0"/>
4828 <volume_morph
4829 name="L_UPPER_LEG"
4830 scale="0.02 0.02 0.0"
4831 pos="0.0 0.02 0.0"/>
4832 <volume_morph
4833 name="L_LOWER_LEG"
4834 scale="0.01 0.01 0.0"/>
4835 </param_morph>
4836 </param>
4837
4838 <param
4839 id="854"
4840 group="1"
4841 name="Saddlebags"
4842 wearable="shape"
4843 edit_group="driven"
4844 value_min="-.5"
4845 value_max="3">
4846 <param_morph>
4847 <volume_morph
4848 name="PELVIS"
4849 scale="0.0 0.025 0.0"/>
4850 </param_morph>
4851
4852 </param>
4853
4854 <param
4855 id="879"
4856 group="0"
4857 sex="male"
4858 name="Male_Package"
4859 label="Package"
4860 wearable="shape"
4861 edit_group="shape_legs"
4862 edit_group_order="4.6"
4863 label_min="Coin Purse"
4864 label_max="Duffle Bag"
4865 value_default="0"
4866 value_min="-.5"
4867 value_max="2"
4868 camera_angle="60"
4869 camera_distance=".6">
4870 <param_morph />
4871 </param>
4872
4873 <!--
4874 #############
4875 # other morphs (not user controlled)
4876 #############
4877 -->
4878 <param
4879 id="153"
4880 group="1"
4881 name="Male_Legs"
4882 wearable="shape"
4883 edit_group="driven"
4884 value_min="0"
4885 value_max="1">
4886 <param_morph />
4887 </param>
4888
4889 <!--
4890 #############
4891 # physics morphs (not user controlled)
4892 #############
4893 -->
4894 <param
4895 id="1202"
4896 group="1"
4897 name="Belly_Physics_Legs_UpDown_Driven"
4898 wearable="physics"
4899 cross_wearable="true"
4900 edit_group="driven"
4901 value_min="-1"
4902 value_max="1">
4903 <param_morph />
4904 </param>
4905
4906
4907 <param
4908 id="1205"
4909 group="1"
4910 name="Butt_Physics_UpDown_Driven"
4911 wearable="physics"
4912 cross_wearable="true"
4913 edit_group="driven"
4914 value_default="0"
4915 value_min="-1"
4916 value_max="1">
4917 <param_morph />
4918 </param>
4919
4920 <param
4921 id="1206"
4922 group="1"
4923 name="Butt_Physics_LeftRight_Driven"
4924 wearable="physics"
4925 cross_wearable="true"
4926 edit_group="driven"
4927 value_default="0"
4928 value_min="-1"
4929 value_max="1">
4930 <param_morph />
4931 </param>
4932
4933 <!--
4934 #end morph targets
4935 -->
4936
4937 </mesh>
4938
4939 <mesh
4940 type="lowerBodyMesh"
4941 lod="1"
4942 file_name="avatar_lower_body_1.llm"
4943 min_pixel_width="160"
4944 reference="avatar_lower_body.llm">
4945 </mesh>
4946
4947 <mesh
4948 type="lowerBodyMesh"
4949 lod="2"
4950 file_name="avatar_lower_body_2.llm"
4951 min_pixel_width="80"
4952 reference="avatar_lower_body.llm">
4953 </mesh>
4954
4955 <mesh
4956 type="lowerBodyMesh"
4957 lod="3"
4958 file_name="avatar_lower_body_3.llm"
4959 min_pixel_width="40"
4960 reference="avatar_lower_body.llm">
4961 </mesh>
4962
4963 <mesh
4964 type="lowerBodyMesh"
4965 lod="4"
4966 file_name="avatar_lower_body_4.llm"
4967 min_pixel_width="0"
4968 reference="avatar_lower_body.llm">
4969 </mesh>
4970
4971 <!--
4972 #lowerBodyMesh2 =
4973 #lowerBodyMesh3 =
4974 -->
4975 <!--
4976 #eyeLidLeftMesh =
4977 -->
4978 <mesh
4979 type="eyeBallLeftMesh"
4980 lod="0"
4981 file_name="avatar_eye.llm"
4982 min_pixel_width="320">
4983 <!-- begin morph_params -->
4984 <param
4985 id="679"
4986 group="1"
4987 name="Eyeball_Size"
4988 label="Eyeball Size"
4989 wearable="shape"
4990 edit_group="shape_eyes"
4991 label_min="small eye"
4992 label_max="big eye"
4993 value_min="-.25"
4994 value_max=".10">
4995 <param_morph />
4996 </param>
4997
4998 <param
4999 id="687"
5000 group="1"
5001 name="Eyeball_Size"
5002 label="Big Eyeball"
5003 wearable="shape"
5004 edit_group="shape_eyes"
5005 label_min="small eye"
5006 label_max="big eye"
5007 value_min="-.25"
5008 value_max=".25">
5009 <param_morph />
5010 </param>
5011 </mesh>
5012
5013 <mesh
5014 type="eyeBallLeftMesh"
5015 lod="1"
5016 file_name="avatar_eye_1.llm"
5017 min_pixel_width="80">
5018 <!-- begin morph_params -->
5019 <param
5020 id="694"
5021 group="1"
5022 name="Eyeball_Size"
5023 label="Eyeball Size"
5024 wearable="shape"
5025 edit_group="shape_eyes"
5026 label_min="small eye"
5027 label_max="big eye"
5028 value_min="-.25"
5029 value_max=".10">
5030 <param_morph />
5031 </param>
5032
5033 <param
5034 id="695"
5035 group="1"
5036 name="Eyeball_Size"
5037 label="Big Eyeball"
5038 wearable="shape"
5039 edit_group="shape_eyes"
5040 label_min="small eye"
5041 label_max="big eye"
5042 value_min="-.25"
5043 value_max=".25">
5044 <param_morph />
5045 </param>
5046 </mesh>
5047
5048 <!--
5049 #eyeLidRightMesh =
5050 -->
5051 <mesh
5052 type="eyeBallRightMesh"
5053 lod="0"
5054 file_name="avatar_eye.llm"
5055 min_pixel_width="320">
5056 <!-- begin morph_params -->
5057 <param
5058 id="680"
5059 group="1"
5060 name="Eyeball_Size"
5061 label="Eyeball Size"
5062 wearable="shape"
5063 label_min="small eye"
5064 label_max="big eye"
5065 value_min="-.25"
5066 value_max=".10">
5067 <param_morph />
5068 </param>
5069
5070 <param
5071 id="688"
5072 group="1"
5073 name="Eyeball_Size"
5074 label="Big Eyeball"
5075 wearable="shape"
5076 label_min="small eye"
5077 label_max="big eye"
5078 value_min="-.25"
5079 value_max=".25">
5080 <param_morph />
5081 </param>
5082 </mesh>
5083
5084 <mesh
5085 type="eyeBallRightMesh"
5086 lod="1"
5087 file_name="avatar_eye_1.llm"
5088 min_pixel_width="80">
5089 <!-- begin morph_params -->
5090 <param
5091 id="681"
5092 group="1"
5093 name="Eyeball_Size"
5094 label="Eyeball Size"
5095 wearable="shape"
5096 edit_group="shape_eyes"
5097 label_min="small eye"
5098 label_max="big eye"
5099 value_min="-.25"
5100 value_max=".10">
5101 <param_morph />
5102 </param>
5103
5104 <param
5105 id="691"
5106 group="1"
5107 name="Eyeball_Size"
5108 label="Big Eyeball"
5109 wearable="shape"
5110 edit_group="shape_eyes"
5111 label_min="small eye"
5112 label_max="big eye"
5113 value_min="-.25"
5114 value_max=".25">
5115 <param_morph />
5116 </param>
5117 </mesh>
5118
5119 <mesh
5120 type="skirtMesh"
5121 lod="0"
5122 file_name="avatar_skirt.llm"
5123 min_pixel_width="320">
5124 <param
5125 id="845"
5126 group="1"
5127 name="skirt_poofy"
5128 label="poofy skirt"
5129 clothing_morph="true"
5130 wearable="skirt"
5131 edit_group="skirt"
5132 label_min="less poofy"
5133 label_max="more poofy"
5134 value_min="0"
5135 value_max="1.5">
5136 <param_morph />
5137 </param>
5138
5139 <param
5140 id="846"
5141 group="1"
5142 name="skirt_loose"
5143 label="loose skirt"
5144 clothing_morph="true"
5145 wearable="skirt"
5146 edit_group="skirt"
5147 label_min="form fitting"
5148 label_max="loose"
5149 value_min="0"
5150 value_max="1">
5151 <param_morph />
5152 </param>
5153
5154 <param
5155 id="866"
5156 group="1"
5157 name="skirt_tight"
5158 label="tight skirt"
5159 clothing_morph="true"
5160 wearable="skirt"
5161 edit_group="skirt"
5162 label_min="form fitting"
5163 label_max="loose"
5164 value_min="0"
5165 value_max="1">
5166 <param_morph />
5167 </param>
5168
5169 <param
5170 id="867"
5171 group="1"
5172 name="skirt_smallbutt"
5173 label="tight skirt"
5174 clothing_morph="false"
5175 wearable="skirt"
5176 edit_group="skirt"
5177 cross_wearable="true"
5178 label_min="form fitting"
5179 label_max="loose"
5180 value_min="0"
5181 value_max="1">
5182 <param_morph />
5183 </param>
5184
5185 <param
5186 id="848"
5187 group="0"
5188 name="skirt_bustle"
5189 label="bustle skirt"
5190 clothing_morph="true"
5191 wearable="skirt"
5192 edit_group_order="3"
5193 edit_group="skirt"
5194 label_min="no bustle"
5195 label_max="more bustle"
5196 value_min="0"
5197 value_max="2"
5198 value_default=".2"
5199 camera_angle="100"
5200 camera_distance="1.3"
5201 camera_elevation="-.5">
5202 <param_morph />
5203 </param>
5204
5205 <param
5206 id="847"
5207 group="1"
5208 name="skirt_bowlegs"
5209 label="legs skirt"
5210 wearable="skirt"
5211 edit_group="driven"
5212 cross_wearable="true"
5213 value_min="-1"
5214 value_max="1"
5215 value_default="0">
5216 <param_morph />
5217 </param>
5218
5219 <param
5220 id="852"
5221 group="1"
5222 name="skirt_bigbutt"
5223 wearable="skirt"
5224 edit_group="driven"
5225 cross_wearable="true"
5226 label="bigbutt skirt"
5227 label_min="less"
5228 label_max="more"
5229 value_min="0"
5230 value_max="1">
5231 <param_morph />
5232 </param>
5233
5234 <param
5235 id="849"
5236 group="1"
5237 name="skirt_belly"
5238 wearable="skirt"
5239 edit_group="driven"
5240 cross_wearable="true"
5241 label="big belly skirt"
5242 value_min="0"
5243 value_max="1">
5244 <param_morph />
5245 </param>
5246
5247 <param
5248 id="850"
5249 group="1"
5250 wearable="skirt"
5251 edit_group="driven"
5252 cross_wearable="true"
5253 name="skirt_saddlebags"
5254 value_min="-.5"
5255 value_max="3">
5256 <param_morph />
5257 </param>
5258
5259 <param
5260 id="851"
5261 group="1"
5262 name="skirt_chubby"
5263 wearable="skirt"
5264 edit_group="driven"
5265 cross_wearable="true"
5266 label_min="less"
5267 label_max="more"
5268 value_min="0"
5269 value_max="1"
5270 value_default="0">
5271 <param_morph />
5272 </param>
5273
5274 <param
5275 id="856"
5276 group="1"
5277 name="skirt_lovehandles"
5278 wearable="skirt"
5279 edit_group="driven"
5280 cross_wearable="true"
5281 label_min="less"
5282 label_max="more"
5283 value_min="-1"
5284 value_max="2"
5285 value_default="0">
5286 <param_morph />
5287 </param>
5288
5289 <!--
5290 #############
5291 # other morphs (not user controlled)
5292 #############
5293 -->
5294 <param
5295 id="857"
5296 group="1"
5297 name="skirt_male"
5298 wearable="skirt"
5299 edit_group="driven"
5300 cross_wearable="true"
5301 value_min="0"
5302 value_max="1">
5303 <param_morph />
5304 </param>
5305
5306 <!--
5307 #############
5308 # physics morphs (not user controlled)
5309 #############
5310 -->
5311 <param
5312 id="1203"
5313 group="1"
5314 name="Belly_Physics_Skirt_UpDown_Driven"
5315 wearable="physics"
5316 cross_wearable="true"
5317 edit_group="driven"
5318 value_default="0"
5319 value_min="-1"
5320 value_max="1">
5321 <param_morph />
5322 </param>
5323
5324 </mesh>
5325
5326 <mesh
5327 type="skirtMesh"
5328 lod="1"
5329 file_name="avatar_skirt_1.llm"
5330 min_pixel_width="160"
5331 reference="avatar_skirt.llm">
5332 </mesh>
5333
5334 <mesh
5335 type="skirtMesh"
5336 lod="2"
5337 file_name="avatar_skirt_2.llm"
5338 min_pixel_width="80"
5339 reference="avatar_skirt.llm">
5340 </mesh>
5341
5342 <mesh
5343 type="skirtMesh"
5344 lod="3"
5345 file_name="avatar_skirt_3.llm"
5346 min_pixel_width="40"
5347 reference="avatar_skirt.llm">
5348 </mesh>
5349
5350 <mesh
5351 type="skirtMesh"
5352 lod="4"
5353 file_name="avatar_skirt_4.llm"
5354 min_pixel_width="0"
5355 reference="avatar_skirt.llm">
5356 </mesh>
5357
5358 <!-- =========================================================== -->
5359 <global_color
5360 name="skin_color">
5361 <param
5362 id="111"
5363 group="0"
5364 wearable="skin"
5365 edit_group="skin_color"
5366 edit_group_order="1"
5367 name="Pigment"
5368 show_simple="true"
5369 label_min="Light"
5370 label_max="Dark"
5371 value_min="0"
5372 value_max="1"
5373 value_default=".5">
5374 <param_color>
5375 <value
5376 color="252, 215, 200, 255" />
5377
5378 <value
5379 color="240, 177, 112, 255" />
5380
5381 <value
5382 color="90, 40, 16, 255" />
5383
5384 <value
5385 color="29, 9, 6, 255" />
5386 </param_color>
5387 </param>
5388
5389 <param
5390 id="110"
5391 group="0"
5392 wearable="skin"
5393 edit_group="skin_color"
5394 edit_group_order="2"
5395 name="Red Skin"
5396 label="Ruddiness"
5397 label_min="Pale"
5398 label_max="Ruddy"
5399 value_min="0"
5400 value_max="0.1">
5401 <param_color
5402 operation="blend">
5403 <value
5404 color="218, 41, 37, 255" />
5405 </param_color>
5406 </param>
5407
5408 <param
5409 id="108"
5410 group="0"
5411 wearable="skin"
5412 edit_group="skin_color"
5413 edit_group_order="3"
5414 name="Rainbow Color"
5415 show_simple="true"
5416 label_min="None"
5417 label_max="Wild"
5418 value_min="0"
5419 value_max="1"
5420 camera_elevation=".1"
5421 camera_distance=".5">
5422 <param_color>
5423 <value
5424 color=" 0, 0, 0, 255" />
5425
5426 <value
5427 color="255, 0, 255, 255" />
5428
5429 <value
5430 color="255, 0, 0, 255" />
5431
5432 <value
5433 color="255, 255, 0, 255" />
5434
5435 <value
5436 color=" 0, 255, 0, 255" />
5437
5438 <value
5439 color=" 0, 255, 255, 255" />
5440
5441 <value
5442 color=" 0, 0, 255, 255" />
5443
5444 <value
5445 color="255, 0, 255, 255" />
5446 </param_color>
5447 </param>
5448 </global_color>
5449
5450 <!-- =========================================================== -->
5451 <global_color
5452 name="hair_color">
5453 <param
5454 id="114"
5455 group="0"
5456 wearable="hair"
5457 edit_group="hair_color"
5458 edit_group_order="3"
5459 name="Blonde Hair"
5460 show_simple="true"
5461 label_min="Black"
5462 label_max="Blonde"
5463 value_min="0"
5464 value_max="1"
5465 value_default=".5"
5466 camera_elevation=".1"
5467 camera_distance=".5">
5468 <param_color>
5469 <value
5470 color="0, 0, 0, 255" />
5471
5472 <value
5473 color="22, 6, 6, 255" />
5474
5475 <value
5476 color="29, 9, 6, 255" />
5477
5478 <value
5479 color="45, 21, 11, 255" />
5480
5481 <value
5482 color="78, 39, 11, 255" />
5483
5484 <value
5485 color="90, 53, 16, 255" />
5486
5487 <value
5488 color="136, 92, 21, 255" />
5489
5490 <value
5491 color="150, 106, 33, 255" />
5492
5493 <value
5494 color="198, 156, 74, 255" />
5495
5496 <value
5497 color="233, 192, 103, 255" />
5498
5499 <value
5500 color="238, 205, 136, 255" />
5501 </param_color>
5502 </param>
5503
5504 <param
5505 id="113"
5506 group="0"
5507 wearable="hair"
5508 edit_group="hair_color"
5509 edit_group_order="4"
5510 name="Red Hair"
5511 show_simple="true"
5512 label_min="No Red"
5513 label_max="Very Red"
5514 value_min="0"
5515 value_max="1"
5516 camera_elevation=".1"
5517 camera_distance=".5">
5518 <param_color>
5519 <value
5520 color="0, 0, 0, 255" />
5521
5522 <value
5523 color="118, 47, 19, 255" />
5524 </param_color>
5525 </param>
5526
5527 <param
5528 id="115"
5529 group="0"
5530 wearable="hair"
5531 edit_group="hair_color"
5532 edit_group_order="1"
5533 name="White Hair"
5534 show_simple="true"
5535 label_min="No White"
5536 label_max="All White"
5537 value_min="0"
5538 value_max="1"
5539 camera_elevation=".1"
5540 camera_distance=".5">
5541 <param_color>
5542 <value
5543 color="0, 0, 0, 255" />
5544
5545 <value
5546 color="255, 255, 255, 255" />
5547 </param_color>
5548 </param>
5549
5550 <param
5551 id="112"
5552 group="0"
5553 wearable="hair"
5554 edit_group="hair_color"
5555 edit_group_order="2"
5556 name="Rainbow Color"
5557 show_simple="true"
5558 label_min="None"
5559 label_max="Wild"
5560 value_min="0"
5561 value_max="1"
5562 camera_elevation=".1"
5563 camera_distance=".5">
5564 <param_color>
5565 <value
5566 color=" 0, 0, 0, 255" />
5567
5568 <value
5569 color="255, 0, 255, 255" />
5570
5571 <value
5572 color="255, 0, 0, 255" />
5573
5574 <value
5575 color="255, 255, 0, 255" />
5576
5577 <value
5578 color=" 0, 255, 0, 255" />
5579
5580 <value
5581 color=" 0, 255, 255, 255" />
5582
5583 <value
5584 color=" 0, 0, 255, 255" />
5585
5586 <value
5587 color="255, 0, 255, 255" />
5588 </param_color>
5589 </param>
5590 </global_color>
5591
5592 <!-- =========================================================== -->
5593 <global_color
5594 name="eye_color">
5595 <param
5596 id="99"
5597 group="0"
5598 wearable="eyes"
5599 edit_group="eyes"
5600 edit_group_order="1"
5601 name="Eye Color"
5602 show_simple="true"
5603 label_min="Natural"
5604 label_max="Unnatural"
5605 value_min="0"
5606 value_max="1"
5607 value_default="0"
5608 camera_elevation=".1"
5609 camera_distance=".3">
5610 <!-- default to natural brown eyes-->
5611 <param_color>
5612 <value
5613 color="50, 25, 5, 255" />
5614
5615 <!-- natural dark brown eyes-->
5616 <value
5617 color="109, 55, 15, 255" />
5618
5619 <!-- natural brown eyes-->
5620 <value
5621 color="150, 93, 49, 255" />
5622
5623 <!-- natural light brown eyes-->
5624 <value
5625 color="152, 118, 25, 255" />
5626
5627 <!--natural hazel eyes-->
5628 <value
5629 color="95, 179, 107, 255" />
5630
5631 <!--natural green eyes-->
5632 <value
5633 color="87, 192, 191, 255" />
5634
5635 <!--natural aqua eyes-->
5636 <value
5637 color="95, 172, 179, 255" />
5638
5639 <!--natural blue eyes-->
5640 <value
5641 color="128, 128, 128, 255" />
5642
5643 <!--natural grey eyes-->
5644 <value
5645 color="0, 0, 0, 255" />
5646
5647 <!--black eyes-->
5648 <value
5649 color="255, 255, 0, 255" />
5650
5651 <!--bright yellow eyes-->
5652 <value
5653 color=" 0, 255, 0, 255" />
5654
5655 <!-- bright green eyes-->
5656 <value
5657 color=" 0, 255, 255, 255" />
5658
5659 <!-- bright cyan eyes-->
5660 <value
5661 color=" 0, 0, 255, 255" />
5662
5663 <!--bright blue eyes-->
5664 <value
5665 color="255, 0, 255, 255" />
5666
5667 <!-- bright violet eyes-->
5668 <value
5669 color="255, 0, 0, 255" />
5670
5671 <!--bright red eyes-->
5672 </param_color>
5673 </param>
5674
5675 <param
5676 id="98"
5677 group="0"
5678 wearable="eyes"
5679 edit_group="eyes"
5680 edit_group_order="2"
5681 name="Eye Lightness"
5682 show_simple="true"
5683 label_min="Darker"
5684 label_max="Lighter"
5685 value_min="0"
5686 value_max="1"
5687 camera_elevation=".1"
5688 camera_distance=".3">
5689 <param_color>
5690 <value
5691 color="0, 0, 0, 0" />
5692
5693 <value
5694 color="255, 255, 255, 255" />
5695 </param_color>
5696 </param>
5697 </global_color>
5698
5699 <!-- =========================================================== -->
5700 <layer_set
5701 body_region="hair"
5702 width="512"
5703 height="512"
5704 clear_alpha="false">
5705 <layer
5706 name="base"
5707 global_color="hair_color"
5708 write_all_channels="true">
5709 <texture
5710 local_texture="hair_grain" />
5711 </layer>
5712
5713 <layer
5714 name="hair texture alpha layer"
5715 visibility_mask="TRUE">
5716 <texture
5717 local_texture="hair_grain" />
5718 </layer>
5719
5720 <layer
5721 name="hair alpha"
5722 visibility_mask="TRUE">
5723 <texture
5724 local_texture="hair_alpha" />
5725 </layer>
5726
5727 </layer_set>
5728 <!-- =========================================================== -->
5729
5730 <layer_set
5731 body_region="head"
5732 width="512"
5733 height="512">
5734 <layer
5735 name="head bump base"
5736 fixed_color = "128,128,128,255"
5737 render_pass="bump">
5738 </layer>
5739
5740 <layer
5741 name="head bump definition"
5742 render_pass="bump">
5743
5744
5745 <texture
5746 tga_file="bump_head_base.tga"
5747 file_is_mask="FALSE"/>
5748
5749 <param
5750 id="873"
5751 group="1"
5752 wearable="skin"
5753 edit_group="driven"
5754 edit_group_order="12"
5755 name="Bump base"
5756 value_min="0"
5757 value_max="1">
5758 <param_alpha
5759 domain="0" />
5760 </param>
5761 </layer>
5762
5763 <layer
5764 name="base"
5765 global_color="skin_color">
5766 <texture
5767 tga_file="head_skingrain.tga" />
5768 </layer>
5769
5770 <layer
5771 name="headcolor">
5772 <texture
5773 tga_file="head_color.tga" />
5774 </layer>
5775
5776 <layer
5777 name="shadow">
5778 <texture
5779 tga_file="head_shading_alpha.tga"
5780 file_is_mask="TRUE" />
5781
5782 <param
5783 id="158"
5784 group="1"
5785 wearable="skin"
5786 name="Shading"
5787 value_min="0"
5788 value_max="1">
5789 <param_color>
5790 <value
5791 color="0, 0, 0, 0" />
5792
5793 <value
5794 color="0, 0, 0, 128" />
5795 </param_color>
5796 </param>
5797 </layer>
5798
5799 <layer
5800 name="highlight">
5801 <texture
5802 tga_file="head_highlights_alpha.tga"
5803file_is_mask="TRUE" />
5804
5805
5806 <param
5807 id="159"
5808 group="1"
5809 name="Shading"
5810 wearable="skin"
5811 value_min="0"
5812 value_max="1">
5813 <param_color>
5814 <value
5815color="255, 255, 255, 0" />
5816
5817
5818 <value
5819 color="255, 255, 255, 64" />
5820 </param_color>
5821 </param>
5822 </layer>
5823 <layer
5824 name="rosyface">
5825 <texture
5826 tga_file="rosyface_alpha.tga"
5827 file_is_mask="true" />
5828
5829 <param
5830 id="116"
5831 group="0"
5832 wearable="skin"
5833 edit_group="skin_facedetail"
5834 edit_group_order="4"
5835 name="Rosy Complexion"
5836 label_min="Less Rosy"
5837 label_max="More Rosy"
5838 value_min="0"
5839 value_max="1"
5840 camera_distance=".3"
5841 camera_elevation=".07">
5842 <param_color>
5843 <value
5844 color="198, 71, 71, 0" />
5845
5846 <value
5847 color="198, 71, 71, 255" />
5848 </param_color>
5849 </param>
5850 </layer>
5851
5852 <layer
5853 name="lips">
5854 <texture
5855 tga_file="lips_mask.tga"
5856 file_is_mask="true" />
5857
5858 <param
5859 id="117"
5860 group="0"
5861 wearable="skin"
5862 edit_group="skin_facedetail"
5863 edit_group_order="5"
5864 name="Lip Pinkness"
5865 label_min="Darker"
5866 label_max="Pinker"
5867 value_min="0"
5868 value_max="1"
5869 camera_distance=".25">
5870 <param_color>
5871 <value
5872 color="220, 115, 115, 0" />
5873
5874 <value
5875 color="220, 115, 115, 128" />
5876 </param_color>
5877 </param>
5878 </layer>
5879
5880 <layer
5881 name="wrinkles_shading"
5882 render_pass="bump"
5883 fixed_color="0,0,0,100">
5884 <param
5885 id="118"
5886 group="1"
5887 wearable="skin"
5888 name="Wrinkles"
5889 value_min="0"
5890 value_max="1">
5891 <param_alpha
5892 tga_file="bump_face_wrinkles.tga"
5893 skip_if_zero="true"
5894 domain="0.3" />
5895 </param>
5896 </layer>
5897
5898 <!--<layer
5899 name="wrinkles_highlights"
5900 fixed_color="255,255,255,64">
5901 <param
5902 id="128"
5903 group="1"
5904 name="Wrinkles"
5905 value_min="0"
5906 value_max="1">
5907 <param_alpha
5908 tga_file="head_wrinkles_highlights_alpha.tga"
5909 skip_if_zero="true"
5910 domain="0.3" />
5911 </param>
5912 </layer>-->
5913 <layer
5914 name="freckles"
5915 fixed_color="120,47,20,128">
5916 <param
5917 id="165"
5918 group="0"
5919 wearable="skin"
5920 edit_group="skin_facedetail"
5921 edit_group_order="2"
5922 name="Freckles"
5923 label_min="Less"
5924 label_max="More"
5925 value_min="0"
5926 value_max="1"
5927 camera_distance=".3"
5928camera_elevation=".07">
5929 <param_alpha
5930 tga_file="freckles_alpha.tga"
5931 skip_if_zero="true"
5932domain="0.5" />
5933 </param>
5934 </layer>
5935 <layer
5936name="eyebrowsbump"
5937render_pass="bump">
5938 <texture
5939 tga_file="head_hair.tga"
5940 file_is_mask="false" />
5941
5942 <param
5943 id="1000"
5944 group="1"
5945 wearable="hair"
5946 edit_group="driven"
5947 name="Eyebrow Size Bump"
5948 value_min="0"
5949 value_max="1">
5950 <param_alpha
5951 tga_file="eyebrows_alpha.tga"
5952 domain="0.1" />
5953 </param>
5954
5955 <param
5956 id="1002"
5957 group="1"
5958 wearable="hair"
5959 edit_group="driven"
5960 name="Eyebrow Density Bump"
5961 value_min="0"
5962 value_max="1">
5963 <param_color>
5964 <value
5965 color="255,255,255,0" />
5966
5967 <value
5968 color="255,255,255,255" />
5969 </param_color>
5970 </param>
5971 </layer>
5972
5973 <layer
5974 name="eyebrows"
5975 global_color="hair_color">
5976 <texture
5977 tga_file="head_hair.tga"
5978 file_is_mask="false" />
5979
5980 <param
5981 id="1001"
5982 group="1"
5983 wearable="hair"
5984 edit_group="hair_eyebrows"
5985 name="Eyebrow Size"
5986 show_simple="true"
5987 value_min="0"
5988 value_max="1"
5989 value_default="0.5">
5990 <param_alpha
5991 tga_file="eyebrows_alpha.tga"
5992 domain="0.1" />
5993 </param>
5994
5995 <param
5996 id="1003"
5997 group="1"
5998 wearable="hair"
5999 edit_group="driven"
6000 name="Eyebrow Density"
6001 value_min="0"
6002 value_max="1">
6003 <param_color
6004 operation="multiply">
6005 <value
6006 color="255,255,255,0" />
6007
6008 <value
6009 color="255,255,255,255" />
6010 </param_color>
6011 </param>
6012 </layer>
6013
6014 <layer
6015 name="lipstick">
6016 <param
6017 id="700"
6018 group="0"
6019 wearable="skin"
6020 edit_group="skin_makeup"
6021 edit_group_order="2"
6022 name="Lipstick Color"
6023 label_min="Pink"
6024 label_max="Black"
6025 value_min="0"
6026 value_max="1"
6027 value_default=".25"
6028 camera_distance=".25">
6029 <param_color>
6030 <value
6031 color="245,161,177,200" />
6032
6033 <value
6034 color="216,37,67,200" />
6035
6036 <value
6037 color="178,48,76,200" />
6038
6039 <value
6040 color="68,0,11,200" />
6041
6042 <value
6043 color="252,207,184,200" />
6044
6045 <value
6046 color="241,136,106,200" />
6047
6048 <value
6049 color="208,110,85,200" />
6050
6051 <value
6052 color="106,28,18,200" />
6053
6054 <value
6055 color="58,26,49,200" />
6056
6057 <value
6058 color="14,14,14,200" />
6059 </param_color>
6060 </param>
6061
6062 <param
6063 id="701"
6064 group="0"
6065 wearable="skin"
6066 edit_group="skin_makeup"
6067 edit_group_order="1"
6068 name="Lipstick"
6069 label_min="No Lipstick"
6070 label_max="More Lipstick"
6071 value_min="0"
6072 value_max=".9"
6073 value_default="0.0"
6074 camera_distance=".25">
6075 <param_alpha
6076 tga_file="lipstick_alpha.tga"
6077 skip_if_zero="true"
6078 domain="0.05" />
6079 </param>
6080 </layer>
6081
6082 <layer
6083 name="lipgloss"
6084 fixed_color="255,255,255,190">
6085 <param
6086 id="702"
6087 name="Lipgloss"
6088 label_min="No Lipgloss"
6089 label_max="Glossy"
6090 wearable="skin"
6091 edit_group="skin_makeup"
6092 edit_group_order="3"
6093 group="0"
6094 value_min="0"
6095 value_max="1"
6096 camera_distance=".25">
6097 <param_alpha
6098 tga_file="lipgloss_alpha.tga"
6099 skip_if_zero="true"
6100 domain="0.2" />
6101 </param>
6102 </layer>
6103
6104 <layer
6105 name="blush">
6106 <param
6107 id="704"
6108 group="0"
6109 wearable="skin"
6110 edit_group="skin_makeup"
6111 edit_group_order="4"
6112 name="Blush"
6113 label_min="No Blush"
6114 label_max="More Blush"
6115 value_min="0"
6116 value_max=".9"
6117 value_default="0"
6118 camera_distance=".3"
6119 camera_elevation=".07"
6120 camera_angle="20">
6121 <param_alpha
6122 tga_file="blush_alpha.tga"
6123 skip_if_zero="true"
6124 domain="0.3" />
6125 </param>
6126
6127 <param
6128 id="705"
6129 group="0"
6130 wearable="skin"
6131 edit_group="skin_makeup"
6132 edit_group_order="5"
6133 name="Blush Color"
6134 label_min="Pink"
6135 label_max="Orange"
6136 value_min="0"
6137 value_max="1"
6138 value_default=".5"
6139 camera_distance=".3"
6140 camera_elevation=".07"
6141 camera_angle="20">
6142 <param_color>
6143 <value
6144 color="253,162,193,200" />
6145
6146 <value
6147 color="247,131,152,200" />
6148
6149 <value
6150 color="213,122,140,200" />
6151
6152 <value
6153 color="253,152,144,200" />
6154
6155 <value
6156 color="236,138,103,200" />
6157
6158 <value
6159 color="195,128,122,200" />
6160
6161 <value
6162 color="148,103,100,200" />
6163
6164 <value
6165 color="168,95,62,200" />
6166 </param_color>
6167 </param>
6168
6169 <param
6170 id="711"
6171 group="0"
6172 wearable="skin"
6173 edit_group="skin_makeup"
6174 edit_group_order="6"
6175 name="Blush Opacity"
6176 label_min="Clear"
6177 label_max="Opaque"
6178 value_min="0"
6179 value_max="1"
6180 value_default=".5"
6181 camera_distance=".3"
6182 camera_elevation=".07"
6183 camera_angle="20">
6184 <param_color
6185 operation="multiply">
6186 <value
6187 color="255,255,255,0" />
6188
6189 <value
6190 color="255,255,255,255" />
6191 </param_color>
6192 </param>
6193 </layer>
6194
6195 <layer
6196 name="Outer Eye Shadow">
6197 <param
6198 id="708"
6199 group="0"
6200 wearable="skin"
6201 edit_group="skin_makeup"
6202 edit_group_order="11"
6203 name="Out Shdw Color"
6204 label_min="Light"
6205 label_max="Dark"
6206 value_min="0"
6207 value_max="1"
6208 camera_distance=".3"
6209 camera_elevation=".14">
6210 <param_color>
6211 <value
6212 color="252,247,246,255" />
6213
6214 <value
6215 color="255,206,206,255" />
6216
6217 <value
6218 color="233,135,149,255" />
6219
6220 <value
6221 color="220,168,192,255" />
6222
6223 <value
6224 color="228,203,232,255" />
6225
6226 <value
6227 color="255,234,195,255" />
6228
6229 <value
6230 color="230,157,101,255" />
6231
6232 <value
6233 color="255,147,86,255" />
6234
6235 <value
6236 color="228,110,89,255" />
6237
6238 <value
6239 color="228,150,120,255" />
6240
6241 <value
6242 color="223,227,213,255" />
6243
6244 <value
6245 color="96,116,87,255" />
6246
6247 <value
6248 color="88,143,107,255" />
6249
6250 <value
6251 color="194,231,223,255" />
6252
6253 <value
6254 color="207,227,234,255" />
6255
6256 <value
6257 color="41,171,212,255" />
6258
6259 <value
6260 color="180,137,130,255" />
6261
6262 <value
6263 color="173,125,105,255" />
6264
6265 <value
6266 color="144,95,98,255" />
6267
6268 <value
6269 color="115,70,77,255" />
6270
6271 <value
6272 color="155,78,47,255" />
6273
6274 <value
6275 color="239,239,239,255" />
6276
6277 <value
6278 color="194,194,194,255" />
6279
6280 <value
6281 color="120,120,120,255" />
6282
6283 <value
6284 color="10,10,10,255" />
6285 </param_color>
6286 </param>
6287
6288 <param
6289 id="706"
6290 group="0"
6291 wearable="skin"
6292 edit_group="skin_makeup"
6293 edit_group_order="12"
6294 name="Out Shdw Opacity"
6295 label_min="Clear"
6296 label_max="Opaque"
6297 value_min=".2"
6298 value_max="1"
6299 value_default=".6"
6300 camera_distance=".3"
6301 camera_elevation=".14">
6302 <param_color
6303 operation="multiply">
6304 <value
6305 color="255,255,255,0" />
6306
6307 <value
6308 color="255,255,255,255" />
6309 </param_color>
6310 </param>
6311
6312 <param
6313 id="707"
6314 group="0"
6315 wearable="skin"
6316 edit_group="skin_makeup"
6317 edit_group_order="10"
6318 name="Outer Shadow"
6319 label_min="No Eyeshadow"
6320 label_max="More Eyeshadow"
6321 value_min="0"
6322 value_max=".7"
6323 camera_distance=".3"
6324 camera_elevation=".14">
6325 <param_alpha
6326 tga_file="eyeshadow_outer_alpha.tga"
6327 skip_if_zero="true"
6328 domain="0.05" />
6329 </param>
6330 </layer>
6331
6332 <layer
6333 name="Inner Eye Shadow">
6334 <param
6335 id="712"
6336 group="0"
6337 wearable="skin"
6338 edit_group="skin_makeup"
6339 edit_group_order="8"
6340 name="In Shdw Color"
6341 label_min="Light"
6342 label_max="Dark"
6343 value_min="0"
6344 value_max="1"
6345 camera_distance=".3"
6346 camera_elevation=".14">
6347 <param_color>
6348 <value
6349 color="252,247,246,255" />
6350
6351 <value
6352 color="255,206,206,255" />
6353
6354 <value
6355 color="233,135,149,255" />
6356
6357 <value
6358 color="220,168,192,255" />
6359
6360 <value
6361 color="228,203,232,255" />
6362
6363 <value
6364 color="255,234,195,255" />
6365
6366 <value
6367 color="230,157,101,255" />
6368
6369 <value
6370 color="255,147,86,255" />
6371
6372 <value
6373 color="228,110,89,255" />
6374
6375 <value
6376 color="228,150,120,255" />
6377
6378 <value
6379 color="223,227,213,255" />
6380
6381 <value
6382 color="96,116,87,255" />
6383
6384 <value
6385 color="88,143,107,255" />
6386
6387 <value
6388 color="194,231,223,255" />
6389
6390 <value
6391 color="207,227,234,255" />
6392
6393 <value
6394 color="41,171,212,255" />
6395
6396 <value
6397 color="180,137,130,255" />
6398
6399 <value
6400 color="173,125,105,255" />
6401
6402 <value
6403 color="144,95,98,255" />
6404
6405 <value
6406 color="115,70,77,255" />
6407
6408 <value
6409 color="155,78,47,255" />
6410
6411 <value
6412 color="239,239,239,255" />
6413
6414 <value
6415 color="194,194,194,255" />
6416
6417 <value
6418 color="120,120,120,255" />
6419
6420 <value
6421 color="10,10,10,255" />
6422 </param_color>
6423 </param>
6424
6425 <param
6426 id="713"
6427 group="0"
6428 wearable="skin"
6429 edit_group="skin_makeup"
6430 edit_group_order="9"
6431 name="In Shdw Opacity"
6432 label_min="Clear"
6433 label_max="Opaque"
6434 value_min=".2"
6435 value_max="1"
6436 value_default=".7"
6437 camera_distance=".3"
6438 camera_elevation=".14">
6439 <param_color
6440 operation="multiply">
6441 <value
6442 color="255,255,255,0" />
6443
6444 <value
6445 color="255,255,255,255" />
6446 </param_color>
6447 </param>
6448
6449 <param
6450 id="709"
6451 group="0"
6452 wearable="skin"
6453 edit_group="skin_makeup"
6454 edit_group_order="7"
6455 name="Inner Shadow"
6456 label_min="No Eyeshadow"
6457 label_max="More Eyeshadow"
6458 value_min="0"
6459 value_max="1"
6460 value_default="0"
6461 camera_distance=".3"
6462 camera_elevation=".14">
6463 <param_alpha
6464 tga_file="eyeshadow_inner_alpha.tga"
6465 skip_if_zero="true"
6466 domain="0.2" />
6467 </param>
6468 </layer>
6469
6470 <layer
6471 name="eyeliner"
6472 fixed_color="0,0,0,200">
6473 <param
6474 id="703"
6475 group="0"
6476 wearable="skin"
6477 edit_group="skin_makeup"
6478 edit_group_order="13"
6479 name="Eyeliner"
6480 label_min="No Eyeliner"
6481 label_max="Full Eyeliner"
6482 value_min="0"
6483 value_max="1"
6484 value_default="0.0"
6485 camera_distance=".3"
6486 camera_elevation=".14">
6487 <param_alpha
6488 tga_file="eyeliner_alpha.tga"
6489 skip_if_zero="true"
6490 domain="0.1" />
6491 </param>
6492
6493 <param
6494 id="714"
6495 group="0"
6496 wearable="skin"
6497 edit_group="skin_makeup"
6498 edit_group_order="14"
6499 name="Eyeliner Color"
6500 label_min="Dark Green"
6501 label_max="Black"
6502 value_min="0"
6503 value_max="1"
6504 camera_distance=".3"
6505 camera_elevation=".14">
6506 <param_color>
6507 <value
6508 color="24,98,40,250" />
6509
6510 <!-- dark green -->
6511 <value
6512 color="9,100,127,250" />
6513
6514 <!-- lt.aqua blue -->
6515 <value
6516 color="61,93,134,250" />
6517
6518 <!-- aqua -->
6519 <value
6520 color="70,29,27,250" />
6521
6522 <!-- dark brown -->
6523 <value
6524 color="115,75,65,250" />
6525
6526 <!-- lt. brown blue -->
6527 <value
6528 color="100,100,100,250" />
6529
6530 <!-- grey -->
6531 <value
6532 color="91,80,74,250" />
6533
6534 <!-- grey/brown -->
6535 <value
6536 color="112,42,76,250" />
6537
6538 <!-- plum -->
6539 <value
6540 color="14,14,14,250" />
6541
6542 <!-- black -->
6543 </param_color>
6544 </param>
6545 </layer>
6546
6547 <layer
6548 name="facialhair bump"
6549 render_pass="bump">
6550 <texture
6551 tga_file="head_hair.tga"
6552 file_is_mask="false" />
6553
6554 <param
6555 id="1004"
6556 sex="male"
6557 group="1"
6558 wearable="hair"
6559 edit_group="driven"
6560 name="Sideburns bump"
6561 value_min="0"
6562 value_max="1">
6563 <param_alpha
6564 tga_file="facehair_sideburns_alpha.tga"
6565 skip_if_zero="true"
6566 domain="0.05" />
6567 </param>
6568
6569 <param
6570 id="1006"
6571 sex="male"
6572 group="1"
6573 wearable="hair"
6574 edit_group="driven"
6575 name="Moustache bump"
6576 value_min="0"
6577 value_max="1">
6578 <param_alpha
6579 tga_file="facehair_moustache_alpha.tga"
6580 skip_if_zero="true"
6581 domain="0.05" />
6582 </param>
6583
6584 <param
6585 id="1008"
6586 sex="male"
6587 group="1"
6588 wearable="hair"
6589 edit_group="driven"
6590 name="Soulpatch bump"
6591 value_min="0"
6592 value_max="1">
6593 <param_alpha
6594 tga_file="facehair_soulpatch_alpha.tga"
6595 skip_if_zero="true"
6596 domain="0.1" />
6597 </param>
6598
6599 <param
6600 id="1010"
6601 sex="male"
6602 group="1"
6603 edit_group="driven"
6604 wearable="hair"
6605 name="Chin Curtains bump"
6606 value_min="0"
6607 value_max="1">
6608 <param_alpha
6609 tga_file="facehair_chincurtains_alpha.tga"
6610 skip_if_zero="true"
6611 domain="0.03" />
6612 </param>
6613
6614 <param
6615 id="1012"
6616 group="1"
6617 sex="male"
6618 wearable="hair"
6619 edit_group="driven"
6620 name="5 O'Clock Shadow bump"
6621 value_min="0"
6622 value_max="1">
6623 <param_color>
6624 <value
6625 color="255,255,255,255" />
6626
6627 <value
6628 color="255,255,255,0" />
6629 </param_color>
6630 </param>
6631 </layer>
6632
6633 <layer
6634 name="facialhair"
6635 global_color="hair_color">
6636
6637 <texture
6638 tga_file="head_hair.tga"
6639 file_is_mask="false" />
6640
6641 <param
6642 id="1005"
6643 sex="male"
6644 group="1"
6645 wearable="hair"
6646 edit_group="driven"
6647 name="Sideburns"
6648 value_min="0"
6649 value_max="1">
6650 <param_alpha
6651 tga_file="facehair_sideburns_alpha.tga"
6652 skip_if_zero="true"
6653 domain="0.05" />
6654 </param>
6655
6656 <param
6657 id="1007"
6658 sex="male"
6659 group="1"
6660 wearable="hair"
6661 edit_group="driven"
6662 name="Moustache"
6663 value_min="0"
6664 value_max="1">
6665 <param_alpha
6666 tga_file="facehair_moustache_alpha.tga"
6667 skip_if_zero="true"
6668 domain="0.05" />
6669 </param>
6670
6671 <param
6672 id="1009"
6673 sex="male"
6674 group="1"
6675 wearable="hair"
6676 edit_group="driven"
6677 name="Soulpatch"
6678 value_min="0"
6679 value_max="1">
6680 <param_alpha
6681 tga_file="facehair_soulpatch_alpha.tga"
6682 skip_if_zero="true"
6683 domain="0.1" />
6684 </param>
6685
6686 <param
6687 id="1011"
6688 sex="male"
6689 group="1"
6690 wearable="hair"
6691 edit_group="driven"
6692 name="Chin Curtains"
6693 value_min="0"
6694 value_max="1">
6695 <param_alpha
6696 tga_file="facehair_chincurtains_alpha.tga"
6697 skip_if_zero="true"
6698 domain="0.03" />
6699 </param>
6700
6701 <param
6702 id="751"
6703 group="1"
6704 wearable="hair"
6705 sex="male"
6706 edit_group="hair_facial"
6707 name="5 O'Clock Shadow"
6708 label_min="Dense hair"
6709 label_max="Shadow hair"
6710 value_min="0"
6711 value_max="1"
6712 value_default="0.7"
6713 camera_elevation=".1"
6714 camera_distance=".3">
6715 <param_color
6716 operation="multiply">
6717 <value
6718 color="255,255,255,255" />
6719
6720 <value
6721 color="255,255,255,30" />
6722 </param_color>
6723 </param>
6724 </layer>
6725
6726 <layer
6727 name="head_bodypaint">
6728 <texture
6729 local_texture="head_bodypaint" />
6730 </layer>
6731 <layer
6732 name="eyelash alpha"
6733 visibility_mask="TRUE">
6734 <texture
6735 tga_file="head_alpha.tga"
6736 file_is_mask="TRUE" />
6737 </layer>
6738 <layer
6739 name="head alpha"
6740 visibility_mask="TRUE">
6741 <texture
6742 local_texture="head_alpha" />
6743 </layer>
6744 <layer
6745 name="head_tattoo">
6746 <texture
6747 local_texture="head_tattoo" />
6748 <param
6749 id="1062"
6750 group="1"
6751 edit_group="colorpicker_driven"
6752 wearable="tattoo"
6753 name="tattoo_head_red"
6754 value_min="0"
6755 value_max="1"
6756 value_default="1">
6757 <param_color>
6758 <value
6759 color="0, 0, 0, 255" />
6760
6761 <value
6762 color="255, 0, 0, 255" />
6763 </param_color>
6764 </param>
6765
6766 <param
6767 id="1063"
6768 group="1"
6769 edit_group="colorpicker_driven"
6770 wearable="tattoo"
6771 name="tattoo_head_green"
6772 value_min="0"
6773 value_max="1"
6774 value_default="1">
6775 <param_color>
6776 <value
6777 color="0, 0, 0, 255" />
6778
6779 <value
6780 color="0, 255, 0, 255" />
6781 </param_color>
6782 </param>
6783
6784 <param
6785 id="1064"
6786 group="1"
6787 edit_group="colorpicker_driven"
6788 wearable="tattoo"
6789 name="tattoo_head_blue"
6790 value_min="0"
6791 value_max="1"
6792 value_default="1">
6793 <param_color>
6794 <value
6795 color="0, 0, 0, 255" />
6796
6797 <value
6798 color="0, 0, 255, 255" />
6799 </param_color>
6800 </param>
6801
6802 </layer>
6803
6804
6805 </layer_set>
6806
6807 <!-- =========================================================== -->
6808 <layer_set
6809 body_region="upper_body"
6810 width="512"
6811 height="512">
6812 <layer
6813 name="base_upperbody bump"
6814 render_pass="bump"
6815 fixed_color="128,128,128,255">
6816 </layer>
6817 <layer
6818 name="upperbody bump definition"
6819 render_pass="bump">
6820 <texture
6821 tga_file="bump_upperbody_base.tga"
6822 file_is_mask="FALSE"/>
6823
6824 <param
6825 id="874"
6826 group="1"
6827 wearable="skin"
6828 edit_group="driven"
6829 edit_group_order="20"
6830 name="Bump upperdef"
6831 value_min="0"
6832 value_max="1">
6833 <param_alpha
6834 domain="0" />
6835 </param>
6836 </layer>
6837
6838 <layer
6839 name="base"
6840 global_color="skin_color">
6841 <texture
6842 tga_file="body_skingrain.tga" />
6843 </layer>
6844
6845 <layer
6846 name="nipples">
6847 <texture
6848 tga_file="upperbody_color.tga" />
6849 </layer>
6850
6851 <layer
6852 name="shadow">
6853 <texture
6854 tga_file="upperbody_shading_alpha.tga"
6855 file_is_mask="TRUE" />
6856
6857 <param
6858 id="125"
6859 group="1"
6860 name="Shading"
6861 wearable="skin"
6862 value_min="0"
6863 value_max="1">
6864 <param_color>
6865 <value
6866 color="0, 0, 0, 0" />
6867
6868 <value
6869 color="0, 0, 0, 128" />
6870 </param_color>
6871 </param>
6872 </layer>
6873
6874 <layer
6875 name="highlight">
6876 <texture
6877 tga_file="upperbody_highlights_alpha.tga"
6878 file_is_mask="TRUE" />
6879
6880 <param
6881 id="126"
6882 group="1"
6883 wearable="skin"
6884 name="Shading"
6885 value_min="0"
6886 value_max="1">
6887 <param_color>
6888 <value
6889 color="255, 255, 255, 0" />
6890
6891 <value
6892 color="255, 255, 255, 64" />
6893 </param_color>
6894 </param>
6895 </layer>
6896
6897 <layer
6898 name="upper_bodypaint">
6899 <texture
6900 local_texture="upper_bodypaint" />
6901 </layer>
6902
6903 <layer
6904 name="freckles upper"
6905 fixed_color="120,47,20,128">
6906 <param
6907 id="776"
6908 group="1"
6909 name="freckles upper"
6910 wearable="skin"
6911 value_min="0"
6912 value_max="1">
6913 <param_alpha
6914 tga_file="upperbodyfreckles_alpha.tga"
6915 skip_if_zero="true"
6916 domain="0.6" />
6917 </param>
6918 </layer>
6919
6920 <layer
6921 name="upper_tattoo">
6922 <texture
6923 local_texture="upper_tattoo" />
6924
6925 <param
6926 id="1065"
6927 group="1"
6928 edit_group="colorpicker_driven"
6929 wearable="tattoo"
6930 name="tattoo_upper_red"
6931 value_min="0"
6932 value_max="1"
6933 value_default="1">
6934 <param_color>
6935 <value
6936 color="0, 0, 0, 255" />
6937
6938 <value
6939 color="255, 0, 0, 255" />
6940 </param_color>
6941 </param>
6942
6943 <param
6944 id="1066"
6945 group="1"
6946 edit_group="colorpicker_driven"
6947 wearable="tattoo"
6948 name="tattoo_upper_green"
6949 value_min="0"
6950 value_max="1"
6951 value_default="1">
6952 <param_color>
6953 <value
6954 color="0, 0, 0, 255" />
6955
6956 <value
6957 color="0, 255, 0, 255" />
6958 </param_color>
6959 </param>
6960
6961 <param
6962 id="1067"
6963 group="1"
6964 edit_group="colorpicker_driven"
6965 wearable="tattoo"
6966 name="tattoo_upper_blue"
6967 value_min="0"
6968 value_max="1"
6969 value_default="1">
6970 <param_color>
6971 <value
6972 color="0, 0, 0, 255" />
6973
6974 <value
6975 color="0, 0, 255, 255" />
6976 </param_color>
6977 </param>
6978
6979 </layer>
6980
6981
6982 <layer
6983 name="upper_undershirt bump"
6984 render_pass="bump"
6985 fixed_color="128,128,128,255">
6986 <texture
6987 local_texture="upper_undershirt"
6988 local_texture_alpha_only="true" />
6989
6990 <param
6991 id="1043"
6992 group="1"
6993 wearable="undershirt"
6994 edit_group="driven"
6995 name="Sleeve Length bump"
6996 value_min=".01"
6997 value_max="1"
6998 value_default=".4">
6999 <param_alpha
7000 tga_file="shirt_sleeve_alpha.tga"
7001 multiply_blend="false"
7002 domain="0.01" />
7003 </param>
7004
7005 <param
7006 id="1045"
7007 group="1"
7008 wearable="undershirt"
7009 edit_group="undershirt"
7010 edit_group_order="2"
7011 name="Bottom bump"
7012 value_min="0"
7013 value_max="1"
7014 value_default=".8">
7015 <param_alpha
7016 tga_file="shirt_bottom_alpha.tga"
7017 multiply_blend="true"
7018 domain="0.05" />
7019 </param>
7020
7021 <param
7022 id="1047"
7023 group="1"
7024 wearable="undershirt"
7025 edit_group="driven"
7026 name="Collar Front bump"
7027 value_min="0"
7028 value_max="1"
7029 value_default=".8">
7030 <param_alpha
7031 tga_file="shirt_collar_alpha.tga"
7032 multiply_blend="true"
7033 domain="0.05" />
7034 </param>
7035
7036 <param
7037 id="1049"
7038 group="1"
7039 wearable="undershirt"
7040 edit_group="driven"
7041 name="Collar Back bump"
7042 value_min="0"
7043 value_max="1"
7044 value_default=".8">
7045 <param_alpha
7046 tga_file="shirt_collar_back_alpha.tga"
7047 multiply_blend="true"
7048 domain="0.05" />
7049 </param>
7050 </layer>
7051
7052 <layer
7053 name="upper_undershirt">
7054 <texture
7055 local_texture="upper_undershirt" />
7056
7057 <param
7058 id="821"
7059 group="0"
7060 wearable="undershirt"
7061 edit_group="colorpicker"
7062 name="undershirt_red"
7063 value_min="0"
7064 value_max="1"
7065 value_default="1">
7066 <param_color>
7067 <value
7068 color="0, 0, 0, 255" />
7069
7070 <value
7071 color="255, 0, 0, 255" />
7072 </param_color>
7073 </param>
7074
7075 <param
7076 id="822"
7077 group="0"
7078 wearable="undershirt"
7079 edit_group="colorpicker"
7080 name="undershirt_green"
7081 value_min="0"
7082 value_max="1"
7083 value_default="1">
7084 <param_color>
7085 <value
7086 color="0, 0, 0, 255" />
7087
7088 <value
7089 color="0, 255, 0, 255" />
7090 </param_color>
7091 </param>
7092
7093 <param
7094 id="823"
7095 group="0"
7096 wearable="undershirt"
7097 edit_group="colorpicker"
7098 name="undershirt_blue"
7099 value_min="0"
7100 value_max="1"
7101 value_default="1">
7102 <param_color>
7103 <value
7104 color="0, 0, 0, 255" />
7105
7106 <value
7107 color="0, 0, 255, 255" />
7108 </param_color>
7109 </param>
7110
7111 <param
7112 id="1042"
7113 group="1"
7114 wearable="undershirt"
7115 edit_group="driven"
7116 name="Sleeve Length"
7117 value_min=".01"
7118 value_max="1"
7119 value_default=".4">
7120 <param_alpha
7121 tga_file="shirt_sleeve_alpha.tga"
7122 multiply_blend="false"
7123 domain="0.01" />
7124 </param>
7125
7126 <param
7127 id="1044"
7128 group="1"
7129 wearable="undershirt"
7130 edit_group="driven"
7131 name="Bottom"
7132 value_min="0"
7133 value_max="1"
7134 value_default=".8">
7135 <param_alpha
7136 tga_file="shirt_bottom_alpha.tga"
7137 multiply_blend="true"
7138 domain="0.05" />
7139 </param>
7140
7141 <param
7142 id="1046"
7143 group="1"
7144 wearable="undershirt"
7145 edit_group="driven"
7146 name="Collar Front"
7147 value_min="0"
7148 value_max="1"
7149 value_default=".8">
7150 <param_alpha
7151 tga_file="shirt_collar_alpha.tga"
7152 multiply_blend="true"
7153 domain="0.05" />
7154 </param>
7155
7156 <param
7157 id="1048"
7158 group="1"
7159 wearable="undershirt"
7160 edit_group="driven"
7161 name="Collar Back"
7162 label_min="Low"
7163 label_max="High"
7164 value_min="0"
7165 value_max="1"
7166 value_default=".8">
7167 <param_alpha
7168 tga_file="shirt_collar_back_alpha.tga"
7169 multiply_blend="true"
7170 domain="0.05" />
7171 </param>
7172 </layer>
7173
7174 <layer
7175 name="Nail Polish">
7176 <param
7177 id="710"
7178 group="0"
7179 wearable="skin"
7180 edit_group="skin_makeup"
7181 edit_group_order="15"
7182 name="Nail Polish"
7183 label_min="No Polish"
7184 label_max="Painted Nails"
7185 value_min="0"
7186 value_max="1"
7187 value_default="0.0"
7188 camera_distance="1.6"
7189 camera_elevation="-.4"
7190 camera_angle="70">
7191 <param_alpha
7192 tga_file="nailpolish_alpha.tga"
7193 skip_if_zero="true"
7194 domain="0.1" />
7195 </param>
7196
7197 <param
7198 id="715"
7199 group="0"
7200 wearable="skin"
7201 edit_group="skin_makeup"
7202 edit_group_order="16"
7203 name="Nail Polish Color"
7204 label_min="Pink"
7205 label_max="Black"
7206 value_min="0"
7207 value_max="1"
7208 camera_distance="1.6"
7209 camera_elevation="-.4"
7210 camera_angle="70">
7211 <param_color>
7212 <value
7213 color="255,187,200,255" />
7214
7215 <value
7216 color="194,102,127,255" />
7217
7218 <value
7219 color="227,34,99,255" />
7220
7221 <value
7222 color="168,41,60,255" />
7223
7224 <value
7225 color="97,28,59,255" />
7226
7227 <value
7228 color="234,115,93,255" />
7229
7230 <value
7231 color="142,58,47,255" />
7232
7233 <value
7234 color="114,30,46,255" />
7235
7236 <value
7237 color="14,14,14,255" />
7238 </param_color>
7239 </param>
7240 </layer>
7241
7242 <layer
7243 name="upper_gloves bump"
7244 render_pass="bump"
7245 fixed_color="128,128,128,255">
7246 <texture
7247 local_texture="upper_gloves"
7248 local_texture_alpha_only="true" />
7249
7250 <param
7251 id="1059"
7252 group="1"
7253 wearable="gloves"
7254 edit_group="driven"
7255 name="Glove Length bump"
7256 value_min=".01"
7257 value_max="1"
7258 value_default=".8">
7259 <param_alpha
7260 tga_file="glove_length_alpha.tga"
7261 domain="0.01" />
7262 </param>
7263
7264 <param
7265 id="1061"
7266 group="1"
7267 wearable="gloves"
7268 edit_group="driven"
7269 name="Glove Fingers bump"
7270 value_min=".01"
7271 value_max="1"
7272 value_default="1">
7273 <param_alpha
7274 tga_file="gloves_fingers_alpha.tga"
7275 multiply_blend="true"
7276 domain="0.01" />
7277 </param>
7278 </layer>
7279
7280 <layer
7281 name="upper_gloves">
7282 <texture
7283 local_texture="upper_gloves" />
7284
7285 <param
7286 id="827"
7287 group="0"
7288 wearable="gloves"
7289 edit_group="colorpicker"
7290 name="gloves_red"
7291 value_min="0"
7292 value_max="1"
7293 value_default="1">
7294 <param_color>
7295 <value
7296 color="0, 0, 0, 255" />
7297
7298 <value
7299 color="255, 0, 0, 255" />
7300 </param_color>
7301 </param>
7302
7303 <param
7304 id="829"
7305 group="0"
7306 wearable="gloves"
7307 edit_group="colorpicker"
7308 name="gloves_green"
7309 value_min="0"
7310 value_max="1"
7311 value_default="1">
7312 <param_color>
7313 <value
7314 color="0, 0, 0, 255" />
7315
7316 <value
7317 color="0, 255, 0, 255" />
7318 </param_color>
7319 </param>
7320
7321 <param
7322 id="830"
7323 group="0"
7324 wearable="gloves"
7325 edit_group="colorpicker"
7326 name="gloves_blue"
7327 value_min="0"
7328 value_max="1"
7329 value_default="1">
7330 <param_color>
7331 <value
7332 color="0, 0, 0, 255" />
7333
7334 <value
7335 color="0, 0, 255, 255" />
7336 </param_color>
7337 </param>
7338
7339 <param
7340 id="1058"
7341 group="1"
7342 wearable="gloves"
7343 edit_group="driven"
7344 name="Glove Length"
7345 value_min=".01"
7346 value_max="1"
7347 value_default=".8">
7348 <param_alpha
7349 tga_file="glove_length_alpha.tga"
7350 domain="0.01" />
7351 </param>
7352
7353 <param
7354 id="1060"
7355 group="1"
7356 wearable="gloves"
7357 edit_group="driven"
7358 name="Glove Fingers"
7359 value_min=".01"
7360 value_max="1"
7361 value_default="1">
7362 <param_alpha
7363 tga_file="gloves_fingers_alpha.tga"
7364 multiply_blend="true"
7365 domain="0.01" />
7366 </param>
7367 </layer>
7368
7369 <layer
7370 name="upper_clothes_shadow">
7371 <texture
7372 local_texture="upper_shirt" />
7373
7374 <param
7375 id="899"
7376 group="1"
7377 edit_group="driven"
7378 wearable="shirt"
7379 name="Upper Clothes Shading"
7380 value_min="0"
7381 value_max="1"
7382 value_default="0">
7383 <param_color>
7384 <value
7385 color="0, 0, 0, 0" />
7386
7387 <value
7388 color="0, 0, 0, 80" />
7389 </param_color>
7390 </param>
7391
7392 <param
7393 id="900"
7394 group="1"
7395 wearable="shirt"
7396 edit_group="driven"
7397 name="Sleeve Length Shadow"
7398 value_min="0.02"
7399 value_max=".87"
7400 value_default="0.02">
7401 <param_alpha
7402 multiply_blend="false"
7403 tga_file="shirt_sleeve_alpha.tga"
7404 skip_if_zero="true"
7405 domain="0.03" />
7406 </param>
7407
7408 <param
7409 id="901"
7410 group="1"
7411 wearable="shirt"
7412 edit_group="driven"
7413 name="Shirt Shadow Bottom"
7414 value_min="0.02"
7415 value_max="1">
7416 <param_alpha
7417 multiply_blend="true"
7418 tga_file="shirt_bottom_alpha.tga"
7419 skip_if_zero="true"
7420 domain="0.05" />
7421 </param>
7422
7423 <param
7424 id="902"
7425 group="1"
7426 wearable="shirt"
7427 edit_group="driven"
7428 name="Collar Front Shadow Height"
7429 value_min="0.02"
7430 value_max="1">
7431 <param_alpha
7432 multiply_blend="true"
7433 tga_file="shirt_collar_alpha.tga"
7434 skip_if_zero="true"
7435 domain="0.02" />
7436 </param>
7437
7438 <param
7439 id="903"
7440 group="1"
7441 wearable="shirt"
7442 edit_group="driven"
7443 name="Collar Back Shadow Height"
7444 value_min="0.02"
7445 value_max="1">
7446 <param_alpha
7447 multiply_blend="true"
7448 tga_file="shirt_collar_back_alpha.tga"
7449 skip_if_zero="true"
7450 domain="0.02" />
7451 </param>
7452 </layer>
7453
7454 <layer
7455 name="upper_shirt base bump"
7456 render_pass="bump"
7457 fixed_color="128,128,128,255">
7458 <texture
7459 local_texture="upper_shirt"
7460 local_texture_alpha_only="true" />
7461
7462 <param
7463 id="1029"
7464 group="1"
7465 wearable="shirt"
7466 edit_group="driven"
7467 name="Sleeve Length Cloth"
7468 value_min="0"
7469 value_max="0.85">
7470 <param_alpha
7471 multiply_blend="false"
7472 tga_file="shirt_sleeve_alpha.tga"
7473 domain="0.01" />
7474 </param>
7475
7476 <param
7477 id="1030"
7478 group="1"
7479 wearable="shirt"
7480 edit_group="driven"
7481 name="Shirt Bottom Cloth"
7482 value_min="0"
7483 value_max="1">
7484 <param_alpha
7485 multiply_blend="true"
7486 tga_file="shirt_bottom_alpha.tga"
7487 domain="0.05" />
7488 </param>
7489
7490 <param
7491 id="1031"
7492 group="1"
7493 wearable="shirt"
7494 edit_group="driven"
7495 name="Collar Front Height Cloth"
7496 value_min="0"
7497 value_max="1">
7498 <param_alpha
7499 multiply_blend="true"
7500 tga_file="shirt_collar_alpha.tga"
7501 domain="0.05" />
7502 </param>
7503
7504 <param
7505 id="1032"
7506 group="1"
7507 wearable="shirt"
7508 edit_group="driven"
7509 name="Collar Back Height Cloth"
7510 value_min="0"
7511 value_max="1">
7512 <param_alpha
7513 multiply_blend="true"
7514 tga_file="shirt_collar_back_alpha.tga"
7515 domain="0.05" />
7516 </param>
7517 </layer>
7518
7519 <layer
7520 name="upper_clothes bump"
7521 render_pass="bump">
7522 <texture
7523 tga_file="bump_shirt_wrinkles.tga" />
7524
7525 <texture
7526 local_texture="upper_shirt"
7527 local_texture_alpha_only="true" />
7528
7529 <param
7530 id="868"
7531 group="0"
7532 wearable="shirt"
7533 edit_group="shirt"
7534 edit_group_order="8"
7535 name="Shirt Wrinkles"
7536 value_min="0"
7537 value_max="1"
7538 value_default="0">
7539 <param_color>
7540 <value
7541 color="255, 255, 255, 0" />
7542
7543 <value
7544 color="255, 255, 255, 255" />
7545 </param_color>
7546 </param>
7547
7548 <param
7549 id="1013"
7550 group="1"
7551 wearable="shirt"
7552 edit_group="driven"
7553 name="Sleeve Length Cloth"
7554 value_min="0"
7555 value_max="0.85">
7556 <param_alpha
7557 multiply_blend="false"
7558 tga_file="shirt_sleeve_alpha.tga"
7559 domain="0.01" />
7560 </param>
7561
7562 <param
7563 id="1014"
7564 group="1"
7565 wearable="shirt"
7566 edit_group="driven"
7567 name="Shirt Bottom Cloth"
7568 value_min="0"
7569 value_max="1">
7570 <param_alpha
7571 multiply_blend="true"
7572 tga_file="shirt_bottom_alpha.tga"
7573 domain="0.05" />
7574 </param>
7575
7576 <param
7577 id="1015"
7578 group="1"
7579 wearable="shirt"
7580 edit_group="driven"
7581 name="Collar Front Height Cloth"
7582 value_min="0"
7583 value_max="1">
7584 <param_alpha
7585 multiply_blend="true"
7586 tga_file="shirt_collar_alpha.tga"
7587 domain="0.05" />
7588 </param>
7589
7590 <param
7591 id="1016"
7592 group="1"
7593 wearable="shirt"
7594 edit_group="driven"
7595 name="Collar Back Height Cloth"
7596 value_min="0"
7597 value_max="1">
7598 <param_alpha
7599 multiply_blend="true"
7600 tga_file="shirt_collar_back_alpha.tga"
7601 domain="0.05" />
7602 </param>
7603 </layer>
7604
7605 <layer
7606 name="upper_clothes">
7607 <texture
7608 local_texture="upper_shirt" />
7609
7610 <param
7611 id="803"
7612 group="0"
7613 wearable="shirt"
7614 edit_group="colorpicker"
7615 name="shirt_red"
7616 value_min="0"
7617 value_max="1"
7618 value_default="1">
7619 <param_color>
7620 <value
7621 color="0, 0, 0, 255" />
7622
7623 <value
7624 color="255, 0, 0, 255" />
7625 </param_color>
7626 </param>
7627
7628 <param
7629 id="804"
7630 group="0"
7631 wearable="shirt"
7632 edit_group="colorpicker"
7633 name="shirt_green"
7634 value_min="0"
7635 value_max="1"
7636 value_default="1">
7637 <param_color>
7638 <value
7639 color="0, 0, 0, 255" />
7640
7641 <value
7642 color="0, 255, 0, 255" />
7643 </param_color>
7644 </param>
7645
7646 <param
7647 id="805"
7648 group="0"
7649 wearable="shirt"
7650 edit_group="colorpicker"
7651 name="shirt_blue"
7652 value_min="0"
7653 value_max="1"
7654 value_default="1">
7655 <param_color>
7656 <value
7657 color="0, 0, 0, 255" />
7658
7659 <value
7660 color="0, 0, 255, 255" />
7661 </param_color>
7662 </param>
7663
7664 <param
7665 id="600"
7666 group="1"
7667 wearable="shirt"
7668 edit_group="driven"
7669 name="Sleeve Length Cloth"
7670 value_min="0"
7671 value_max="0.85"
7672 value_default=".7">
7673 <param_alpha
7674 multiply_blend="false"
7675 tga_file="shirt_sleeve_alpha.tga"
7676 domain="0.01" />
7677 </param>
7678
7679 <param
7680 id="601"
7681 group="1"
7682 wearable="shirt"
7683 edit_group="driven"
7684 name="Shirt Bottom Cloth"
7685 value_min="0"
7686 value_max="1"
7687 value_default=".8">
7688 <param_alpha
7689 multiply_blend="true"
7690 tga_file="shirt_bottom_alpha.tga"
7691 domain="0.05" />
7692 </param>
7693
7694 <param
7695 id="602"
7696 group="1"
7697 wearable="shirt"
7698 edit_group="driven"
7699 name="Collar Front Height Cloth"
7700 value_min="0"
7701 value_max="1"
7702 value_default=".8">
7703 <param_alpha
7704 multiply_blend="true"
7705 tga_file="shirt_collar_alpha.tga"
7706 domain="0.05" />
7707 </param>
7708
7709 <param
7710 id="778"
7711 group="1"
7712 wearable="shirt"
7713 edit_group="driven"
7714 name="Collar Back Height Cloth"
7715 value_min="0"
7716 value_max="1"
7717 value_default=".8">
7718 <param_alpha
7719 multiply_blend="true"
7720 tga_file="shirt_collar_back_alpha.tga"
7721 domain="0.05" />
7722 </param>
7723 </layer>
7724
7725 <layer
7726 name="upper_jacket base bump"
7727 render_pass="bump"
7728 fixed_color="128,128,128,255">
7729 <texture
7730 local_texture="upper_jacket"
7731 local_texture_alpha_only="true" />
7732
7733 <param
7734 id="1039"
7735 group="1"
7736 wearable="jacket"
7737 edit_group="driven"
7738 edit_group_order="1"
7739 name="Jacket Sleeve Length bump"
7740 value_min="0"
7741 value_max="1">
7742 <param_alpha
7743 multiply_blend="false"
7744 tga_file="shirt_sleeve_alpha.tga"
7745 domain="0.01" />
7746 </param>
7747
7748 <param
7749 id="1040"
7750 group="1"
7751 wearable="jacket"
7752 edit_group="driven"
7753 name="Jacket Collar Front bump"
7754 value_min="0"
7755 value_max="1">
7756 <param_alpha
7757 multiply_blend="true"
7758 tga_file="shirt_collar_alpha.tga"
7759 domain="0.05" />
7760 </param>
7761
7762 <param
7763 id="1041"
7764 group="1"
7765 wearable="jacket"
7766 edit_group="driven"
7767 edit_group_order="3.5"
7768 name="Jacket Collar Back bump"
7769 value_min="0"
7770 value_max="1">
7771 <param_alpha
7772 multiply_blend="true"
7773 tga_file="shirt_collar_back_alpha.tga"
7774 domain="0.05" />
7775 </param>
7776
7777 <param
7778 id="1037"
7779 group="1"
7780 wearable="jacket"
7781 edit_group="driven"
7782 name="jacket bottom length upper bump"
7783 value_min="0"
7784 value_max="1">
7785 <param_alpha
7786 multiply_blend="true"
7787 tga_file="jacket_length_upper_alpha.tga"
7788 domain="0.01" />
7789 </param>
7790
7791 <param
7792 id="1038"
7793 group="1"
7794 wearable="jacket"
7795 edit_group="driven"
7796 name="jacket open upper bump"
7797 value_min="0"
7798 value_max="1">
7799 <param_alpha
7800 multiply_blend="true"
7801 tga_file="jacket_open_upper_alpha.tga"
7802 domain="0.01" />
7803 </param>
7804 </layer>
7805
7806 <layer
7807 name="upper_jacket bump"
7808 render_pass="bump">
7809 <texture
7810 tga_file="bump_shirt_wrinkles.tga" />
7811
7812 <texture
7813 local_texture="upper_jacket"
7814 local_texture_alpha_only="true" />
7815
7816
7817 <param
7818 id="875"
7819 group="1"
7820 wearable="jacket"
7821 name="jacket upper Wrinkles"
7822 value_min="0"
7823 value_max="1"
7824 value_default="0">
7825 <param_color>
7826 <value
7827 color="255, 255, 255, 0" />
7828
7829 <value
7830 color="255, 255, 255, 255" />
7831 </param_color>
7832 </param>
7833
7834 <param
7835 id="1019"
7836 group="1"
7837 wearable="jacket"
7838 edit_group="driven"
7839 edit_group_order="1"
7840 name="Jacket Sleeve Length bump"
7841 value_min="0"
7842 value_max="1">
7843 <param_alpha
7844 multiply_blend="false"
7845 tga_file="shirt_sleeve_alpha.tga"
7846 domain="0.01" />
7847 </param>
7848
7849 <param
7850 id="1021"
7851 group="1"
7852 wearable="jacket"
7853 edit_group="driven"
7854 name="Jacket Collar Front bump"
7855 value_min="0"
7856 value_max="1">
7857 <param_alpha
7858 multiply_blend="true"
7859 tga_file="shirt_collar_alpha.tga"
7860 domain="0.05" />
7861 </param>
7862
7863 <param
7864 id="1023"
7865 group="1"
7866 wearable="jacket"
7867 edit_group="driven"
7868 edit_group_order="3.5"
7869 name="Jacket Collar Back bump"
7870 value_min="0"
7871 value_max="1">
7872 <param_alpha
7873 multiply_blend="true"
7874 tga_file="shirt_collar_back_alpha.tga"
7875 domain="0.05" />
7876 </param>
7877
7878 <param
7879 id="1025"
7880 group="1"
7881 wearable="jacket"
7882 edit_group="driven"
7883 name="jacket bottom length upper bump"
7884 value_min="0"
7885 value_max="1">
7886 <param_alpha
7887 multiply_blend="true"
7888 tga_file="jacket_length_upper_alpha.tga"
7889 domain="0.01" />
7890 </param>
7891
7892 <param
7893 id="1026"
7894 group="1"
7895 wearable="jacket"
7896 edit_group="driven"
7897 name="jacket open upper bump"
7898 value_min="0"
7899 value_max="1">
7900 <param_alpha
7901 multiply_blend="true"
7902 tga_file="jacket_open_upper_alpha.tga"
7903 domain="0.01" />
7904 </param>
7905 </layer>
7906
7907 <layer
7908 name="upper_jacket">
7909 <texture
7910 local_texture="upper_jacket" />
7911
7912 <param
7913 id="831"
7914 group="1"
7915 edit_group="colorpicker_driven"
7916 wearable="jacket"
7917 name="upper_jacket_red"
7918 value_min="0"
7919 value_max="1"
7920 value_default="1">
7921 <param_color>
7922 <value
7923 color="0, 0, 0, 255" />
7924
7925 <value
7926 color="255, 0, 0, 255" />
7927 </param_color>
7928 </param>
7929
7930 <param
7931 id="832"
7932 group="1"
7933 edit_group="colorpicker_driven"
7934 wearable="jacket"
7935 name="upper_jacket_green"
7936 value_min="0"
7937 value_max="1"
7938 value_default="1">
7939 <param_color>
7940 <value
7941 color="0, 0, 0, 255" />
7942
7943 <value
7944 color="0, 255, 0, 255" />
7945 </param_color>
7946 </param>
7947
7948 <param
7949 id="833"
7950 group="1"
7951 edit_group="colorpicker_driven"
7952 wearable="jacket"
7953 name="upper_jacket_blue"
7954 value_min="0"
7955 value_max="1"
7956 value_default="1">
7957 <param_color>
7958 <value
7959 color="0, 0, 0, 255" />
7960
7961 <value
7962 color="0, 0, 255, 255" />
7963 </param_color>
7964 </param>
7965
7966 <param
7967 id="1020"
7968 group="1"
7969 edit_group="driven"
7970 wearable="jacket"
7971 name="jacket Sleeve Length" value_min="0"
7972 value_max="1">
7973 <param_alpha
7974 multiply_blend="false"
7975 tga_file="shirt_sleeve_alpha.tga"
7976 domain="0.01" />
7977 </param>
7978
7979 <param
7980 id="1022"
7981 group="1"
7982 wearable="jacket"
7983 edit_group="driven"
7984 name="jacket Collar Front"
7985 value_min="0"
7986 value_max="1">
7987 <param_alpha
7988 multiply_blend="true"
7989 tga_file="shirt_collar_alpha.tga"
7990 domain="0.05" />
7991 </param>
7992
7993 <param
7994 id="1024"
7995 group="1"
7996 wearable="jacket"
7997 edit_group="driven"
7998 edit_group_order="3.5"
7999 name="jacket Collar Back"
8000 value_min="0"
8001 value_max="1">
8002 <param_alpha
8003 multiply_blend="true"
8004 tga_file="shirt_collar_back_alpha.tga"
8005 domain="0.05" />
8006 </param>
8007
8008 <param
8009 id="620"
8010 group="1"
8011 wearable="jacket"
8012 edit_group="jacket"
8013 name="bottom length upper"
8014 label_min="hi cut"
8015 label_max="low cut"
8016 value_min="0"
8017 value_max="1"
8018 value_default=".8"
8019 camera_distance="1.2"
8020 camera_angle="30"
8021 camera_elevation=".2">
8022 <param_alpha
8023 multiply_blend="true"
8024 tga_file="jacket_length_upper_alpha.tga"
8025 domain="0.01" />
8026 </param>
8027
8028 <param
8029 id="622"
8030 group="1"
8031 wearable="jacket"
8032 edit_group="jacket"
8033 name="open upper"
8034 label_min="closed"
8035 label_max="open"
8036 value_min="0"
8037 value_max="1"
8038 value_default=".8"
8039 camera_distance="1.2"
8040 camera_angle="30"
8041 camera_elevation=".2">
8042 <param_alpha
8043 multiply_blend="true"
8044 tga_file="jacket_open_upper_alpha.tga"
8045 domain="0.01" />
8046 </param>
8047 </layer>
8048
8049 <layer
8050 name="upper alpha"
8051 visibility_mask="TRUE">
8052 <texture
8053 local_texture="upper_alpha" />
8054 </layer>
8055
8056 </layer_set>
8057
8058 <!-- =========================================================== -->
8059 <layer_set
8060 body_region="lower_body"
8061 width="512"
8062 height="512">
8063 <layer
8064 name="lower body bump base"
8065 fixed_color = "128,128,128,255"
8066 render_pass="bump">
8067 </layer>
8068 <layer
8069 name="base_lowerbody bump"
8070 render_pass="bump">
8071 <texture
8072 tga_file="bump_lowerbody_base.tga"
8073 file_is_mask="FALSE" />
8074
8075 <param
8076 id="878"
8077 group="1"
8078 wearable="skin"
8079 edit_group="driven"
8080 edit_group_order="20"
8081 name="Bump upperdef"
8082 value_min="0"
8083 value_max="1">
8084 <param_alpha
8085 domain="0" />
8086 </param>
8087 </layer>
8088
8089 <layer
8090 name="base"
8091 global_color="skin_color">
8092 <texture
8093 tga_file="body_skingrain.tga" />
8094 </layer>
8095
8096 <layer
8097 name="shadow">
8098 <texture
8099 tga_file="lowerbody_shading_alpha.tga"
8100 file_is_mask="TRUE" />
8101
8102 <param
8103 id="160"
8104 group="1"
8105 name="Shading"
8106 wearable="pants"
8107 cross_wearable="true"
8108 value_min="0"
8109 value_max="1">
8110 <param_color>
8111 <value
8112 color="0, 0, 0, 0" />
8113
8114 <value
8115 color="0, 0, 0, 128" />
8116 </param_color>
8117 </param>
8118 </layer>
8119
8120 <layer
8121 name="highlight">
8122 <texture
8123 tga_file="lowerbody_highlights_alpha.tga"
8124 file_is_mask="TRUE" />
8125
8126 <param
8127 id="161"
8128 group="1"
8129 name="Shading"
8130 wearable="skin"
8131 value_min="0"
8132 value_max="1">
8133 <param_color>
8134 <value
8135 color="255, 255, 255, 0" />
8136
8137 <value
8138 color="255, 255, 255, 64" />
8139 </param_color>
8140 </param>
8141 </layer>
8142
8143 <layer
8144 name="toenails">
8145 <texture
8146 tga_file="lowerbody_color.tga" />
8147 </layer>
8148
8149 <layer
8150 name="lower_bodypaint">
8151 <texture
8152 local_texture="lower_bodypaint" />
8153 </layer>
8154
8155 <layer
8156 name="freckles lower"
8157 fixed_color="120,47,20,128">
8158 <param
8159 id="777"
8160 group="1"
8161 name="freckles lower"
8162 wearable="skin"
8163 value_min="0"
8164 value_max="1">
8165 <param_alpha
8166 tga_file="bodyfreckles_alpha.tga"
8167 skip_if_zero="true"
8168 domain="0.6" />
8169 </param>
8170 </layer>
8171
8172 <layer
8173 name="lower_tattoo">
8174 <texture
8175 local_texture="lower_tattoo" />
8176
8177 <param
8178 id="1068"
8179 group="1"
8180 edit_group="colorpicker_driven"
8181 wearable="tattoo"
8182 name="tattoo_lower_red"
8183 value_min="0"
8184 value_max="1"
8185 value_default="1">
8186 <param_color>
8187 <value
8188 color="0, 0, 0, 255" />
8189
8190 <value
8191 color="255, 0, 0, 255" />
8192 </param_color>
8193 </param>
8194
8195 <param
8196 id="1069"
8197 group="1"
8198 edit_group="colorpicker_driven"
8199 wearable="tattoo"
8200 name="tattoo_lower_green"
8201 value_min="0"
8202 value_max="1"
8203 value_default="1">
8204 <param_color>
8205 <value
8206 color="0, 0, 0, 255" />
8207
8208 <value
8209 color="0, 255, 0, 255" />
8210 </param_color>
8211 </param>
8212
8213 <param
8214 id="1070"
8215 group="1"
8216 edit_group="colorpicker_driven"
8217 wearable="tattoo"
8218 name="tattoo_lower_blue"
8219 value_min="0"
8220 value_max="1"
8221 value_default="1">
8222 <param_color>
8223 <value
8224 color="0, 0, 0, 255" />
8225
8226 <value
8227 color="0, 0, 255, 255" />
8228 </param_color>
8229 </param>
8230
8231 </layer>
8232
8233 <layer
8234 name="lower_underpants bump"
8235 render_pass="bump"
8236 fixed_color="128,128,128,255">
8237 <texture
8238 local_texture="lower_underpants"
8239 local_texture_alpha_only="true" />
8240
8241 <param
8242 id="1055"
8243 group="1"
8244 wearable="underpants"
8245 edit_group="underpants"
8246 name="Pants Length"
8247 value_min="0"
8248 value_max="1"
8249 value_default=".3">
8250 <param_alpha
8251 tga_file="pants_length_alpha.tga"
8252 domain="0.01" />
8253 </param>
8254
8255 <param
8256 id="1057"
8257 group="1"
8258 wearable="underpants"
8259 edit_group="underpants"
8260 name="Pants Waist"
8261 value_min="0"
8262 value_max="1"
8263 value_default=".8">
8264 <param_alpha
8265 tga_file="pants_waist_alpha.tga"
8266 domain="0.05" />
8267 </param>
8268 </layer>
8269
8270 <layer
8271 name="lower_underpants">
8272 <texture
8273 local_texture="lower_underpants" />
8274
8275 <param
8276 id="824"
8277 group="0"
8278 wearable="underpants"
8279 edit_group="colorpicker"
8280 name="underpants_red"
8281 value_min="0"
8282 value_max="1"
8283 value_default="1">
8284 <param_color>
8285 <value
8286 color="0, 0, 0, 255" />
8287
8288 <value
8289 color="255, 0, 0, 255" />
8290 </param_color>
8291 </param>
8292
8293 <param
8294 id="825"
8295 group="0"
8296 wearable="underpants"
8297 edit_group="colorpicker"
8298 name="underpants_green"
8299 value_min="0"
8300 value_max="1"
8301 value_default="1">
8302 <param_color>
8303 <value
8304 color="0, 0, 0, 255" />
8305
8306 <value
8307 color="0, 255, 0, 255" />
8308 </param_color>
8309 </param>
8310
8311 <param
8312 id="826"
8313 group="0"
8314 wearable="underpants"
8315 edit_group="colorpicker"
8316 name="underpants_blue"
8317 value_min="0"
8318 value_max="1"
8319 value_default="1">
8320 <param_color>
8321 <value
8322 color="0, 0, 0, 255" />
8323
8324 <value
8325 color="0, 0, 255, 255" />
8326 </param_color>
8327 </param>
8328
8329 <param
8330 id="1054"
8331 group="1"
8332 wearable="underpants"
8333 edit_group="driven"
8334 name="Pants Length"
8335 value_min="0"
8336 value_max="1"
8337 value_default=".3"
8338 camera_distance="1.2"
8339 camera_angle="30"
8340 camera_elevation="-.3">
8341 <param_alpha
8342 tga_file="pants_length_alpha.tga"
8343 domain="0.01" />
8344 </param>
8345
8346 <param
8347 id="1056"
8348 group="1"
8349 wearable="underpants"
8350 edit_group="driven"
8351 name="Pants Waist"
8352 value_min="0"
8353 value_max="1"
8354 value_default=".8">
8355 <param_alpha
8356 tga_file="pants_waist_alpha.tga"
8357 domain="0.05" />
8358 </param>
8359 </layer>
8360
8361 <layer
8362 name="lower_socks bump"
8363 render_pass="bump"
8364 fixed_color="128,128,128,255">
8365 <texture
8366 local_texture="lower_socks"
8367 local_texture_alpha_only="true" />
8368
8369 <param
8370 id="1051"
8371 group="1"
8372 wearable="socks"
8373 edit_group="driven"
8374 name="Socks Length bump"
8375 value_min="0"
8376 value_max="1"
8377 value_default="0.35">
8378 <param_alpha
8379 tga_file="shoe_height_alpha.tga"
8380 domain="0.01" />
8381 </param>
8382 </layer>
8383
8384 <layer
8385 name="lower_socks">
8386 <texture
8387 local_texture="lower_socks" />
8388
8389 <param
8390 id="818"
8391 group="0"
8392 wearable="socks"
8393 edit_group="colorpicker"
8394 name="socks_red"
8395 value_min="0"
8396 value_max="1"
8397 value_default="1">
8398 <param_color>
8399 <value
8400 color="0, 0, 0, 255" />
8401
8402 <value
8403 color="255, 0, 0, 255" />
8404 </param_color>
8405 </param>
8406
8407 <param
8408 id="819"
8409 group="0"
8410 wearable="socks"
8411 edit_group="colorpicker"
8412 name="socks_green"
8413 value_min="0"
8414 value_max="1"
8415 value_default="1">
8416 <param_color>
8417 <value
8418 color="0, 0, 0, 255" />
8419
8420 <value
8421 color="0, 255, 0, 255" />
8422 </param_color>
8423 </param>
8424
8425 <param
8426 id="820"
8427 group="0"
8428 wearable="socks"
8429 edit_group="colorpicker"
8430 name="socks_blue"
8431 value_min="0"
8432 value_max="1"
8433 value_default="1">
8434 <param_color>
8435 <value
8436 color="0, 0, 0, 255" />
8437
8438 <value
8439 color="0, 0, 255, 255" />
8440 </param_color>
8441 </param>
8442
8443 <param
8444 id="1050"
8445 group="1"
8446 wearable="socks"
8447 edit_group="driven"
8448 name="Socks Length bump"
8449 value_min="0"
8450 value_max="1"
8451 value_default="0.35">
8452 <param_alpha
8453 tga_file="shoe_height_alpha.tga"
8454 domain="0.01" />
8455 </param>
8456 </layer>
8457
8458 <layer
8459 name="lower_shoes bump"
8460 render_pass="bump"
8461 fixed_color="128,128,128,255">
8462 <texture
8463 local_texture="lower_shoes"
8464 local_texture_alpha_only="true" />
8465
8466 <param
8467 id="1053"
8468 group="1"
8469 wearable="shoes"
8470 edit_group="driven"
8471 name="Shoe Height bump"
8472 value_min="0"
8473 value_max="1"
8474 value_default="0.1">
8475 <param_alpha
8476 tga_file="shoe_height_alpha.tga"
8477 domain="0.01" />
8478 </param>
8479 </layer>
8480
8481 <layer
8482 name="lower_shoes">
8483 <texture
8484 local_texture="lower_shoes" />
8485
8486 <param
8487 id="812"
8488 group="0"
8489 wearable="shoes"
8490 edit_group="colorpicker"
8491 name="shoes_red"
8492 value_min="0"
8493 value_max="1"
8494 value_default="1">
8495 <param_color>
8496 <value
8497 color="0, 0, 0, 255" />
8498
8499 <value
8500 color="255, 0, 0, 255" />
8501 </param_color>
8502 </param>
8503
8504 <param
8505 id="813"
8506 group="0"
8507 wearable="shoes"
8508 edit_group="colorpicker"
8509 name="shoes_green"
8510 value_min="0"
8511 value_max="1"
8512 value_default="1">
8513 <param_color>
8514 <value
8515 color="0, 0, 0, 255" />
8516
8517 <value
8518 color="0, 255, 0, 255" />
8519 </param_color>
8520 </param>
8521
8522 <param
8523 id="817"
8524 group="0"
8525 wearable="shoes"
8526 edit_group="colorpicker"
8527 name="shoes_blue"
8528 value_min="0"
8529 value_max="1"
8530 value_default="1">
8531 <param_color>
8532 <value
8533 color="0, 0, 0, 255" />
8534
8535 <value
8536 color="0, 0, 255, 255" />
8537 </param_color>
8538 </param>
8539
8540 <param
8541 id="1052"
8542 group="1"
8543 wearable="shoes"
8544 edit_group="driven"
8545 name="Shoe Height"
8546 value_min="0"
8547 value_max="1"
8548 value_default="0.1">
8549 <param_alpha
8550 tga_file="shoe_height_alpha.tga"
8551 domain="0.01" />
8552 </param>
8553 </layer>
8554
8555 <layer
8556 name="lower_clothes_shadow">
8557 <texture
8558 local_texture="lower_pants" />
8559
8560 <param
8561 id="913"
8562 group="1"
8563 edit_group="driven"
8564 wearable="pants"
8565 name="Lower Clothes Shading"
8566 value_min="0"
8567 value_max="1"
8568 value_default="0">
8569 <param_color>
8570 <value
8571 color="0, 0, 0, 0" />
8572
8573 <value
8574 color="0, 0, 0, 80" />
8575 </param_color>
8576 </param>
8577
8578 <param
8579 id="914"
8580 group="1"
8581 edit_group="driven"
8582 wearable="pants"
8583 name="Waist Height Shadow"
8584 value_min="0.02"
8585 value_max="1">
8586 <param_alpha
8587 tga_file="pants_waist_alpha.tga"
8588 skip_if_zero="true"
8589 domain="0.04" />
8590 </param>
8591
8592 <param
8593 id="915"
8594 group="1"
8595 edit_group="driven"
8596 wearable="pants"
8597 name="Pants Length Shadow"
8598 value_min="0.02"
8599 value_max="1">
8600 <param_alpha
8601 tga_file="pants_length_alpha.tga"
8602 skip_if_zero="true"
8603 domain="0.03" />
8604 </param>
8605 </layer>
8606
8607 <layer
8608 name="lower_pants base bump"
8609 render_pass="bump"
8610 fixed_color="128,128,128,255">
8611 <texture
8612 local_texture="lower_pants"
8613 local_texture_alpha_only="true" />
8614
8615 <param
8616 id="1035"
8617 group="1"
8618 edit_group="driven"
8619 wearable="pants"
8620 name="Waist Height Cloth"
8621 value_min="0"
8622 value_max="1">
8623 <param_alpha
8624 tga_file="pants_waist_alpha.tga"
8625 domain="0.05" />
8626 </param>
8627
8628 <param
8629 id="1036"
8630 group="1"
8631 edit_group="driven"
8632 wearable="pants"
8633 name="Pants Length Cloth"
8634 value_min="0"
8635 value_max="1">
8636 <param_alpha
8637 tga_file="pants_length_alpha.tga"
8638 domain="0.01" />
8639 </param>
8640 </layer>
8641
8642 <layer
8643 name="lower_pants bump"
8644 render_pass="bump">
8645 <texture
8646 tga_file="bump_pants_wrinkles.tga" />
8647
8648 <texture
8649 local_texture="lower_pants"
8650 local_texture_alpha_only="true" />
8651
8652 <param
8653 id="869"
8654 group="0"
8655 wearable="pants"
8656 edit_group="pants"
8657 edit_group_order="6"
8658 name="Pants Wrinkles"
8659 value_min="0"
8660 value_max="1"
8661 value_default="0">
8662 <param_color>
8663 <value
8664 color="255, 255, 255, 0" />
8665
8666 <value
8667 color="255, 255, 255, 255" />
8668 </param_color>
8669 </param>
8670
8671 <param
8672 id="1017"
8673 group="1"
8674 edit_group="driven"
8675 wearable="pants"
8676 name="Waist Height Cloth"
8677 value_min="0"
8678 value_max="1">
8679 <param_alpha
8680 tga_file="pants_waist_alpha.tga"
8681 domain="0.05" />
8682 </param>
8683
8684 <param
8685 id="1018"
8686 group="1"
8687 edit_group="driven"
8688 wearable="pants"
8689 name="Pants Length Cloth"
8690 value_min="0"
8691 value_max="1">
8692 <param_alpha
8693 tga_file="pants_length_alpha.tga"
8694 domain="0.01" />
8695 </param>
8696 </layer>
8697
8698 <layer
8699 name="lower_pants">
8700 <texture
8701 local_texture="lower_pants" />
8702
8703 <param
8704 id="806"
8705 group="0"
8706 wearable="pants"
8707 edit_group="colorpicker"
8708 name="pants_red"
8709 value_min="0"
8710 value_max="1"
8711 value_default="1">
8712 <param_color>
8713 <value
8714 color="0, 0, 0, 255" />
8715
8716 <value
8717 color="255, 0, 0, 255" />
8718 </param_color>
8719 </param>
8720
8721 <param
8722 id="807"
8723 group="0"
8724 wearable="pants"
8725 edit_group="colorpicker"
8726 name="pants_green"
8727 value_min="0"
8728 value_max="1"
8729 value_default="1">
8730 <param_color>
8731 <value
8732 color="0, 0, 0, 255" />
8733
8734 <value
8735 color="0, 255, 0, 255" />
8736 </param_color>
8737 </param>
8738
8739 <param
8740 id="808"
8741 group="0"
8742 wearable="pants"
8743 edit_group="colorpicker"
8744 name="pants_blue"
8745 value_min="0"
8746 value_max="1"
8747 value_default="1">
8748 <param_color>
8749 <value
8750 color="0, 0, 0, 255" />
8751
8752 <value
8753 color="0, 0, 255, 255" />
8754 </param_color>
8755 </param>
8756
8757 <param
8758 id="614"
8759 group="1"
8760 edit_group="driven"
8761 wearable="pants"
8762 name="Waist Height Cloth"
8763 value_min="0"
8764 value_max="1"
8765 value_default=".8">
8766 <param_alpha
8767 tga_file="pants_waist_alpha.tga"
8768 domain="0.05" />
8769 </param>
8770
8771 <param
8772 id="615"
8773 group="1"
8774 edit_group="driven"
8775 wearable="pants"
8776 name="Pants Length Cloth"
8777 value_min="0"
8778 value_max="1"
8779 value_default=".8">
8780 <param_alpha
8781 tga_file="pants_length_alpha.tga"
8782 domain="0.01" />
8783 </param>
8784 </layer>
8785
8786 <layer
8787 name="lower_jacket base bump"
8788 render_pass="bump"
8789 fixed_color="128,128,128,255">
8790 <texture
8791 local_texture="lower_jacket"
8792 local_texture_alpha_only="true" />
8793
8794 <param
8795 id="1033"
8796 group="1"
8797 wearable="jacket"
8798 edit_group="driven"
8799 cross_wearable="true"
8800 name="jacket bottom length lower bump"
8801 value_min="0"
8802 value_max="1">
8803 <param_alpha
8804 multiply_blend="false"
8805 tga_file="jacket_length_lower_alpha.tga"
8806 domain="0.01" />
8807 </param>
8808
8809 <param
8810 id="1034"
8811 group="1"
8812 wearable="jacket"
8813 edit_group="driven"
8814 name="jacket open lower bump"
8815 value_min="0"
8816 value_max="1">
8817 <param_alpha
8818 multiply_blend="true"
8819 tga_file="jacket_open_lower_alpha.tga"
8820 domain="0.01" />
8821 </param>
8822 </layer>
8823
8824 <layer
8825 name="lower_jacket bump"
8826 render_pass="bump">
8827 <texture
8828 tga_file="bump_pants_wrinkles.tga" />
8829
8830 <texture
8831 local_texture="lower_jacket"
8832 local_texture_alpha_only="true" />
8833
8834
8835 <param
8836 id="876"
8837 group="1"
8838 wearable="jacket"
8839 name="jacket upper Wrinkles"
8840 value_min="0"
8841 value_max="1"
8842 value_default="0">
8843 <param_color>
8844 <value
8845 color="255, 255, 255, 0" />
8846
8847 <value
8848 color="255, 255, 255, 255" />
8849 </param_color>
8850 </param>
8851
8852 <param
8853 id="1027"
8854 group="1"
8855 wearable="jacket"
8856 edit_group="driven"
8857 name="jacket bottom length lower bump"
8858 value_min="0"
8859 value_max="1">
8860 <param_alpha
8861 multiply_blend="false"
8862 tga_file="jacket_length_lower_alpha.tga"
8863 domain="0.01" />
8864 </param>
8865
8866 <param
8867 id="1028"
8868 group="1"
8869 wearable="jacket"
8870 edit_group="driven"
8871 name="jacket open lower bump"
8872 value_min="0"
8873 value_max="1">
8874 <param_alpha
8875 multiply_blend="true"
8876 tga_file="jacket_open_lower_alpha.tga"
8877 domain="0.01" />
8878 </param>
8879 </layer>
8880
8881 <layer
8882 name="lower_jacket">
8883 <texture
8884 local_texture="lower_jacket" />
8885
8886 <param
8887 id="809"
8888 group="1"
8889 edit_group="colorpicker_driven"
8890 wearable="jacket"
8891 name="lower_jacket_red"
8892 value_min="0"
8893 value_max="1"
8894 value_default="1">
8895 <param_color>
8896 <value
8897 color="0, 0, 0, 255" />
8898
8899 <value
8900 color="255, 0, 0, 255" />
8901 </param_color>
8902 </param>
8903
8904 <param
8905 id="810"
8906 group="1"
8907 edit_group="colorpicker_driven"
8908 wearable="jacket"
8909 name="lower_jacket_green"
8910 value_min="0"
8911 value_max="1"
8912 value_default="1">
8913 <param_color>
8914 <value
8915 color="0, 0, 0, 255" />
8916
8917 <value
8918 color="0, 255, 0, 255" />
8919 </param_color>
8920 </param>
8921
8922 <param
8923 id="811"
8924 group="1"
8925 edit_group="colorpicker_driven"
8926 wearable="jacket"
8927 name="lower_jacket_blue"
8928 value_min="0"
8929 value_max="1"
8930 value_default="1">
8931 <param_color>
8932 <value
8933 color="0, 0, 0, 255" />
8934
8935 <value
8936 color="0, 0, 255, 255" />
8937 </param_color>
8938 </param>
8939
8940 <param
8941 id="621"
8942 group="1"
8943 wearable="jacket"
8944 edit_group="jacket"
8945 name="bottom length lower"
8946 label_min="hi cut"
8947 label_max="low cut"
8948 value_min="0"
8949 value_max="1"
8950 value_default=".8"
8951 camera_distance="1.2"
8952 camera_angle="30"
8953 camera_elevation=".2">
8954 <param_alpha
8955 multiply_blend="false"
8956 tga_file="jacket_length_lower_alpha.tga"
8957 domain="0.01" />
8958 </param>
8959
8960 <param
8961 id="623"
8962 group="1"
8963 wearable="jacket"
8964 edit_group="jacket"
8965 name="open lower"
8966 label_min="open"
8967 label_max="closed"
8968 value_min="0"
8969 value_max="1"
8970 value_default=".8"
8971 camera_distance="1.2"
8972 camera_angle="30"
8973 camera_elevation=".2">
8974 <param_alpha
8975 multiply_blend="true"
8976 tga_file="jacket_open_lower_alpha.tga"
8977 domain="0.01" />
8978 </param>
8979 </layer>
8980
8981 <layer
8982 name="lower alpha"
8983 visibility_mask="TRUE">
8984 <texture
8985 local_texture="lower_alpha" />
8986 </layer>
8987
8988 </layer_set>
8989
8990 <!-- =========================================================== -->
8991 <layer_set
8992 body_region="eyes"
8993 width="128"
8994 height="128">
8995 <layer
8996 name="whites">
8997 <texture
8998 tga_file="eyewhite.tga" />
8999 </layer>
9000
9001 <layer
9002 name="iris"
9003 global_color="eye_color">
9004 <texture
9005 local_texture="eyes_iris" />
9006 </layer>
9007
9008 <layer
9009 name="eyes alpha"
9010 visibility_mask="TRUE">
9011 <texture
9012 local_texture="eyes_alpha" />
9013 </layer>
9014
9015 </layer_set>
9016
9017 <!-- =========================================================== -->
9018 <layer_set
9019 body_region="skirt"
9020 width="512"
9021 height="512"
9022 clear_alpha="false">
9023 <layer
9024 name="skirt_fabric"
9025 write_all_channels="true">
9026 <texture
9027 local_texture="skirt" />
9028
9029 <param
9030 id="921"
9031 group="0"
9032 wearable="skirt"
9033 edit_group="colorpicker"
9034 name="skirt_red"
9035 value_min="0"
9036 value_max="1"
9037 value_default="1">
9038 <param_color>
9039 <value
9040 color="0, 0, 0, 255" />
9041
9042 <value
9043 color="255, 0, 0, 255" />
9044 </param_color>
9045 </param>
9046
9047 <param
9048 id="922"
9049 group="0"
9050 wearable="skirt"
9051 edit_group="colorpicker"
9052 name="skirt_green"
9053 value_min="0"
9054 value_max="1"
9055 value_default="1">
9056 <param_color>
9057 <value
9058 color="0, 0, 0, 255" />
9059
9060 <value
9061 color="0, 255, 0, 255" />
9062 </param_color>
9063 </param>
9064
9065 <param
9066 id="923"
9067 group="0"
9068 wearable="skirt"
9069 edit_group="colorpicker"
9070 name="skirt_blue"
9071 value_min="0"
9072 value_max="1"
9073 value_default="1">
9074 <param_color>
9075 <value
9076 color="0, 0, 0, 255" />
9077
9078 <value
9079 color="0, 0, 255, 255" />
9080 </param_color>
9081 </param>
9082 </layer>
9083
9084 <layer
9085 name="skirt_fabric_alpha">
9086 <param
9087 id="858"
9088 group="0"
9089 wearable="skirt"
9090 edit_group="skirt"
9091 edit_group_order="1"
9092 name="Skirt Length"
9093 show_simple="true"
9094 label_min="Short"
9095 label_max="Long"
9096 value_min=".01"
9097 value_max="1"
9098 value_default=".4"
9099 simple_percent_min="40"
9100 simple_percent_max="100"
9101 camera_distance="1.3"
9102 camera_elevation="-.5"
9103 camera_angle="30">
9104 <param_alpha
9105 tga_file="skirt_length_alpha.tga"
9106 domain="0"
9107 multiply_blend="true" />
9108 </param>
9109
9110 <param
9111 id="859"
9112 group="0"
9113 wearable="skirt"
9114 edit_group="skirt"
9115 edit_group_order="4"
9116 name="Slit Front"
9117 label_min="Open Front"
9118 label_max="Closed Front"
9119 value_min="0"
9120 value_max="1"
9121 value_default="1"
9122 camera_distance="1.3"
9123 camera_elevation="-.5"
9124 camera_angle="30">
9125 <param_alpha
9126 tga_file="skirt_slit_front_alpha.tga"
9127 multiply_blend="true"
9128 domain="0" />
9129 </param>
9130
9131 <param
9132 id="860"
9133 group="0"
9134 wearable="skirt"
9135 edit_group="skirt"
9136 edit_group_order="5"
9137 name="Slit Back"
9138 label_min="Open Back"
9139 label_max="Closed Back"
9140 value_min="0"
9141 value_max="1"
9142 value_default="1"
9143 camera_distance="1.3"
9144 camera_elevation="-.5"
9145 camera_angle="160">
9146 <param_alpha
9147 tga_file="skirt_slit_back_alpha.tga"
9148 multiply_blend="true"
9149 domain="0" />
9150 </param>
9151
9152 <param
9153 id="861"
9154 group="0"
9155 wearable="skirt"
9156 edit_group="skirt"
9157 edit_group_order="6"
9158 name="Slit Left"
9159 label_min="Open Left"
9160 label_max="Closed Left"
9161 value_min="0"
9162 value_max="1"
9163 value_default="1"
9164 camera_distance="1.3"
9165 camera_elevation="-.5"
9166 camera_angle="30">
9167 <param_alpha
9168 tga_file="skirt_slit_left_alpha.tga"
9169 multiply_blend="true"
9170 domain="0" />
9171 </param>
9172
9173 <param
9174 id="862"
9175 group="0"
9176 wearable="skirt"
9177 edit_group="skirt"
9178 edit_group_order="7"
9179 name="Slit Right"
9180 label_min="Open Right"
9181 label_max="Closed Right"
9182 value_min="0"
9183 value_max="1"
9184 value_default="1"
9185 camera_distance="1.3"
9186 camera_elevation="-.5"
9187 camera_angle="-30">
9188 <param_alpha
9189 tga_file="skirt_slit_right_alpha.tga"
9190 multiply_blend="true"
9191 domain="0" />
9192 </param>
9193 </layer>
9194
9195 </layer_set>
9196
9197 <!-- =========================================================== -->
9198 <driver_parameters>
9199
9200 <param
9201 id="828"
9202 group="0"
9203 name="Loose Upper Clothing"
9204 label="Shirt Fit"
9205 show_simple="true"
9206 wearable="shirt"
9207 edit_group="shirt"
9208 edit_group_order="4"
9209 label_min="Tight Shirt"
9210 label_max="Loose Shirt"
9211 value_min="0"
9212 value_max="1"
9213 camera_distance="1.2"
9214 camera_angle="30"
9215 camera_elevation=".2">
9216 <param_driver>
9217 <driven
9218 id="628" />
9219
9220 <driven
9221 id="899"
9222 min1="0.1"
9223 max1="0.5"
9224 max2="1"
9225 min2="1" />
9226 </param_driver>
9227 </param>
9228
9229 <param
9230 id="816"
9231 group="0"
9232 name="Loose Lower Clothing"
9233 label="Pants Fit"
9234 show_simple="true"
9235 wearable="pants"
9236 edit_group="pants"
9237 edit_group_order="2.5"
9238 label_min="Tight Pants"
9239 label_max="Loose Pants"
9240 value_min="0"
9241 value_max="1"
9242 camera_distance="1.8"
9243 camera_angle="30"
9244 camera_elevation="-.3">
9245 <param_driver>
9246 <driven
9247 id="516" />
9248
9249 <driven
9250 id="913"
9251 min1="0.1"
9252 max1="0.5"
9253 max2="1"
9254 min2="1" />
9255 </param_driver>
9256 </param>
9257
9258 <param
9259 id="814"
9260 group="0"
9261 wearable="pants"
9262 edit_group="pants"
9263 edit_group_order="2"
9264 name="Waist Height"
9265 label_min="Low"
9266 label_max="High"
9267 value_min="0"
9268 value_max="1"
9269 value_default="1"
9270 camera_distance="1.2"
9271 camera_angle="30"
9272 camera_elevation="-.3">
9273 <param_driver>
9274 <driven
9275 id="614" />
9276
9277 <driven
9278 id="1017" />
9279
9280 <driven
9281 id="1035" />
9282
9283 <driven
9284 id="914"
9285 min1="0"
9286 max1=".98"
9287 max2="1"
9288 min2="1" />
9289 </param_driver>
9290 </param>
9291
9292 <param
9293 id="815"
9294 group="0"
9295 wearable="pants"
9296 edit_group="pants"
9297 edit_group_order="1"
9298 name="Pants Length"
9299 show_simple="true"
9300 label_min="Short"
9301 label_max="Long"
9302 value_min="0"
9303 value_max="1"
9304 value_default=".8"
9305 simple_percent_min="20"
9306 simple_percent_max="100"
9307 camera_distance="1.8"
9308 camera_angle="30"
9309 camera_elevation="-.3">
9310 <param_driver>
9311 <driven
9312 id="615"
9313 min1="0"
9314 max1=".9"
9315 max2="1"
9316 min2="1" />
9317
9318 <driven
9319 id="1018"
9320 min1="0"
9321 max1=".9"
9322 max2="1"
9323 min2="1" />
9324
9325 <driven
9326 id="1036"
9327 min1="0"
9328 max1=".9"
9329 max2="1"
9330 min2="1" />
9331
9332 <driven
9333 id="793"
9334 min1=".9"
9335 max1="1"
9336 max2="1"
9337 min2="1" />
9338
9339 <driven
9340 id="915"
9341 min1="0"
9342 max1=".882"
9343 max2="1"
9344 min2="1" />
9345 </param_driver>
9346 </param>
9347
9348 <param
9349 id="800"
9350 group="0"
9351 wearable="shirt"
9352 edit_group="shirt"
9353 edit_group_order="1"
9354 name="Sleeve Length"
9355 show_simple="true"
9356 label_min="Short"
9357 label_max="Long"
9358 value_min="0"
9359 value_max="1"
9360 value_default=".89"
9361 simple_percent_min="15"
9362 simple_percent_max="100"
9363 camera_distance="1.2"
9364 camera_angle="30"
9365 camera_elevation=".2">
9366 <param_driver>
9367 <driven
9368 id="600" />
9369
9370 <driven
9371 id="1013" />
9372
9373 <driven
9374 id="1029" />
9375
9376 <driven
9377 id="900"
9378 min1="0"
9379 max1="1"
9380 max2="1"
9381 min2="1" />
9382 </param_driver>
9383 </param>
9384
9385 <param
9386 id="801"
9387 group="0"
9388 wearable="shirt"
9389 edit_group="shirt"
9390 edit_group_order="2"
9391 name="Shirt Bottom"
9392 label_min="Short"
9393 label_max="Long"
9394 value_min="0"
9395 value_max="1"
9396 value_default="1"
9397 camera_distance="1.2"
9398 camera_angle="30"
9399 camera_elevation=".2">
9400 <param_driver>
9401 <driven
9402 id="601" />
9403
9404 <driven
9405 id="1014" />
9406
9407 <driven
9408 id="1030" />
9409
9410 <driven
9411 id="901"
9412 min1="0"
9413 max1=".98"
9414 max2="1"
9415 min2="1" />
9416 </param_driver>
9417 </param>
9418
9419 <param
9420 id="802"
9421 group="0"
9422 wearable="shirt"
9423 edit_group="shirt"
9424 edit_group_order="3"
9425 name="Collar Front"
9426 show_simple="true"
9427 label_min="Low"
9428 label_max="High"
9429 value_min="0"
9430 value_max="1"
9431 value_default=".78"
9432 simple_percent_min="40"
9433 simple_percent_max="100"
9434 camera_distance="1.2"
9435 camera_angle="15"
9436 camera_elevation=".2">
9437 <param_driver>
9438 <driven
9439 id="602" />
9440
9441 <driven
9442 id="1015" />
9443
9444 <driven
9445 id="1031" />
9446
9447 <driven
9448 id="902"
9449 min1="0"
9450 max1=".98"
9451 max2="1"
9452 min2="1" />
9453 </param_driver>
9454 </param>
9455
9456 <param
9457 id="781"
9458 group="0"
9459 wearable="shirt"
9460 edit_group="shirt"
9461 edit_group_order="3.1"
9462 name="Collar Back"
9463 label_min="Low"
9464 label_max="High"
9465 value_min="0"
9466 value_max="1"
9467 value_default=".78"
9468 camera_distance="1.2"
9469 camera_angle="195"
9470 camera_elevation=".2">
9471 <param_driver>
9472 <driven
9473 id="778" />
9474
9475 <driven
9476 id="1016" />
9477
9478 <driven
9479 id="1032" />
9480
9481 <driven
9482 id="903"
9483 min1="0"
9484 max1=".98"
9485 max2="1"
9486 min2="1" />
9487 </param_driver>
9488 </param>
9489
9490 <param
9491 id="150"
9492 group="0"
9493 wearable="skin"
9494 edit_group="skin_bodydetail"
9495 name="Body Definition"
9496 label_min="Less"
9497 label_max="More"
9498 value_min="0"
9499 value_max="1"
9500 value_default="0"
9501 camera_distance="1.4"
9502 camera_elevation="-.2">
9503 <param_driver>
9504 <driven
9505 id="125" />
9506
9507 <driven
9508 id="126" />
9509
9510 <driven
9511 id="160" />
9512
9513 <driven
9514 id="161" />
9515
9516 <driven
9517 id="874" />
9518
9519 <driven
9520 id="878" />
9521
9522 </param_driver>
9523 </param>
9524
9525 <param
9526 id="775"
9527 group="0"
9528 wearable="skin"
9529 edit_group="skin_bodydetail"
9530 name="Body Freckles"
9531 label_min="Less Freckles"
9532 label_max="More Freckles"
9533 value_min="0"
9534 value_max="1"
9535 value_default="0"
9536 camera_distance="1.4"
9537 camera_elevation="-.2">
9538 <param_driver>
9539 <driven
9540 id="776" />
9541
9542 <driven
9543 id="777" />
9544 </param_driver>
9545 </param>
9546
9547 <param
9548 id="162"
9549 group="0"
9550 wearable="skin"
9551 edit_group="skin_facedetail"
9552 edit_group_order="1"
9553 name="Facial Definition"
9554 label_min="Less"
9555 label_max="More"
9556 value_min="0"
9557 value_max="1"
9558 camera_distance=".3"
9559 camera_elevation=".07"
9560 value_default="0">
9561 <param_driver>
9562 <driven
9563 id="158" />
9564
9565 <driven
9566 id="159" />
9567
9568 <driven
9569 id="873" />
9570 </param_driver>
9571 </param>
9572
9573 <param
9574 id="163"
9575 group="0"
9576 wearable="skin"
9577 edit_group="skin_facedetail"
9578 edit_group_order="3"
9579 name="Wrinkles"
9580 label_min="Less"
9581 label_max="More"
9582 value_min="0"
9583 value_max="1"
9584 camera_distance=".3"
9585 camera_elevation=".07"
9586 value_default="0">
9587 <param_driver>
9588 <!--<driven
9589 id="128" />-->
9590 <driven
9591 id="118" />
9592 </param_driver>
9593 </param>
9594
9595 <param
9596 id="505"
9597 group="0"
9598 wearable="shape"
9599 edit_group="shape_mouth"
9600 edit_group_order="3"
9601 name="Lip Thickness"
9602 label_min="Thin Lips"
9603 label_max="Fat Lips"
9604 value_min="0"
9605 value_max="1"
9606 value_default=".5"
9607 camera_distance=".3"
9608 camera_elevation=".04"
9609 camera_angle="20">
9610 <param_driver>
9611 <driven
9612 id="26"
9613 min1="0"
9614 max1="0"
9615 max2="0"
9616 min2=".5" />
9617
9618 <driven
9619 id="28"
9620 min1=".5"
9621 max1="1"
9622 max2="1"
9623 min2="1" />
9624 </param_driver>
9625 </param>
9626
9627 <param
9628 id="799"
9629 group="0"
9630 wearable="shape"
9631 edit_group="shape_mouth"
9632 edit_group_order="3.2"
9633 name="Lip Ratio"
9634 label="Lip Ratio"
9635 show_simple="true"
9636 label_min="More Upper Lip"
9637 label_max="More Lower Lip"
9638 value_min="0"
9639 value_max="1"
9640 value_default=".5"
9641 camera_distance=".3"
9642 camera_elevation=".04"
9643 camera_angle="20">
9644 <param_driver>
9645 <driven
9646 id="797"
9647 min1="0"
9648 max1="0"
9649 max2="0"
9650 min2=".5" />
9651
9652 <driven
9653 id="798"
9654 min1=".5"
9655 max1="1"
9656 max2="1"
9657 min2="1" />
9658 </param_driver>
9659 </param>
9660
9661 <param
9662 id="155"
9663 group="0"
9664 wearable="shape"
9665 edit_group="shape_mouth"
9666 edit_group_order="1"
9667 name="Lip Width"
9668 label="Lip Width"
9669 label_min="Narrow Lips"
9670 label_max="Wide Lips"
9671 show_simple="true"
9672 value_min="-0.9"
9673 value_max="1.3"
9674 camera_distance=".3"
9675 camera_elevation=".04"
9676 value_default="0">
9677 <param_driver>
9678 <driven
9679 id="29" />
9680
9681 <driven
9682 id="30" />
9683 </param_driver>
9684 </param>
9685
9686 <param
9687 id="196"
9688 group="0"
9689 wearable="shape"
9690 edit_group="shape_eyes"
9691 edit_group_order="2"
9692 name="Eye Spacing"
9693 label="Eye Spacing"
9694 label_min="Close Set Eyes"
9695 label_max="Far Set Eyes"
9696 show_simple="true"
9697 value_min="-2"
9698 value_max="1"
9699 value_default="0"
9700 camera_elevation=".1"
9701 camera_distance=".35"
9702 camera_angle="5">
9703 <param_driver>
9704 <driven
9705 id="194" />
9706
9707 <driven
9708 id="195" />
9709 </param_driver>
9710 </param>
9711
9712 <param
9713 id="769"
9714 group="0"
9715 wearable="shape"
9716 edit_group="shape_eyes"
9717 edit_group_order="4.5"
9718 name="Eye Depth"
9719 label_min="Sunken Eyes"
9720 label_max="Bugged Eyes"
9721 value_min="0"
9722 value_max="1"
9723 value_default=".5"
9724 camera_elevation=".1"
9725 camera_distance=".3"
9726 camera_angle="75">
9727 <param_driver>
9728 <driven
9729 id="767" />
9730
9731 <driven
9732 id="768" />
9733 </param_driver>
9734 </param>
9735
9736 <param
9737 id="198"
9738 group="0"
9739 wearable="shoes"
9740 edit_group="shoes"
9741 edit_group_order="2"
9742 name="Heel Height"
9743 label_min="Low Heels"
9744 label_max="High Heels"
9745 value_min="0"
9746 value_max="1"
9747 value_default="0"
9748 camera_angle="45"
9749 camera_distance=".8"
9750 camera_elevation="-1">
9751 <param_driver>
9752 <driven
9753 id="197" />
9754
9755 <driven
9756 id="500" />
9757 </param_driver>
9758 </param>
9759
9760 <param
9761 id="513"
9762 group="0"
9763 wearable="shoes"
9764 edit_group="shoes"
9765 edit_group_order="3"
9766 name="Heel Shape"
9767 label_min="Pointy Heels"
9768 label_max="Thick Heels"
9769 value_min="0"
9770 value_max="1"
9771 value_default=".5"
9772 camera_angle="45"
9773 camera_distance="1.5"
9774 camera_elevation="-1">
9775 <param_driver>
9776 <driven
9777 id="509"
9778 min1="0"
9779 max1="0"
9780 max2="0"
9781 min2=".5" />
9782
9783 <driven
9784 id="510"
9785 min1=".5"
9786 max1="1"
9787 max2="1"
9788 min2="1" />
9789 </param_driver>
9790 </param>
9791
9792 <param
9793 id="514"
9794 group="0"
9795 wearable="shoes"
9796 edit_group="shoes"
9797 edit_group_order="4"
9798 name="Toe Shape"
9799 label_min="Pointy"
9800 label_max="Square"
9801 value_min="0"
9802 value_max="1"
9803 value_default=".5"
9804 camera_angle="5"
9805 camera_distance=".8"
9806 camera_elevation="-.8">
9807 <param_driver>
9808 <driven
9809 id="511"
9810 min1="0"
9811 max1="0"
9812 max2="0"
9813 min2=".5" />
9814
9815 <driven
9816 id="512"
9817 min1=".5"
9818 max1="1"
9819 max2="1"
9820 min2="1" />
9821 </param_driver>
9822 </param>
9823
9824 <param
9825 id="503"
9826 group="0"
9827 wearable="shoes"
9828 edit_group="shoes"
9829 edit_group_order="6"
9830 name="Platform Height"
9831 label_min="Low Platforms"
9832 label_max="High Platforms"
9833 value_min="0"
9834 value_max="1"
9835 value_default="0"
9836 camera_angle="45"
9837 camera_distance=".5"
9838 camera_elevation="-1">
9839 <param_driver>
9840 <driven
9841 id="501" />
9842
9843 <driven
9844 id="502" />
9845 </param_driver>
9846 </param>
9847
9848 <param
9849 id="193"
9850 group="0"
9851 wearable="shape"
9852 edit_group="shape_head"
9853 edit_group_order="3"
9854 name="Head Shape"
9855 label="Head Shape"
9856 label_min="More Square"
9857 label_max="More Round"
9858 show_simple="true"
9859 value_min="0"
9860 value_max="1"
9861 value_default=".5"
9862 camera_elevation=".1"
9863 camera_distance=".5"
9864 camera_angle="20">
9865 <param_driver>
9866 <driven
9867 id="188"
9868 min1="0"
9869 max1="0"
9870 max2="0"
9871 min2=".5" />
9872
9873 <driven
9874 id="642"
9875 min1="0"
9876 max1="0"
9877 max2="0"
9878 min2=".5" />
9879
9880 <driven
9881 id="189"
9882 min1=".5"
9883 max1="1"
9884 max2="1"
9885 min2="1" />
9886
9887 <driven
9888 id="643"
9889 min1=".5"
9890 max1="1"
9891 max2="1"
9892 min2="1" />
9893 </param_driver>
9894 </param>
9895
9896 <param
9897 id="157"
9898 group="0"
9899 wearable="shape"
9900 edit_group="shape_torso"
9901 edit_group_order="13"
9902 name="Belly Size"
9903 label_min="Small"
9904 label_max="Big"
9905 value_min="0"
9906 value_max="1"
9907 value_default="0"
9908 camera_distance="1.4"
9909 camera_angle="30"
9910 camera_elevation=".2">
9911 <param_driver>
9912 <driven
9913 id="104" />
9914
9915 <driven
9916 id="156" />
9917
9918 <driven
9919 id="849" />
9920 </param_driver>
9921 </param>
9922
9923 <param
9924 id="637"
9925 group="0"
9926 wearable="shape"
9927 edit_group="shape_body"
9928 edit_group_order="3"
9929 name="Body Fat"
9930 label_min="Less Body Fat"
9931 label_max="More Body Fat"
9932 value_min="0"
9933 value_max="1"
9934 value_default="0"
9935 camera_distance="1.8">
9936 <param_driver>
9937 <driven
9938 id="633" />
9939
9940 <driven
9941 id="634" />
9942
9943 <driven
9944 id="635" />
9945
9946 <driven
9947 id="851" />
9948 </param_driver>
9949 </param>
9950
9951 <param
9952 id="130"
9953 group="0"
9954 wearable="hair"
9955 edit_group="hair_style"
9956 edit_group_order="8"
9957 name="Front Fringe"
9958 label_min="Short"
9959 label_max="Long"
9960 value_min="0"
9961 value_max="1"
9962 value_default=".45"
9963 camera_elevation=".1"
9964 camera_distance=".5"
9965 camera_angle="20">
9966 <param_driver>
9967 <driven
9968 id="144"
9969 min1="0"
9970 max1="0"
9971 max2="0"
9972 min2=".5" />
9973
9974 <driven
9975 id="145"
9976 min1=".5"
9977 max1="1"
9978 max2="1"
9979 min2="1" />
9980 </param_driver>
9981 </param>
9982
9983 <param
9984 id="131"
9985 group="0"
9986 wearable="hair"
9987 edit_group="hair_style"
9988 edit_group_order="9"
9989 name="Side Fringe"
9990 label_min="Short"
9991 label_max="Long"
9992 value_min="0"
9993 value_max="1"
9994 value_default=".5"
9995 camera_elevation=".1"
9996 camera_distance=".5"
9997 camera_angle="90">
9998 <param_driver>
9999 <driven
10000 id="146"
10001 min1="0"
10002 max1="0"
10003 max2="0"
10004 min2=".5" />
10005
10006 <driven
10007 id="147"
10008 min1=".5"
10009 max1="1"
10010 max2="1"
10011 min2="1" />
10012 </param_driver>
10013 </param>
10014
10015 <param
10016 id="132"
10017 group="0"
10018 wearable="hair"
10019 edit_group="hair_style"
10020 edit_group_order="10"
10021 name="Back Fringe"
10022 label_min="Short"
10023 label_max="Long"
10024 value_min="0"
10025 value_max="1"
10026 value_default=".39"
10027 camera_elevation=".1"
10028 camera_distance=".5"
10029 camera_angle="160">
10030 <param_driver>
10031 <driven
10032 id="148"
10033 min1="0"
10034 max1="0"
10035 max2="0"
10036 min2=".5" />
10037
10038 <driven
10039 id="149"
10040 min1=".5"
10041 max1="1"
10042 max2="1"
10043 min2="1" />
10044 </param_driver>
10045 </param>
10046
10047 <param
10048 id="133"
10049 group="0"
10050 wearable="hair"
10051 edit_group="hair_style"
10052 edit_group_order="2"
10053 name="Hair Front"
10054 label_min="Short"
10055 label_max="Long"
10056 value_min="0"
10057 value_max="1"
10058 value_default=".25"
10059 camera_elevation=".1"
10060 camera_distance=".5"
10061 camera_angle="20">
10062 <param_driver>
10063 <driven
10064 id="172"
10065 min1="0"
10066 max1="0"
10067 max2="0"
10068 min2=".5" />
10069
10070 <driven
10071 id="171"
10072 min1=".5"
10073 max1="1"
10074 max2="1"
10075 min2="1" />
10076 </param_driver>
10077 </param>
10078
10079 <param
10080 id="134"
10081 group="0"
10082 wearable="hair"
10083 edit_group="hair_style"
10084 edit_group_order="3"
10085 name="Hair Sides"
10086 label_min="Short"
10087 label_max="Long"
10088 value_min="0"
10089 value_max="1"
10090 value_default=".5"
10091 camera_elevation=".1"
10092 camera_distance=".5"
10093 camera_angle="90">
10094 <param_driver>
10095 <driven
10096 id="174"
10097 min1="0"
10098 max1="0"
10099 max2="0"
10100 min2=".5" />
10101
10102 <driven
10103 id="173"
10104 min1=".5"
10105 max1="1"
10106 max2="1"
10107 min2="1" />
10108 </param_driver>
10109 </param>
10110
10111 <param
10112 id="135"
10113 group="0"
10114 wearable="hair"
10115 edit_group="hair_style"
10116 edit_group_order="4"
10117 name="Hair Back"
10118 show_simple="true"
10119 label_min="Short"
10120 label_max="Long"
10121 value_min="0"
10122 value_max="1"
10123 value_default=".55"
10124 camera_elevation="-.1"
10125 camera_distance=".8"
10126 camera_angle="160">
10127 <param_driver>
10128 <driven
10129 id="176"
10130 min1="0"
10131 max1="0"
10132 max2="0"
10133 min2=".5" />
10134
10135 <driven
10136 id="175"
10137 min1=".5"
10138 max1="1"
10139 max2="1"
10140 min2="1" />
10141 </param_driver>
10142 </param>
10143
10144 <param
10145 id="136"
10146 group="0"
10147 wearable="hair"
10148 edit_group="hair_style"
10149 edit_group_order="11.5"
10150 name="Hair Sweep"
10151 label_min="Sweep Forward"
10152 label_max="Sweep Back"
10153 value_min="0"
10154 value_max="1"
10155 value_default=".5"
10156 camera_elevation=".1"
10157 camera_distance=".5"
10158 camera_angle="90">
10159 <param_driver>
10160 <driven
10161 id="179"
10162 min1="0"
10163 max1="0"
10164 max2="0"
10165 min2=".5" />
10166
10167 <driven
10168 id="178"
10169 min1=".5"
10170 max1="1"
10171 max2="1"
10172 min2="1" />
10173 </param_driver>
10174 </param>
10175
10176 <param
10177 id="137"
10178 group="0"
10179 wearable="hair"
10180 edit_group="hair_style"
10181 edit_group_order="16"
10182 name="Hair Tilt"
10183 label_min="Left"
10184 label_max="Right"
10185 value_min="0"
10186 value_max="1"
10187 value_default=".5"
10188 camera_elevation=".1"
10189 camera_distance=".5"
10190 camera_angle="0">
10191 <param_driver>
10192 <driven
10193 id="190"
10194 min1="0"
10195 max1="0"
10196 max2="0"
10197 min2=".5" />
10198
10199 <driven
10200 id="191"
10201 min1=".5"
10202 max1="1"
10203 max2="1"
10204 min2="1" />
10205 </param_driver>
10206 </param>
10207
10208 <param
10209 id="608"
10210 group="0"
10211 wearable="jacket"
10212 edit_group="jacket"
10213 edit_group_order="2"
10214 name="bottom length lower"
10215 label="Jacket Length"
10216 label_min="Short"
10217 label_max="Long"
10218 value_min="0"
10219 value_max="1"
10220 value_default=".8"
10221 camera_distance="1.4"
10222 camera_angle="30"
10223 camera_elevation=".2">
10224 <param_driver>
10225 <driven
10226 id="620" />
10227
10228 <driven
10229 id="1025" />
10230
10231 <driven
10232 id="1037" />
10233
10234 <driven
10235 id="621" />
10236
10237 <driven
10238 id="1027" />
10239
10240 <driven
10241 id="1033" />
10242 </param_driver>
10243 </param>
10244
10245 <param
10246 id="609"
10247 group="0"
10248 wearable="jacket"
10249 edit_group="jacket"
10250 edit_group_order="4"
10251 name="open jacket"
10252 label="Open Front"
10253 label_min="Open"
10254 label_max="Closed"
10255 value_min="0"
10256 value_max="1"
10257 value_default=".2"
10258 camera_distance="1.4"
10259 camera_angle="30"
10260 camera_elevation=".2">
10261 <param_driver>
10262 <driven
10263 id="622" />
10264
10265 <driven
10266 id="1026" />
10267
10268 <driven
10269 id="1038" />
10270
10271 <driven
10272 id="623" />
10273
10274 <driven
10275 id="1028" />
10276
10277 <driven
10278 id="1034" />
10279 </param_driver>
10280 </param>
10281
10282 <param
10283 id="105"
10284 group="0"
10285 sex="female"
10286 wearable="shape"
10287 edit_group="shape_torso"
10288 edit_group_order="6"
10289 name="Breast Size"
10290 label_min="Small"
10291 label_max="Large"
10292 value_min="0"
10293 value_max="1"
10294 value_default=".5"
10295 camera_elevation=".3"
10296 camera_distance="1.2"
10297 camera_angle="30">
10298 <param_driver>
10299 <driven
10300 id="843"
10301 min1="0"
10302 max1="0"
10303 max2="0"
10304 min2=".01" />
10305
10306 <driven
10307 id="627"
10308 min1="0"
10309 max1="0.01"
10310 max2="0.01"
10311 min2=".5" />
10312
10313 <driven
10314 id="626"
10315 min1=".5"
10316 max1="1"
10317 max2="1"
10318 min2="1" />
10319 </param_driver>
10320 </param>
10321
10322 <param
10323 id="629"
10324 group="0"
10325 wearable="shape"
10326 edit_group="shape_head"
10327 edit_group_order="6"
10328 name="Forehead Angle"
10329 label_min="More Vertical"
10330 label_max="More Sloped"
10331 value_min="0"
10332 value_max="1"
10333 value_default=".5"
10334 camera_elevation=".1"
10335 camera_distance=".5"
10336 camera_angle="70">
10337 <param_driver>
10338 <driven
10339 id="630"
10340 min1="0"
10341 max1="0"
10342 max2="0"
10343 min2=".5" />
10344
10345 <driven
10346 id="644"
10347 min1="0"
10348 max1="0"
10349 max2="0"
10350 min2=".5" />
10351
10352 <driven
10353 id="631"
10354 min1=".5"
10355 max1="1"
10356 max2="1"
10357 min2="1" />
10358
10359 <driven
10360 id="645"
10361 min1=".5"
10362 max1="1"
10363 max2="1"
10364 min2="1" />
10365 </param_driver>
10366 </param>
10367
10368 <param
10369 id="646"
10370 group="0"
10371 name="Egg_Head"
10372 label="Egg Head"
10373 wearable="shape"
10374 edit_group="shape_head"
10375 edit_group_order="4"
10376 label_min="Chin Heavy"
10377 label_max="Forehead Heavy"
10378 show_simple="true"
10379 value_min="-1.3"
10380 value_max="1"
10381 value_default="0"
10382 camera_elevation=".1"
10383 camera_distance=".5"
10384 camera_angle="20">
10385 <param_driver>
10386 <driven
10387 id="640" />
10388
10389 <driven
10390 id="186" />
10391 </param_driver>
10392 </param>
10393
10394 <param
10395 id="647"
10396 group="0"
10397 name="Squash_Stretch_Head"
10398 label="Head Stretch"
10399 wearable="shape"
10400 edit_group="shape_head"
10401 edit_group_order="2"
10402 show_simple="true"
10403 label_min="Squash Head"
10404 label_max="Stretch Head"
10405 value_min="-0.5"
10406 value_max="1"
10407 value_default="0"
10408 camera_elevation=".1"
10409 camera_distance=".5"
10410 camera_angle="20">
10411 <param_driver>
10412 <driven
10413 id="641" />
10414
10415 <driven
10416 id="187" />
10417 </param_driver>
10418 </param>
10419
10420 <param
10421 id="649"
10422 group="0"
10423 sex="female"
10424 wearable="shape"
10425 edit_group="shape_torso"
10426 edit_group_order="1.1"
10427 name="Torso Muscles"
10428 label="Torso Muscles"
10429 show_simple="true"
10430 label_min="Less Muscular"
10431 label_max="More Muscular"
10432 value_min="0"
10433 value_max="1"
10434 value_default=".5"
10435 camera_elevation=".1"
10436 camera_distance="1"
10437 camera_angle="15">
10438 <param_driver>
10439 <driven
10440 id="648"
10441 min1="0"
10442 max1="0"
10443 max2="0"
10444 min2=".5" />
10445
10446 <driven
10447 id="106"
10448 min1=".5"
10449 max1="1"
10450 max2="1"
10451 min2="1" />
10452 </param_driver>
10453 </param>
10454
10455 <param
10456 id="678"
10457 group="0"
10458 sex="male"
10459 wearable="shape"
10460 edit_group="shape_torso"
10461 edit_group_order="1"
10462 name="Torso Muscles"
10463 show_simple="true"
10464 label_min="Less Muscular"
10465 label_max="More Muscular"
10466 value_min="0"
10467 value_max="1"
10468 value_default=".5"
10469 camera_elevation=".1"
10470 camera_distance="1.2"
10471 camera_angle="0">
10472 <param_driver>
10473 <driven
10474 id="677"
10475 min1="0"
10476 max1="0"
10477 max2="0"
10478 min2=".5" />
10479
10480 <driven
10481 id="106"
10482 min1=".5"
10483 max1="1"
10484 max2="1"
10485 min2="1" />
10486 </param_driver>
10487 </param>
10488
10489 <param
10490 id="652"
10491 group="0"
10492 wearable="shape"
10493 edit_group="shape_legs"
10494 edit_group_order="1"
10495 name="Leg Muscles"
10496 label_min="Less Muscular"
10497 label_max="More Muscular"
10498 show_simple="true"
10499 value_min="0"
10500 value_max="1"
10501 value_default=".5"
10502 camera_distance="1.3"
10503 camera_elevation="-.5"
10504 camera_angle="15">
10505 <param_driver>
10506 <driven
10507 id="651"
10508 min1="0"
10509 max1="0"
10510 max2="0"
10511 min2=".5" />
10512
10513 <driven
10514 id="152"
10515 min1=".5"
10516 max1="1"
10517 max2="1"
10518 min2="1" />
10519 </param_driver>
10520 </param>
10521
10522 <param
10523 id="80"
10524 name="male"
10525 group="0"
10526 edit_group="dummy"
10527 wearable="shape"
10528 value_min="0"
10529 value_max="1">
10530 <param_driver>
10531 <driven
10532 id="32" />
10533
10534 <driven
10535 id="153" />
10536
10537 <driven
10538 id="40" />
10539
10540 <driven
10541 id="100" />
10542
10543 <driven
10544 id="857" />
10545 </param_driver>
10546 </param>
10547
10548 <param
10549 id="659"
10550 group="0"
10551 wearable="shape"
10552 edit_group="shape_mouth"
10553 edit_group_order="5"
10554 name="Mouth Corner"
10555 label_min="Corner Down"
10556 label_max="Corner Up"
10557 value_min="0"
10558 value_max="1"
10559 value_default=".5"
10560 camera_elevation="0"
10561 camera_distance=".28">
10562 <param_driver>
10563 <driven
10564 id="658"
10565 min1="0"
10566 max1="0"
10567 max2="0"
10568 min2=".5" />
10569
10570 <driven
10571 id="657"
10572 min1=".5"
10573 max1="1"
10574 max2="1"
10575 min2="1" />
10576 </param_driver>
10577 </param>
10578
10579 <param
10580 id="662"
10581 group="0"
10582 wearable="shape"
10583 edit_group="shape_head"
10584 edit_group_order="5"
10585 name="Face Shear"
10586 label_min="Shear Right Up"
10587 label_max="Shear Left Up"
10588 value_min="0"
10589 value_max="1"
10590 value_default=".5"
10591 camera_elevation=".1"
10592 camera_distance=".5">
10593 <param_driver>
10594 <driven
10595 id="660" />
10596
10597 <driven
10598 id="661" />
10599
10600 <driven
10601 id="774" />
10602 </param_driver>
10603 </param>
10604
10605 <param
10606 id="773"
10607 group="0"
10608 wearable="shape"
10609 edit_group="shape_head"
10610 edit_group_order="4.5"
10611 name="Head Length"
10612 label_min="Flat Head"
10613 label_max="Long Head"
10614 value_min="0"
10615 value_max="1"
10616 value_default=".5"
10617 camera_elevation=".1"
10618 camera_distance=".5"
10619 camera_angle="75">
10620 <param_driver>
10621 <driven
10622 id="770" />
10623
10624 <driven
10625 id="771" />
10626
10627 <driven
10628 id="772" />
10629 </param_driver>
10630 </param>
10631
10632 <param
10633 id="682"
10634 group="0"
10635 wearable="shape"
10636 edit_group="shape_head"
10637 edit_group_order="1"
10638 name="Head Size"
10639 label="Head Size"
10640 label_min="Small Head"
10641 label_max="Big Head"
10642 show_simple="true"
10643 value_min="0"
10644 value_max="1"
10645 value_default=".5"
10646 camera_elevation=".1"
10647 camera_distance=".5">
10648 <param_driver>
10649 <driven
10650 id="679" />
10651
10652 <driven
10653 id="694" />
10654
10655 <driven
10656 id="680" />
10657
10658 <driven
10659 id="681" />
10660
10661 <driven
10662 id="655" />
10663 </param_driver>
10664 </param>
10665
10666 <param
10667 id="690"
10668 group="0"
10669 wearable="shape"
10670 edit_group="shape_eyes"
10671 edit_group_order="1"
10672 name="Eye Size"
10673 label="Eye Size"
10674 label_min="Beady Eyes"
10675 label_max="Anime Eyes"
10676 value_min="0"
10677 value_max="1"
10678 value_default=".5"
10679 show_simple="true"
10680 camera_elevation=".1"
10681 camera_distance=".35">
10682 <param_driver>
10683 <driven
10684 id="686" />
10685
10686 <driven
10687 id="687" />
10688
10689 <driven
10690 id="695" />
10691
10692 <driven
10693 id="688" />
10694
10695 <driven
10696 id="691" />
10697
10698 <driven
10699 id="689" />
10700 </param_driver>
10701 </param>
10702
10703 <param
10704 id="752"
10705 group="0"
10706 sex="male"
10707 wearable="hair"
10708 edit_group="hair_facial"
10709 edit_group_order="1"
10710 name="Hair Thickness"
10711 label_min="5 O'Clock Shadow"
10712 label_max="Bushy Hair"
10713 value_min="0"
10714 value_max="1"
10715 value_default=".5"
10716 camera_elevation="0"
10717 camera_distance=".28">
10718 <param_driver>
10719 <driven
10720 id="751"
10721 min1="0"
10722 max1="0"
10723 max2="0"
10724 min2=".2" />
10725
10726 <driven
10727 id="1012"
10728 min1="0"
10729 max1="0"
10730 max2=".2"
10731 min2=".6" />
10732
10733 <driven
10734 id="400"
10735 min1=".2"
10736 max1="1"
10737 max2="1"
10738 min2="1" />
10739 </param_driver>
10740 </param>
10741
10742 <param
10743 id="763"
10744 group="0"
10745 wearable="hair"
10746 edit_group="hair_style"
10747 edit_group_order="1"
10748 name="Hair Volume"
10749 show_simple="true"
10750 label_min="Less Volume"
10751 label_max="More Volume"
10752 value_min="0"
10753 value_max="1"
10754 value_default=".55"
10755 camera_elevation=".1"
10756 camera_distance=".5"
10757 camera_angle="20">
10758 <param_driver>
10759 <driven
10760 id="761"
10761 min1="0"
10762 max1="0"
10763 max2="0"
10764 min2=".5" />
10765
10766 <driven
10767 id="180"
10768 min1=".5"
10769 max1="1"
10770 max2="1"
10771 min2="1" />
10772 </param_driver>
10773 </param>
10774
10775 <param
10776 id="834"
10777 group="0"
10778 wearable="jacket"
10779 edit_group="colorpicker"
10780 name="jacket_red"
10781 value_min="0"
10782 value_max="1"
10783 value_default="1">
10784 <param_driver>
10785 <driven
10786 id="809"
10787 min1="0"
10788 max1="1"
10789 max2="1"
10790 min2="1" />
10791
10792 <driven
10793 id="831"
10794 min1="0"
10795 max1="1"
10796 max2="1"
10797 min2="1" />
10798 </param_driver>
10799 </param>
10800
10801 <param
10802 id="835"
10803 group="0"
10804 wearable="jacket"
10805 edit_group="colorpicker"
10806 name="jacket_green"
10807 value_min="0"
10808 value_max="1"
10809 value_default="1">
10810 <param_driver>
10811 <driven
10812 id="810"
10813 min1="0"
10814 max1="1"
10815 max2="1"
10816 min2="1" />
10817
10818 <driven
10819 id="832"
10820 min1="0"
10821 max1="1"
10822 max2="1"
10823 min2="1" />
10824 </param_driver>
10825 </param>
10826
10827 <param
10828 id="836"
10829 group="0"
10830 wearable="jacket"
10831 edit_group="colorpicker"
10832 name="jacket_blue"
10833 value_min="0"
10834 value_max="1"
10835 value_default="1">
10836 <param_driver>
10837 <driven
10838 id="811"
10839 min1="0"
10840 max1="1"
10841 max2="1"
10842 min2="1" />
10843
10844 <driven
10845 id="833"
10846 min1="0"
10847 max1="1"
10848 max2="1"
10849 min2="1" />
10850 </param_driver>
10851 </param>
10852
10853 <param
10854 id="785"
10855 group="0"
10856 wearable="hair"
10857 edit_group="hair_style"
10858 edit_group_order="14.6"
10859 name="Pigtails"
10860 show_simple="true"
10861 label_min="Short Pigtails"
10862 label_max="Long Pigtails"
10863 value_min="0"
10864 value_max="1"
10865 value_default="0"
10866 camera_elevation=".1"
10867 camera_distance=".5"
10868 camera_angle="15">
10869 <param_driver>
10870 <driven
10871 id="782"
10872 min1="0"
10873 max1=".10"
10874 max2=".10"
10875 min2=".5" />
10876
10877 <driven
10878 id="783"
10879 min1=".10"
10880 max1=".5"
10881 max2=".5"
10882 min2=".75" />
10883
10884 <driven
10885 id="790"
10886 min1=".5"
10887 max1=".75"
10888 max2=".75"
10889 min2="1" />
10890
10891 <driven
10892 id="784"
10893 min1=".75"
10894 max1="1"
10895 max2="1"
10896 min2="1" />
10897 </param_driver>
10898 </param>
10899
10900 <param
10901 id="789"
10902 group="0"
10903 wearable="hair"
10904 edit_group="hair_style"
10905 edit_group_order="14.7"
10906 name="Ponytail"
10907 label_min="Short Ponytail"
10908 label_max="Long Ponytail"
10909 value_min="0"
10910 value_max="1"
10911 value_default="0"
10912 camera_elevation=".1"
10913 camera_distance=".5"
10914 camera_angle="180">
10915 <param_driver>
10916 <driven
10917 id="786"
10918 min1="0"
10919 max1=".10"
10920 max2=".10"
10921 min2=".66" />
10922
10923 <driven
10924 id="787"
10925 min1=".10"
10926 max1=".66"
10927 max2=".66"
10928 min2="1" />
10929
10930 <driven
10931 id="788"
10932 min1=".66"
10933 max1="1"
10934 max2="1"
10935 min2="1" />
10936 </param_driver>
10937 </param>
10938
10939 <param
10940 id="795"
10941 group="0"
10942 name="Butt Size"
10943 label="Butt Size"
10944 wearable="shape"
10945 edit_group="shape_legs"
10946 edit_group_order="4"
10947 label_min="Flat Butt"
10948 label_max="Big Butt"
10949 value_min="0"
10950 value_max="1"
10951 value_default=".25"
10952 camera_angle="180"
10953 camera_distance=".6">
10954 <param_driver>
10955 <driven
10956 id="867"
10957 min1="0"
10958 max1="0"
10959 max2="0"
10960 min2=".3" />
10961
10962 <driven
10963 id="794"
10964 min1="0"
10965 max1="0"
10966 max2="0"
10967 min2=".3" />
10968
10969 <driven
10970 id="151"
10971 min1=".3"
10972 max1="1"
10973 max2="1"
10974 min2="1" />
10975
10976 <driven
10977 id="852"
10978 min1=".3"
10979 max1="1"
10980 max2="1"
10981 min2="1" />
10982 </param_driver>
10983 </param>
10984
10985 <param
10986 id="841"
10987 group="0"
10988 name="Bowed_Legs"
10989 label="Knee Angle"
10990 wearable="shape"
10991 edit_group_order="5.5"
10992 edit_group="shape_legs"
10993 label_min="Knock Kneed"
10994 label_max="Bow Legged"
10995 value_min="-1"
10996 value_max="1"
10997 value_default="0"
10998 camera_distance="1.3"
10999 camera_elevation="-.5">
11000 <param_driver>
11001 <driven
11002 id="853" />
11003
11004 <driven
11005 id="847" />
11006 </param_driver>
11007 </param>
11008
11009 <param
11010 id="753"
11011 group="0"
11012 name="Saddlebags"
11013 label="Saddle Bags"
11014 wearable="shape"
11015 edit_group="shape_legs"
11016 edit_group_order="5"
11017 label_min="Less Saddle"
11018 label_max="More Saddle"
11019 value_min="-0.5"
11020 value_max="3"
11021 value_default="0"
11022 camera_angle="0"
11023 camera_distance="1.2">
11024 <param_driver>
11025 <driven
11026 id="850" />
11027
11028 <driven
11029 id="854" />
11030 </param_driver>
11031 </param>
11032
11033 <param
11034 id="676"
11035 group="0"
11036 name="Love_Handles"
11037 label="Love Handles"
11038 wearable="shape"
11039 edit_group="shape_torso"
11040 edit_group_order="12"
11041 label_min="Less Love"
11042 label_max="More Love"
11043 value_min="-1"
11044 value_max="2"
11045 value_default="0"
11046 camera_elevation=".3"
11047 camera_distance=".9">
11048 <param_driver>
11049 <driven
11050 id="855" />
11051
11052 <driven
11053 id="856" />
11054 </param_driver>
11055 </param>
11056
11057 <param
11058 id="863"
11059 group="0"
11060 name="skirt_looseness"
11061 label="Skirt Fit"
11062 show_simple="true"
11063 clothing_morph="true"
11064 wearable="skirt"
11065 edit_group_order="2"
11066 edit_group="skirt"
11067 label_min="Tight Skirt"
11068 label_max="Poofy Skirt"
11069 value_min="0"
11070 value_max="1"
11071 value_default=".333"
11072 camera_distance="1.3"
11073 camera_elevation="-.5">
11074 <param_driver>
11075 <driven
11076 id="866"
11077 min1="0"
11078 max1="0"
11079 max2="0"
11080 min2=".2" />
11081
11082 <driven
11083 id="846"
11084 min1="0"
11085 max1=".5"
11086 max2=".5"
11087 min2="1" />
11088
11089 <driven
11090 id="845"
11091 min1=".5"
11092 max1="1"
11093 max2="1"
11094 min2="1" />
11095 </param_driver>
11096 </param>
11097
11098 <param
11099 id="119"
11100 group="0"
11101 wearable="hair"
11102 edit_group="hair_eyebrows"
11103 edit_group_order="1"
11104 name="Eyebrow Size"
11105 show_simple="true"
11106 label_min="Thin Eyebrows"
11107 label_max="Bushy Eyebrows"
11108 value_min="0"
11109 value_max="1"
11110 value_default="0.5"
11111 camera_elevation=".1"
11112 camera_distance=".3">
11113 <param_driver>
11114 <driven
11115 id="1000" />
11116
11117 <driven
11118 id="1001" />
11119 </param_driver>
11120 </param>
11121
11122 <param
11123 id="750"
11124 group="0"
11125 wearable="hair"
11126 edit_group="hair_eyebrows"
11127 edit_group_order="2"
11128 name="Eyebrow Density"
11129 label_min="Sparse"
11130 label_max="Dense"
11131 value_min="0"
11132 value_max="1"
11133 value_default="0.7"
11134 camera_elevation=".1"
11135 camera_distance=".3">
11136 <param_driver>
11137 <driven
11138 id="1002" />
11139
11140 <driven
11141 id="1003" />
11142 </param_driver>
11143 </param>
11144
11145 <param
11146 id="166"
11147 sex="male"
11148 group="0"
11149 wearable="hair"
11150 edit_group="hair_facial"
11151 edit_group_order="2"
11152 name="Sideburns"
11153 show_simple="true"
11154 label_min="Short Sideburns"
11155 label_max="Mutton Chops"
11156 value_min="0"
11157 value_max="1"
11158 value_default="0.0"
11159 camera_elevation=".1"
11160 camera_distance=".3"
11161 camera_angle="30">
11162 <param_driver>
11163 <driven
11164 id="1004" />
11165
11166 <driven
11167 id="1005" />
11168 </param_driver>
11169 </param>
11170
11171 <param
11172 id="167"
11173 sex="male"
11174 group="0"
11175 wearable="hair"
11176 edit_group="hair_facial"
11177 edit_group_order="3"
11178 name="Moustache"
11179 show_simple="true"
11180 label_min="Chaplin"
11181 label_max="Handlebars"
11182 value_min="0"
11183 value_max="1"
11184 value_default="0.0"
11185 camera_elevation=".1"
11186 camera_distance=".3"
11187 camera_angle="30">
11188 <param_driver>
11189 <driven
11190 id="1006" />
11191
11192 <driven
11193 id="1007" />
11194 </param_driver>
11195 </param>
11196
11197 <param
11198 id="168"
11199 sex="male"
11200 group="0"
11201 wearable="hair"
11202 edit_group="hair_facial"
11203 edit_group_order="5"
11204 name="Soulpatch"
11205 show_simple="true"
11206 label_min="Less soul"
11207 label_max="More soul"
11208 value_min="0"
11209 value_max="1"
11210 value_default="0.0"
11211 camera_elevation="-.1"
11212 camera_distance=".3"
11213 camera_angle="0">
11214 <param_driver>
11215 <driven
11216 id="1008" />
11217
11218 <driven
11219 id="1009" />
11220 </param_driver>
11221 </param>
11222
11223 <param
11224 id="169"
11225 sex="male"
11226 group="0"
11227 wearable="hair"
11228 edit_group="hair_facial"
11229 edit_group_order="4"
11230 name="Chin Curtains"
11231 show_simple="true"
11232 label_min="Less Curtains"
11233 label_max="More Curtains"
11234 value_min="0"
11235 value_max="1"
11236 value_default="0.0"
11237 camera_elevation="-.1"
11238 camera_distance=".3"
11239 camera_angle="45">
11240 <param_driver>
11241 <driven
11242 id="1010" />
11243
11244 <driven
11245 id="1011" />
11246 </param_driver>
11247 </param>
11248
11249 <param
11250 id="606"
11251 group="0"
11252 wearable="jacket"
11253 edit_group="jacket"
11254 edit_group_order="1"
11255 name="Sleeve Length"
11256 label_min="Short"
11257 label_max="Long"
11258 value_min="0"
11259 value_max="1"
11260 value_default=".8"
11261 camera_distance="1.2"
11262 camera_angle="30"
11263 camera_elevation=".2">
11264 <param_driver>
11265 <driven
11266 id="1019" />
11267
11268 <driven
11269 id="1039" />
11270
11271 <driven
11272 id="1020" />
11273 </param_driver>
11274 </param>
11275
11276 <param
11277 id="607"
11278 group="0"
11279 wearable="jacket"
11280 edit_group="jacket"
11281 edit_group_order="3"
11282 name="Collar Front"
11283 label_min="Low"
11284 label_max="High"
11285 value_min="0"
11286 value_max="1"
11287 value_default=".8"
11288 camera_distance="1.2"
11289 camera_angle="15"
11290 camera_elevation=".2">
11291 <param_driver>
11292 <driven
11293 id="1021" />
11294
11295 <driven
11296 id="1040" />
11297
11298 <driven
11299 id="1022" />
11300 </param_driver>
11301 </param>
11302
11303 <param
11304 id="780"
11305 group="0"
11306 wearable="jacket"
11307 edit_group="jacket"
11308 edit_group_order="3.5"
11309 name="Collar Back"
11310 label_min="Low"
11311 label_max="High"
11312 value_min="0"
11313 value_max="1"
11314 value_default=".8"
11315 camera_distance="1.2"
11316 camera_angle="195"
11317 camera_elevation=".2">
11318 <param_driver>
11319 <driven
11320 id="1023" />
11321
11322 <driven
11323 id="1041" />
11324
11325 <driven
11326 id="1024" />
11327 </param_driver>
11328 </param>
11329
11330 <param
11331 id="603"
11332 group="0"
11333 wearable="undershirt"
11334 edit_group="undershirt"
11335 edit_group_order="1"
11336 name="Sleeve Length"
11337 label_min="Short"
11338 label_max="Long"
11339 value_min=".01"
11340 value_max="1"
11341 value_default=".4"
11342 camera_distance="1.2"
11343 camera_angle="30"
11344 camera_elevation=".2">
11345 <param_driver>
11346 <driven
11347 id="1042" />
11348
11349 <driven
11350 id="1043" />
11351 </param_driver>
11352 </param>
11353
11354 <param
11355 id="604"
11356 group="0"
11357 wearable="undershirt"
11358 edit_group="undershirt"
11359 edit_group_order="2"
11360 name="Bottom"
11361 label_min="Short"
11362 label_max="Long"
11363 value_min="0"
11364 value_max="1"
11365 value_default=".85"
11366 camera_distance="1.2"
11367 camera_angle="30"
11368 camera_elevation=".2">
11369 <param_driver>
11370 <driven
11371 id="1044" />
11372
11373 <driven
11374 id="1045" />
11375 </param_driver>
11376 </param>
11377
11378 <param
11379 id="605"
11380 group="0"
11381 wearable="undershirt"
11382 edit_group="undershirt"
11383 edit_group_order="3"
11384 name="Collar Front"
11385 label_min="Low"
11386 label_max="High"
11387 value_min="0"
11388 value_max="1"
11389 value_default=".84"
11390 camera_distance=".8"
11391 camera_angle="15"
11392 camera_elevation=".2">
11393 <param_driver>
11394 <driven
11395 id="1046" />
11396
11397 <driven
11398 id="1047" />
11399 </param_driver>
11400 </param>
11401
11402 <param
11403 id="779"
11404 group="0"
11405 wearable="undershirt"
11406 edit_group="undershirt"
11407 edit_group_order="4"
11408 name="Collar Back"
11409 label_min="Low"
11410 label_max="High"
11411 value_min="0"
11412 value_max="1"
11413 value_default=".84"
11414 camera_distance=".8"
11415 camera_angle="195"
11416 camera_elevation=".2">
11417 <param_driver>
11418 <driven
11419 id="1048" />
11420
11421 <driven
11422 id="1049" />
11423 </param_driver>
11424 </param>
11425
11426 <param
11427 id="617"
11428 group="0"
11429 wearable="socks"
11430 edit_group="socks"
11431 name="Socks Length"
11432 label_min="Short"
11433 label_max="Long"
11434 value_min="0"
11435 value_max="1"
11436 value_default="0.35"
11437 camera_distance=".95"
11438 camera_angle="30"
11439 camera_elevation="-.75">
11440 <param_driver>
11441 <driven
11442 id="1050" />
11443
11444 <driven
11445 id="1051" />
11446 </param_driver>
11447 </param>
11448
11449 <param
11450 id="616"
11451 group="0"
11452 wearable="shoes"
11453 edit_group="shoes"
11454 edit_group_order="1"
11455 name="Shoe Height"
11456 label_min="Short"
11457 label_max="Tall"
11458 value_min="0"
11459 value_max="1"
11460 value_default="0.1"
11461 camera_distance="1.2"
11462 camera_angle="30"
11463 camera_elevation="-.75">
11464 <param_driver>
11465 <driven
11466 id="1052" />
11467
11468 <driven
11469 id="1053" />
11470 </param_driver>
11471 </param>
11472
11473 <param
11474 id="619"
11475 group="0"
11476 wearable="underpants"
11477 edit_group="underpants"
11478 name="Pants Length"
11479 label_min="Short"
11480 label_max="Long"
11481 value_min="0"
11482 value_max="1"
11483 value_default=".3"
11484 camera_distance="1.2"
11485 camera_angle="30"
11486 camera_elevation="-.3">
11487 <param_driver>
11488 <driven
11489 id="1054" />
11490
11491 <driven
11492 id="1055" />
11493 </param_driver>
11494 </param>
11495
11496 <param
11497 id="624"
11498 group="0"
11499 wearable="underpants"
11500 edit_group="underpants"
11501 name="Pants Waist"
11502 label_min="Low"
11503 label_max="High"
11504 value_min="0"
11505 value_max="1"
11506 value_default=".8"
11507 camera_distance="1.2"
11508 camera_angle="30"
11509 camera_elevation="-.3">
11510 <param_driver>
11511 <driven
11512 id="1056" />
11513
11514 <driven
11515 id="1057" />
11516 </param_driver>
11517 </param>
11518
11519 <param
11520 id="93"
11521 group="0"
11522 wearable="gloves"
11523 edit_group="gloves"
11524 name="Glove Length"
11525 label_min="Short"
11526 label_max="Long"
11527 value_min=".01"
11528 value_max="1"
11529 value_default=".8"
11530 camera_distance="1.2"
11531 camera_angle="30"
11532 camera_elevation=".2">
11533 <param_driver>
11534 <driven
11535 id="1058" />
11536
11537 <driven
11538 id="1059" />
11539 </param_driver>
11540 </param>
11541
11542 <param
11543 id="844"
11544 group="0"
11545 wearable="gloves"
11546 edit_group="gloves"
11547 name="Glove Fingers"
11548 label_min="Fingerless"
11549 label_max="Fingers"
11550 value_min=".01"
11551 value_max="1"
11552 value_default="1"
11553 camera_distance="1.2"
11554 camera_angle="30"
11555 camera_elevation=".2">
11556 <param_driver>
11557 <driven
11558 id="1060" />
11559
11560 <driven
11561 id="1061" />
11562 </param_driver>
11563 </param>
11564
11565 <!--Pointy eyebrows became a driver/driven param with new max value for backwards compatibility between 1.0 and 1.1-->
11566 <param
11567 id="16"
11568 group="0"
11569 name="Pointy_Eyebrows"
11570 label="Eyebrow Points"
11571 wearable="hair"
11572 edit_group="hair_eyebrows"
11573 edit_group_order="4"
11574 label_min="Smooth"
11575 label_max="Pointy"
11576 value_min="-.5"
11577 value_max="3"
11578 camera_elevation=".1"
11579 camera_distance=".3">
11580 <param_driver>
11581 <driven
11582 id="870" />
11583 </param_driver>
11584 </param>
11585
11586 <!--Lower eyebrows became a driver/driven param with new min value for backwards compatibility between 1.0 and 1.1-->
11587 <param
11588 id="757"
11589 group="0"
11590 name="Lower_Eyebrows"
11591 label="Eyebrow Height"
11592 show_simple="true"
11593 wearable="hair"
11594 edit_group="hair_eyebrows"
11595 edit_group_order="2.5"
11596 label_min="Higher"
11597 label_max="Lower"
11598 value_min="-4"
11599 value_max="2"
11600 value_default="-1"
11601 camera_elevation=".1"
11602 camera_distance=".3">
11603 <param_driver>
11604 <driven
11605 id="871" />
11606 </param_driver>
11607 </param>
11608
11609 <!--Arced eyebrows became a driver/driven param with new max value for backwards compatibility between 1.0 and 1.1-->
11610 <param
11611 id="31"
11612 group="0"
11613 name="Arced_Eyebrows"
11614 label="Eyebrow Arc"
11615 wearable="hair"
11616 edit_group="hair_eyebrows"
11617 edit_group_order="3"
11618 label_min="Flat"
11619 label_max="Arced"
11620 value_min="0"
11621 value_max="2"
11622 value_default=".5"
11623 camera_elevation=".1"
11624 camera_distance=".3">
11625 <param_driver>
11626 <driven
11627 id="872" />
11628 </param_driver>
11629 </param>
11630
11631
11632 <param
11633 id="877"
11634 group="0"
11635 name="Jacket Wrinkles"
11636 label="Jacket Wrinkles"
11637 wearable="jacket"
11638 edit_group="jacket"
11639 edit_group_order="20"
11640 label_min="No Wrinkles"
11641 label_max="Wrinkles"
11642 value_min="0"
11643 value_max="1"
11644 value_default="0"
11645 camera_elevation=".1"
11646 camera_distance=".3">
11647 <param_driver>
11648 <driven
11649 id="875" />
11650
11651
11652 <driven
11653 id="876" />
11654 </param_driver>
11655 </param>
11656
11657 <param
11658 id="1071"
11659 group="2"
11660 wearable="tattoo"
11661 edit_group="colorpicker"
11662 name="tattoo_red"
11663 value_min="0"
11664 value_max="1"
11665 value_default="1">
11666 <param_driver>
11667 <driven
11668 id="1062"
11669 min1="0"
11670 max1="1"
11671 max2="1"
11672 min2="1" />
11673
11674 <driven
11675 id="1065"
11676 min1="0"
11677 max1="1"
11678 max2="1"
11679 min2="1" />
11680
11681 <driven
11682 id="1068"
11683 min1="0"
11684 max1="1"
11685 max2="1"
11686 min2="1" />
11687 </param_driver>
11688 </param>
11689
11690 <param
11691 id="1072"
11692 group="2"
11693 wearable="tattoo"
11694 edit_group="colorpicker"
11695 name="tattoo_green"
11696 value_min="0"
11697 value_max="1"
11698 value_default="1">
11699 <param_driver>
11700 <driven
11701 id="1063"
11702 min1="0"
11703 max1="1"
11704 max2="1"
11705 min2="1" />
11706
11707 <driven
11708 id="1066"
11709 min1="0"
11710 max1="1"
11711 max2="1"
11712 min2="1" />
11713
11714 <driven
11715 id="1069"
11716 min1="0"
11717 max1="1"
11718 max2="1"
11719 min2="1" />
11720 </param_driver>
11721 </param>
11722
11723 <param
11724 id="1073"
11725 group="2"
11726 wearable="tattoo"
11727 edit_group="colorpicker"
11728 name="tattoo_blue"
11729 value_min="0"
11730 value_max="1"
11731 value_default="1">
11732 <param_driver>
11733 <driven
11734 id="1064"
11735 min1="0"
11736 max1="1"
11737 max2="1"
11738 min2="1" />
11739
11740 <driven
11741 id="1067"
11742 min1="0"
11743 max1="1"
11744 max2="1"
11745 min2="1" />
11746
11747 <driven
11748 id="1070"
11749 min1="0"
11750 max1="1"
11751 max2="1"
11752 min2="1" />
11753
11754 </param_driver>
11755 </param>
11756
11757 <!-- ==PHYSICS PARAMETERS======================================= -->
11758
11759 <param
11760 id="1100"
11761 group="1"
11762 sex="female"
11763 wearable="physics"
11764 name="Breast_Physics_UpDown_Controller"
11765 label="Breast Physics UpDown Controller"
11766 value_min="-1"
11767 value_max="1"
11768 value_default="0">
11769 <param_driver>
11770 <driven
11771 id="1200" />
11772 </param_driver>
11773 </param>
11774
11775 <param
11776 id="1101"
11777 group="1"
11778 sex="female"
11779 wearable="physics"
11780 name="Breast_Physics_InOut_Controller"
11781 label="Breast Physics InOut Controller"
11782 value_min="-1"
11783 value_max="1"
11784 value_default="0">
11785 <param_driver>
11786 <driven
11787 id="1201" />
11788 </param_driver>
11789 </param>
11790
11791 <param
11792 id="1102"
11793 group="1"
11794 wearable="physics"
11795 name="Belly_Physics_UpDown_Controller"
11796 label="Belly Physics UpDown Controller"
11797 value_min="-1"
11798 value_max="1"
11799 value_default="0">
11800 <param_driver>
11801 <driven
11802 id="1202" />
11803 <driven
11804 id="1203" />
11805 <driven
11806 id="1204" />
11807 </param_driver>
11808 </param>
11809
11810 <param
11811 id="1103"
11812 group="1"
11813 wearable="shape"
11814 name="Butt_Physics_UpDown_Controller"
11815 label="Butt Physics UpDown Controller"
11816 value_min="-1"
11817 value_max="1"
11818 value_default="0">
11819 <param_driver>
11820 <driven
11821 id="1205" />
11822 </param_driver>
11823 </param>
11824
11825 <param
11826 id="1104"
11827 group="1"
11828 wearable="shape"
11829 name="Butt_Physics_LeftRight_Controller"
11830 label="Butt Physics LeftRight Controller"
11831 value_min="-1"
11832 value_max="1"
11833 value_default="0">
11834 <param_driver>
11835 <driven
11836 id="1206" />
11837 </param_driver>
11838 </param>
11839
11840 <param
11841 id="1105"
11842 group="1"
11843 wearable="shape"
11844 name="Breast_Physics_LeftRight_Controller"
11845 label="Breast Physics LeftRight Controller"
11846 value_min="-1"
11847 value_max="1"
11848 value_default="0">
11849 <param_driver>
11850 <driven
11851 id="1207" />
11852 </param_driver>
11853 </param>
11854
11855 <param
11856 id="10000"
11857 group="0"
11858 sex="female"
11859 name="Breast_Physics_Mass"
11860 label="Breast Physics Mass"
11861 wearable="physics"
11862 edit_group="physics_advanced"
11863 value_default=".1"
11864 value_min=".1"
11865 value_max="1">
11866 <param_driver />
11867 </param>
11868 <param
11869 id="10001"
11870 group="0"
11871 sex="female"
11872 name="Breast_Physics_Gravity"
11873 label="Breast Physics Gravity"
11874 wearable="physics"
11875 edit_group="physics_advanced"
11876 value_default="0"
11877 value_min="0"
11878 value_max="30">
11879 <param_driver />
11880 </param>
11881
11882 <param
11883 id="10002"
11884 group="0"
11885 sex="female"
11886 name="Breast_Physics_Drag"
11887 label="Breast Physics Drag"
11888 wearable="physics"
11889 edit_group="physics_advanced"
11890 value_default="1"
11891 value_min="0"
11892 value_max="10">
11893 <param_driver />
11894 </param>
11895
11896 <param
11897 id="10003"
11898 group="0"
11899 sex="female"
11900 name="Breast_Physics_UpDown_Max_Effect"
11901 label="Breast Physics UpDown Max Effect"
11902 wearable="physics"
11903 edit_group="physics_breasts_updown"
11904 value_default="0"
11905 value_min="0"
11906 value_max="3">
11907 <param_driver />
11908 </param>
11909 <param
11910 id="10004"
11911 group="0"
11912 sex="female"
11913 name="Breast_Physics_UpDown_Spring"
11914 label="Breast Physics UpDown Spring"
11915 wearable="physics"
11916 edit_group="physics_breasts_updown"
11917 value_default="10"
11918 value_min="0"
11919 value_max="100">
11920 <param_driver />
11921 </param>
11922 <param
11923 id="10005"
11924 group="0"
11925 sex="female"
11926 name="Breast_Physics_UpDown_Gain"
11927 label="Breast Physics UpDown Gain"
11928 wearable="physics"
11929 edit_group="physics_breasts_updown"
11930 value_default="10"
11931 value_min="1"
11932 value_max="100">
11933 <param_driver />
11934 </param>
11935 <param
11936 id="10006"
11937 group="0"
11938 sex="female"
11939 name="Breast_Physics_UpDown_Damping"
11940 label="Breast Physics UpDown Damping"
11941 wearable="physics"
11942 edit_group="physics_breasts_updown"
11943 value_default=".2"
11944 value_min="0"
11945 value_max="1">
11946 <param_driver />
11947 </param>
11948
11949 <param
11950 id="10007"
11951 group="0"
11952 sex="female"
11953 name="Breast_Physics_InOut_Max_Effect"
11954 label="Breast Physics InOut Max Effect"
11955 wearable="physics"
11956 edit_group="physics_breasts_inout"
11957 value_default="0"
11958 value_min="0"
11959 value_max="3">
11960 <param_driver />
11961 </param>
11962 <param
11963 id="10008"
11964 group="0"
11965 sex="female"
11966 name="Breast_Physics_InOut_Spring"
11967 label="Breast Physics InOut Spring"
11968 wearable="physics"
11969 edit_group="physics_breasts_inout"
11970 value_default="10"
11971 value_min="0"
11972 value_max="100">
11973 <param_driver />
11974 </param>
11975 <param
11976 id="10009"
11977 group="0"
11978 sex="female"
11979 name="Breast_Physics_InOut_Gain"
11980 label="Breast Physics InOut Gain"
11981 wearable="physics"
11982 edit_group="physics_breasts_inout"
11983 value_default="10"
11984 value_min="1"
11985 value_max="100">
11986 <param_driver />
11987 </param>
11988 <param
11989 id="10010"
11990 group="0"
11991 sex="female"
11992 name="Breast_Physics_InOut_Damping"
11993 label="Breast Physics InOut Damping"
11994 wearable="physics"
11995 edit_group="physics_breasts_inout"
11996 value_default=".2"
11997 value_min="0"
11998 value_max="1">
11999 <param_driver />
12000 </param>
12001
12002 <param
12003 id="10011"
12004 group="0"
12005 name="Belly_Physics_Mass"
12006 label="Belly Physics Mass"
12007 wearable="physics"
12008 edit_group="physics_advanced"
12009 value_default=".1"
12010 value_min=".1"
12011 value_max="1">
12012 <param_driver />
12013 </param>
12014 <param
12015 id="10012"
12016 group="0"
12017 name="Belly_Physics_Gravity"
12018 label="Belly Physics Gravity"
12019 wearable="physics"
12020 edit_group="physics_advanced"
12021 value_default="0"
12022 value_min="0"
12023 value_max="30">
12024 <param_driver />
12025 </param>
12026 <param
12027 id="10013"
12028 group="0"
12029 name="Belly_Physics_Drag"
12030 label="Belly Physics Drag"
12031 wearable="physics"
12032 edit_group="physics_advanced"
12033 value_default="1"
12034 value_min="0"
12035 value_max="10">
12036 <param_driver />
12037 </param>
12038 <param
12039 id="10014"
12040 group="0"
12041 name="Belly_Physics_UpDown_Max_Effect"
12042 label="Belly Physics UpDown Max Effect"
12043 wearable="physics"
12044 edit_group="physics_belly_updown"
12045 value_default="0"
12046 value_min="0"
12047 value_max="3">
12048 <param_driver />
12049 </param>
12050 <param
12051 id="10015"
12052 group="0"
12053 name="Belly_Physics_UpDown_Spring"
12054 label="Belly Physics UpDown Spring"
12055 wearable="physics"
12056 edit_group="physics_belly_updown"
12057 value_default="10"
12058 value_min="0"
12059 value_max="100">
12060 <param_driver />
12061 </param>
12062 <param
12063 id="10016"
12064 group="0"
12065 name="Belly_Physics_UpDown_Gain"
12066 label="Belly Physics UpDown Gain"
12067 wearable="physics"
12068 edit_group="physics_belly_updown"
12069 value_default="10"
12070 value_min="1"
12071 value_max="100">
12072 <param_driver />
12073 </param>
12074 <param
12075 id="10017"
12076 group="0"
12077 name="Belly_Physics_UpDown_Damping"
12078 label="Belly Physics UpDown Damping"
12079 wearable="physics"
12080 edit_group="physics_belly_updown"
12081 value_default=".2"
12082 value_min="0"
12083 value_max="1">
12084 <param_driver />
12085 </param>
12086
12087 <param
12088 id="10018"
12089 group="0"
12090 name="Butt_Physics_Mass"
12091 label="Butt Physics Mass"
12092 wearable="physics"
12093 edit_group="physics_advanced"
12094 value_default=".1"
12095 value_min=".1"
12096 value_max="1">
12097 <param_driver />
12098 </param>
12099 <param
12100 id="10019"
12101 group="0"
12102 name="Butt_Physics_Gravity"
12103 label="Butt Physics Gravity"
12104 wearable="physics"
12105 edit_group="physics_advanced"
12106 value_default="0"
12107 value_min="0"
12108 value_max="30">
12109 <param_driver />
12110 </param>
12111 <param
12112 id="10020"
12113 group="0"
12114 name="Butt_Physics_Drag"
12115 label="Butt Physics Drag"
12116 wearable="physics"
12117 edit_group="physics_advanced"
12118 value_default="1"
12119 value_min="0"
12120 value_max="10">
12121 <param_driver />
12122 </param>
12123
12124 <param
12125 id="10021"
12126 group="0"
12127 name="Butt_Physics_UpDown_Max_Effect"
12128 label="Butt Physics UpDown Max Effect"
12129 wearable="physics"
12130 edit_group="physics_butt_updown"
12131 value_default="0"
12132 value_min="0"
12133 value_max="3">
12134 <param_driver />
12135 </param>
12136 <param
12137 id="10022"
12138 group="0"
12139 name="Butt_Physics_UpDown_Spring"
12140 label="Butt Physics UpDown Spring"
12141 wearable="physics"
12142 edit_group="physics_butt_updown"
12143 value_default="10"
12144 value_min="0"
12145 value_max="100">
12146 <param_driver />
12147 </param>
12148 <param
12149 id="10023"
12150 group="0"
12151 name="Butt_Physics_UpDown_Gain"
12152 label="Butt Physics UpDown Gain"
12153 wearable="physics"
12154 edit_group="physics_butt_updown"
12155 value_default="10"
12156 value_min="1"
12157 value_max="100">
12158 <param_driver />
12159 </param>
12160 <param
12161 id="10024"
12162 group="0"
12163 name="Butt_Physics_UpDown_Damping"
12164 label="Butt Physics UpDown Damping"
12165 wearable="physics"
12166 edit_group="physics_butt_updown"
12167 value_default=".2"
12168 value_min="0"
12169 value_max="1">
12170 <param_driver />
12171 </param>
12172
12173 <param
12174 id="10025"
12175 group="0"
12176 name="Butt_Physics_LeftRight_Max_Effect"
12177 label="Butt Physics LeftRight Max Effect"
12178 wearable="physics"
12179 edit_group="physics_butt_leftright"
12180 value_default="0"
12181 value_min="0"
12182 value_max="3">
12183 <param_driver />
12184 </param>
12185 <param
12186 id="10026"
12187 group="0"
12188 name="Butt_Physics_LeftRight_Spring"
12189 label="Butt Physics LeftRight Spring"
12190 wearable="physics"
12191 edit_group="physics_butt_leftright"
12192 value_default="10"
12193 value_min="0"
12194 value_max="100">
12195 <param_driver />
12196 </param>
12197 <param
12198 id="10027"
12199 group="0"
12200 name="Butt_Physics_LeftRight_Gain"
12201 label="Butt Physics LeftRight Gain"
12202 wearable="physics"
12203 edit_group="physics_butt_leftright"
12204 value_default="10"
12205 value_min="1"
12206 value_max="100">
12207 <param_driver />
12208 </param>
12209 <param
12210 id="10028"
12211 group="0"
12212 name="Butt_Physics_LeftRight_Damping"
12213 label="Butt Physics LeftRight Damping"
12214 wearable="physics"
12215 edit_group="physics_butt_leftright"
12216 value_default=".2"
12217 value_min="0"
12218 value_max="1">
12219 <param_driver />
12220 </param>
12221
12222 <param
12223 id="10029"
12224 group="0"
12225 sex="female"
12226 name="Breast_Physics_LeftRight_Max_Effect"
12227 label="Breast Physics LeftRight Max Effect"
12228 wearable="physics"
12229 edit_group="physics_breasts_leftright"
12230 value_default="0"
12231 value_min="0"
12232 value_max="3">
12233 <param_driver />
12234 </param>
12235 <param
12236 id="10030"
12237 group="0"
12238 sex="female"
12239 name="Breast_Physics_LeftRight_Spring"
12240 label="Breast Physics LeftRight Spring"
12241 wearable="physics"
12242 edit_group="physics_breasts_leftright"
12243 value_default="10"
12244 value_min="0"
12245 value_max="100">
12246 <param_driver />
12247 </param>
12248 <param
12249 id="10031"
12250 group="0"
12251 sex="female"
12252 name="Breast_Physics_LeftRight_Gain"
12253 label="Breast Physics LeftRight Gain"
12254 wearable="physics"
12255 edit_group="physics_breasts_leftright"
12256 value_default="10"
12257 value_min="1"
12258 value_max="100">
12259 <param_driver />
12260 </param>
12261 <param
12262 id="10032"
12263 group="0"
12264 sex="female"
12265 name="Breast_Physics_LeftRight_Damping"
12266 label="Breast Physics LeftRight Damping"
12267 wearable="physics"
12268 edit_group="physics_breasts_leftright"
12269 value_default=".2"
12270 value_min="0"
12271 value_max="1">
12272 <param_driver />
12273 </param>
12274
12275 </driver_parameters>
12276
12277 <morph_masks>
12278 <mask
12279 morph_name="Displace_Hair_Facial"
12280 body_region="head"
12281 layer="facialhair" />
12282 <mask
12283 morph_name="Displace_Loose_Upperbody"
12284 body_region="upper_body"
12285 layer="upper_clothes" />
12286 <mask
12287 morph_name="Shirtsleeve_flair"
12288 body_region="upper_body"
12289 layer="upper_clothes" />
12290 <mask
12291 morph_name="Displace_Loose_Lowerbody"
12292 body_region="lower_body"
12293 layer="lower_pants" />
12294 <mask
12295 morph_name="Leg_Pantflair"
12296 body_region="lower_body"
12297 layer="lower_pants" />
12298 <mask
12299 morph_name="Low_Crotch"
12300 body_region="lower_body"
12301 layer="lower_pants" />
12302 <mask
12303 morph_name="Leg_Longcuffs"
12304 body_region="lower_body"
12305 layer="lower_pants" />
12306 </morph_masks>
12307</linden_avatar>
12308
diff --git a/bin/openmetaverse_data/blush_alpha.tga b/bin/openmetaverse_data/blush_alpha.tga
new file mode 100644
index 0000000..05be7e7
--- /dev/null
+++ b/bin/openmetaverse_data/blush_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/body_skingrain.tga b/bin/openmetaverse_data/body_skingrain.tga
new file mode 100644
index 0000000..7264baa
--- /dev/null
+++ b/bin/openmetaverse_data/body_skingrain.tga
Binary files differ
diff --git a/bin/openmetaverse_data/bodyfreckles_alpha.tga b/bin/openmetaverse_data/bodyfreckles_alpha.tga
new file mode 100644
index 0000000..d30ab3d
--- /dev/null
+++ b/bin/openmetaverse_data/bodyfreckles_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/bump_face_wrinkles.tga b/bin/openmetaverse_data/bump_face_wrinkles.tga
new file mode 100644
index 0000000..54bf7a5
--- /dev/null
+++ b/bin/openmetaverse_data/bump_face_wrinkles.tga
Binary files differ
diff --git a/bin/openmetaverse_data/bump_head_base.tga b/bin/openmetaverse_data/bump_head_base.tga
new file mode 100644
index 0000000..fa35685
--- /dev/null
+++ b/bin/openmetaverse_data/bump_head_base.tga
Binary files differ
diff --git a/bin/openmetaverse_data/bump_lowerbody_base.tga b/bin/openmetaverse_data/bump_lowerbody_base.tga
new file mode 100644
index 0000000..498ea3c
--- /dev/null
+++ b/bin/openmetaverse_data/bump_lowerbody_base.tga
Binary files differ
diff --git a/bin/openmetaverse_data/bump_pants_wrinkles.tga b/bin/openmetaverse_data/bump_pants_wrinkles.tga
new file mode 100644
index 0000000..cca7241
--- /dev/null
+++ b/bin/openmetaverse_data/bump_pants_wrinkles.tga
Binary files differ
diff --git a/bin/openmetaverse_data/bump_shirt_wrinkles.tga b/bin/openmetaverse_data/bump_shirt_wrinkles.tga
new file mode 100644
index 0000000..9e0d757
--- /dev/null
+++ b/bin/openmetaverse_data/bump_shirt_wrinkles.tga
Binary files differ
diff --git a/bin/openmetaverse_data/bump_upperbody_base.tga b/bin/openmetaverse_data/bump_upperbody_base.tga
new file mode 100644
index 0000000..e57d635
--- /dev/null
+++ b/bin/openmetaverse_data/bump_upperbody_base.tga
Binary files differ
diff --git a/bin/openmetaverse_data/eyebrows_alpha.tga b/bin/openmetaverse_data/eyebrows_alpha.tga
new file mode 100644
index 0000000..c363e48
--- /dev/null
+++ b/bin/openmetaverse_data/eyebrows_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/eyeliner_alpha.tga b/bin/openmetaverse_data/eyeliner_alpha.tga
new file mode 100644
index 0000000..1611eb3
--- /dev/null
+++ b/bin/openmetaverse_data/eyeliner_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/eyeshadow_inner_alpha.tga b/bin/openmetaverse_data/eyeshadow_inner_alpha.tga
new file mode 100644
index 0000000..37d7919
--- /dev/null
+++ b/bin/openmetaverse_data/eyeshadow_inner_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/eyeshadow_outer_alpha.tga b/bin/openmetaverse_data/eyeshadow_outer_alpha.tga
new file mode 100644
index 0000000..00eef9d
--- /dev/null
+++ b/bin/openmetaverse_data/eyeshadow_outer_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/eyewhite.tga b/bin/openmetaverse_data/eyewhite.tga
new file mode 100644
index 0000000..a720496
--- /dev/null
+++ b/bin/openmetaverse_data/eyewhite.tga
Binary files differ
diff --git a/bin/openmetaverse_data/facehair_chincurtains_alpha.tga b/bin/openmetaverse_data/facehair_chincurtains_alpha.tga
new file mode 100644
index 0000000..b103970
--- /dev/null
+++ b/bin/openmetaverse_data/facehair_chincurtains_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/facehair_moustache_alpha.tga b/bin/openmetaverse_data/facehair_moustache_alpha.tga
new file mode 100644
index 0000000..4068c4f
--- /dev/null
+++ b/bin/openmetaverse_data/facehair_moustache_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/facehair_sideburns_alpha.tga b/bin/openmetaverse_data/facehair_sideburns_alpha.tga
new file mode 100644
index 0000000..acddc2d
--- /dev/null
+++ b/bin/openmetaverse_data/facehair_sideburns_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/facehair_soulpatch_alpha.tga b/bin/openmetaverse_data/facehair_soulpatch_alpha.tga
new file mode 100644
index 0000000..687091a
--- /dev/null
+++ b/bin/openmetaverse_data/facehair_soulpatch_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/freckles_alpha.tga b/bin/openmetaverse_data/freckles_alpha.tga
new file mode 100644
index 0000000..a9a4ec0
--- /dev/null
+++ b/bin/openmetaverse_data/freckles_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/glove_length_alpha.tga b/bin/openmetaverse_data/glove_length_alpha.tga
new file mode 100644
index 0000000..db89ad5
--- /dev/null
+++ b/bin/openmetaverse_data/glove_length_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/gloves_fingers_alpha.tga b/bin/openmetaverse_data/gloves_fingers_alpha.tga
new file mode 100644
index 0000000..dba2eec
--- /dev/null
+++ b/bin/openmetaverse_data/gloves_fingers_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/head_alpha.tga b/bin/openmetaverse_data/head_alpha.tga
new file mode 100644
index 0000000..8164525
--- /dev/null
+++ b/bin/openmetaverse_data/head_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/head_color.tga b/bin/openmetaverse_data/head_color.tga
new file mode 100644
index 0000000..74b1b30
--- /dev/null
+++ b/bin/openmetaverse_data/head_color.tga
Binary files differ
diff --git a/bin/openmetaverse_data/head_hair.tga b/bin/openmetaverse_data/head_hair.tga
new file mode 100644
index 0000000..5321f35
--- /dev/null
+++ b/bin/openmetaverse_data/head_hair.tga
Binary files differ
diff --git a/bin/openmetaverse_data/head_highlights_alpha.tga b/bin/openmetaverse_data/head_highlights_alpha.tga
new file mode 100644
index 0000000..8dc5239
--- /dev/null
+++ b/bin/openmetaverse_data/head_highlights_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/head_shading_alpha.tga b/bin/openmetaverse_data/head_shading_alpha.tga
new file mode 100644
index 0000000..e8ea490
--- /dev/null
+++ b/bin/openmetaverse_data/head_shading_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/head_skingrain.tga b/bin/openmetaverse_data/head_skingrain.tga
new file mode 100644
index 0000000..b42dee0
--- /dev/null
+++ b/bin/openmetaverse_data/head_skingrain.tga
Binary files differ
diff --git a/bin/openmetaverse_data/jacket_length_lower_alpha.tga b/bin/openmetaverse_data/jacket_length_lower_alpha.tga
new file mode 100644
index 0000000..722bc19
--- /dev/null
+++ b/bin/openmetaverse_data/jacket_length_lower_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/jacket_length_upper_alpha.tga b/bin/openmetaverse_data/jacket_length_upper_alpha.tga
new file mode 100644
index 0000000..e9db7e7
--- /dev/null
+++ b/bin/openmetaverse_data/jacket_length_upper_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/jacket_open_lower_alpha.tga b/bin/openmetaverse_data/jacket_open_lower_alpha.tga
new file mode 100644
index 0000000..db0c2fb
--- /dev/null
+++ b/bin/openmetaverse_data/jacket_open_lower_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/jacket_open_upper_alpha.tga b/bin/openmetaverse_data/jacket_open_upper_alpha.tga
new file mode 100644
index 0000000..71b8a0b
--- /dev/null
+++ b/bin/openmetaverse_data/jacket_open_upper_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/lipgloss_alpha.tga b/bin/openmetaverse_data/lipgloss_alpha.tga
new file mode 100644
index 0000000..78ceeca
--- /dev/null
+++ b/bin/openmetaverse_data/lipgloss_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/lips_mask.tga b/bin/openmetaverse_data/lips_mask.tga
new file mode 100644
index 0000000..ae1401c
--- /dev/null
+++ b/bin/openmetaverse_data/lips_mask.tga
Binary files differ
diff --git a/bin/openmetaverse_data/lipstick_alpha.tga b/bin/openmetaverse_data/lipstick_alpha.tga
new file mode 100644
index 0000000..2795f1b
--- /dev/null
+++ b/bin/openmetaverse_data/lipstick_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/lowerbody_color.tga b/bin/openmetaverse_data/lowerbody_color.tga
new file mode 100644
index 0000000..a63aa12
--- /dev/null
+++ b/bin/openmetaverse_data/lowerbody_color.tga
Binary files differ
diff --git a/bin/openmetaverse_data/lowerbody_highlights_alpha.tga b/bin/openmetaverse_data/lowerbody_highlights_alpha.tga
new file mode 100644
index 0000000..ae3413a
--- /dev/null
+++ b/bin/openmetaverse_data/lowerbody_highlights_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/lowerbody_shading_alpha.tga b/bin/openmetaverse_data/lowerbody_shading_alpha.tga
new file mode 100644
index 0000000..0242663
--- /dev/null
+++ b/bin/openmetaverse_data/lowerbody_shading_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/nailpolish_alpha.tga b/bin/openmetaverse_data/nailpolish_alpha.tga
new file mode 100644
index 0000000..91af762
--- /dev/null
+++ b/bin/openmetaverse_data/nailpolish_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/pants_length_alpha.tga b/bin/openmetaverse_data/pants_length_alpha.tga
new file mode 100644
index 0000000..3c4f21c
--- /dev/null
+++ b/bin/openmetaverse_data/pants_length_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/pants_waist_alpha.tga b/bin/openmetaverse_data/pants_waist_alpha.tga
new file mode 100644
index 0000000..35658c0
--- /dev/null
+++ b/bin/openmetaverse_data/pants_waist_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/rosyface_alpha.tga b/bin/openmetaverse_data/rosyface_alpha.tga
new file mode 100644
index 0000000..a0c8513
--- /dev/null
+++ b/bin/openmetaverse_data/rosyface_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/rouge_alpha.tga b/bin/openmetaverse_data/rouge_alpha.tga
new file mode 100644
index 0000000..a0c8513
--- /dev/null
+++ b/bin/openmetaverse_data/rouge_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/shirt_bottom_alpha.tga b/bin/openmetaverse_data/shirt_bottom_alpha.tga
new file mode 100644
index 0000000..7cce03d
--- /dev/null
+++ b/bin/openmetaverse_data/shirt_bottom_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/shirt_collar_alpha.tga b/bin/openmetaverse_data/shirt_collar_alpha.tga
new file mode 100644
index 0000000..f55f635
--- /dev/null
+++ b/bin/openmetaverse_data/shirt_collar_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/shirt_collar_back_alpha.tga b/bin/openmetaverse_data/shirt_collar_back_alpha.tga
new file mode 100644
index 0000000..43a6453
--- /dev/null
+++ b/bin/openmetaverse_data/shirt_collar_back_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/shirt_sleeve_alpha.tga b/bin/openmetaverse_data/shirt_sleeve_alpha.tga
new file mode 100644
index 0000000..e3b18f4
--- /dev/null
+++ b/bin/openmetaverse_data/shirt_sleeve_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/shoe_height_alpha.tga b/bin/openmetaverse_data/shoe_height_alpha.tga
new file mode 100644
index 0000000..d08dd75
--- /dev/null
+++ b/bin/openmetaverse_data/shoe_height_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/skirt_length_alpha.tga b/bin/openmetaverse_data/skirt_length_alpha.tga
new file mode 100644
index 0000000..c867994
--- /dev/null
+++ b/bin/openmetaverse_data/skirt_length_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/skirt_slit_back_alpha.tga b/bin/openmetaverse_data/skirt_slit_back_alpha.tga
new file mode 100644
index 0000000..0e49688
--- /dev/null
+++ b/bin/openmetaverse_data/skirt_slit_back_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/skirt_slit_front_alpha.tga b/bin/openmetaverse_data/skirt_slit_front_alpha.tga
new file mode 100644
index 0000000..888bbf7
--- /dev/null
+++ b/bin/openmetaverse_data/skirt_slit_front_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/skirt_slit_left_alpha.tga b/bin/openmetaverse_data/skirt_slit_left_alpha.tga
new file mode 100644
index 0000000..210feac
--- /dev/null
+++ b/bin/openmetaverse_data/skirt_slit_left_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/skirt_slit_right_alpha.tga b/bin/openmetaverse_data/skirt_slit_right_alpha.tga
new file mode 100644
index 0000000..ce11c64
--- /dev/null
+++ b/bin/openmetaverse_data/skirt_slit_right_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/underpants_trial_female.tga b/bin/openmetaverse_data/underpants_trial_female.tga
new file mode 100644
index 0000000..96bf732
--- /dev/null
+++ b/bin/openmetaverse_data/underpants_trial_female.tga
Binary files differ
diff --git a/bin/openmetaverse_data/underpants_trial_male.tga b/bin/openmetaverse_data/underpants_trial_male.tga
new file mode 100644
index 0000000..095695c
--- /dev/null
+++ b/bin/openmetaverse_data/underpants_trial_male.tga
Binary files differ
diff --git a/bin/openmetaverse_data/undershirt_trial_female.tga b/bin/openmetaverse_data/undershirt_trial_female.tga
new file mode 100644
index 0000000..e17a309
--- /dev/null
+++ b/bin/openmetaverse_data/undershirt_trial_female.tga
Binary files differ
diff --git a/bin/openmetaverse_data/upperbody_color.tga b/bin/openmetaverse_data/upperbody_color.tga
new file mode 100644
index 0000000..85fcc41
--- /dev/null
+++ b/bin/openmetaverse_data/upperbody_color.tga
Binary files differ
diff --git a/bin/openmetaverse_data/upperbody_highlights_alpha.tga b/bin/openmetaverse_data/upperbody_highlights_alpha.tga
new file mode 100644
index 0000000..2d8102b
--- /dev/null
+++ b/bin/openmetaverse_data/upperbody_highlights_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/upperbody_shading_alpha.tga b/bin/openmetaverse_data/upperbody_shading_alpha.tga
new file mode 100644
index 0000000..b420506
--- /dev/null
+++ b/bin/openmetaverse_data/upperbody_shading_alpha.tga
Binary files differ
diff --git a/bin/openmetaverse_data/upperbodyfreckles_alpha.tga b/bin/openmetaverse_data/upperbodyfreckles_alpha.tga
new file mode 100644
index 0000000..76c7ce8
--- /dev/null
+++ b/bin/openmetaverse_data/upperbodyfreckles_alpha.tga
Binary files differ
diff --git a/bin/pCampBot.exe.config b/bin/pCampBot.exe.config
index 9cfb7e9..9cfb7e9 100644..100755
--- a/bin/pCampBot.exe.config
+++ b/bin/pCampBot.exe.config
diff --git a/prebuild.xml b/prebuild.xml
index afcae1c..08e7070 100644
--- a/prebuild.xml
+++ b/prebuild.xml
@@ -112,6 +112,34 @@
112 </Files> 112 </Files>
113 </Project> 113 </Project>
114 114
115 <Project frameworkVersion="v3_5" name="OpenSim.Services.Interfaces" path="OpenSim/Services/Interfaces" type="Library">
116 <Configuration name="Debug">
117 <Options>
118 <OutputPath>../../../bin/</OutputPath>
119 </Options>
120 </Configuration>
121 <Configuration name="Release">
122 <Options>
123 <OutputPath>../../../bin/</OutputPath>
124 </Options>
125 </Configuration>
126
127 <ReferencePath>../../../bin/</ReferencePath>
128 <Reference name="System"/>
129 <Reference name="OpenMetaverseTypes" path="../../../bin/"/>
130 <Reference name="OpenMetaverse" path="../../../bin/"/>
131 <Reference name="OpenMetaverse.StructuredData" path="../../../bin/"/>
132 <Reference name="OpenSim.Framework"/>
133 <Reference name="OpenSim.Framework.Console"/>
134 <Reference name="OpenSim.Framework.Servers.HttpServer"/>
135 <Reference name="Nini" path="../../../bin/"/>
136 <Reference name="log4net" path="../../../bin/"/>
137
138 <Files>
139 <Match pattern="*.cs" recurse="true"/>
140 </Files>
141 </Project>
142
115 <Project frameworkVersion="v3_5" name="OpenSim.Framework.Monitoring" path="OpenSim/Framework/Monitoring" type="Library"> 143 <Project frameworkVersion="v3_5" name="OpenSim.Framework.Monitoring" path="OpenSim/Framework/Monitoring" type="Library">
116 <Configuration name="Debug"> 144 <Configuration name="Debug">
117 <Options> 145 <Options>
@@ -206,34 +234,6 @@
206 </Files> 234 </Files>
207 </Project> 235 </Project>
208 236
209 <Project frameworkVersion="v3_5" name="OpenSim.Services.Interfaces" path="OpenSim/Services/Interfaces" type="Library">
210 <Configuration name="Debug">
211 <Options>
212 <OutputPath>../../../bin/</OutputPath>
213 </Options>
214 </Configuration>
215 <Configuration name="Release">
216 <Options>
217 <OutputPath>../../../bin/</OutputPath>
218 </Options>
219 </Configuration>
220
221 <ReferencePath>../../../bin/</ReferencePath>
222 <Reference name="System"/>
223 <Reference name="OpenMetaverseTypes" path="../../../bin/"/>
224 <Reference name="OpenMetaverse" path="../../../bin/"/>
225 <Reference name="OpenMetaverse.StructuredData" path="../../../bin/"/>
226 <Reference name="OpenSim.Framework"/>
227 <Reference name="OpenSim.Framework.Console"/>
228 <Reference name="OpenSim.Framework.Servers.HttpServer"/>
229 <Reference name="Nini" path="../../../bin/"/>
230 <Reference name="log4net" path="../../../bin/"/>
231
232 <Files>
233 <Match pattern="*.cs" recurse="true"/>
234 </Files>
235 </Project>
236
237 <Project frameworkVersion="v3_5" name="OpenSim.Framework.Serialization" path="OpenSim/Framework/Serialization" type="Library"> 237 <Project frameworkVersion="v3_5" name="OpenSim.Framework.Serialization" path="OpenSim/Framework/Serialization" type="Library">
238 <Configuration name="Debug"> 238 <Configuration name="Debug">
239 <Options> 239 <Options>
@@ -1497,110 +1497,6 @@
1497 </Files> 1497 </Files>
1498 </Project> 1498 </Project>
1499 1499
1500 <Project frameworkVersion="v3_5" name="OpenSim.Region.CoreModules" path="OpenSim/Region/CoreModules" type="Library">
1501 <Configuration name="Debug">
1502 <Options>
1503 <OutputPath>../../../bin/</OutputPath>
1504 <AllowUnsafe>true</AllowUnsafe>
1505 </Options>
1506 </Configuration>
1507 <Configuration name="Release">
1508 <Options>
1509 <OutputPath>../../../bin/</OutputPath>
1510 <AllowUnsafe>true</AllowUnsafe>
1511 </Options>
1512 </Configuration>
1513
1514 <ReferencePath>../../../bin/</ReferencePath>
1515 <Reference name="System"/>
1516 <Reference name="System.Core"/>
1517 <Reference name="System.Xml"/>
1518 <Reference name="System.Xml.Linq"/>
1519 <Reference name="System.Drawing"/>
1520 <Reference name="System.Web"/>
1521 <Reference name="NDesk.Options" path="../../../bin/"/>
1522 <Reference name="OpenMetaverseTypes" path="../../../bin/"/>
1523 <Reference name="OpenMetaverse.StructuredData" path="../../../bin/"/>
1524 <Reference name="OpenMetaverse" path="../../../bin/"/>
1525 <Reference name="CSJ2K" path="../../../bin/"/>
1526 <Reference name="Warp3D" path="../../../bin/"/>
1527 <Reference name="OpenSim.Capabilities"/>
1528 <Reference name="OpenSim.Data"/>
1529 <Reference name="OpenSim.Framework"/>
1530 <Reference name="OpenSim.Framework.Communications"/>
1531 <Reference name="OpenSim.Framework.Console"/>
1532 <Reference name="OpenSim.Framework.Monitoring"/>
1533 <Reference name="OpenSim.Framework.Serialization"/>
1534 <Reference name="OpenSim.Framework.Servers"/>
1535 <Reference name="OpenSim.Framework.Servers.HttpServer"/>
1536 <Reference name="OpenSim.Region.Framework"/>
1537 <Reference name="OpenSim.Region.Physics.Manager"/>
1538 <Reference name="OpenSim.Server.Base"/>
1539 <Reference name="OpenSim.Server.Handlers"/>
1540 <Reference name="OpenSim.Services.Connectors"/>
1541 <Reference name="OpenSim.Services.Base"/>
1542 <Reference name="OpenSim.Services.Interfaces"/>
1543 <Reference name="Ionic.Zip" path="../../../bin/"/>
1544
1545 <Reference name="GlynnTucker.Cache" path="../../../bin/"/>
1546
1547 <!-- For scripting in funny languages by default -->
1548 <Reference name="XMLRPC" path="../../../bin/"/>
1549 <Reference name="OpenSim.Framework.Communications"/>
1550 <Reference name="Nini" path="../../../bin/"/>
1551 <Reference name="log4net" path="../../../bin/"/>
1552 <Reference name="DotNetOpenMail" path="../../../bin/"/>
1553
1554 <!-- To allow regions to have mono addins -->
1555 <Reference name="Mono.Addins" path="../../../bin/"/>
1556
1557 <Files>
1558 <Match buildAction="EmbeddedResource" path="Resources" pattern="*.addin.xml" recurse="true"/>
1559 <Match pattern="*.cs" recurse="true">
1560 <Exclude name="Tests" pattern="Tests"/>
1561 </Match>
1562 <Match buildAction="EmbeddedResource" path="Resources" pattern="*.addin.xml" recurse="true"/>
1563 </Files>
1564 </Project>
1565
1566 <Project frameworkVersion="v3_5" name="OpenSim.Region.RegionCombinerModule" path="OpenSim/Region/RegionCombinerModule" type="Library">
1567 <Configuration name="Debug">
1568 <Options>
1569 <OutputPath>../../../bin/</OutputPath>
1570 </Options>
1571 </Configuration>
1572 <Configuration name="Release">
1573 <Options>
1574 <OutputPath>../../../bin/</OutputPath>
1575 </Options>
1576 </Configuration>
1577
1578 <ReferencePath>../../../bin/</ReferencePath>
1579 <Reference name="System"/>
1580 <Reference name="System.Xml"/>
1581 <Reference name="OpenMetaverseTypes" path="../../../bin/"/>
1582 <Reference name="OpenMetaverse" path="../../../bin/"/>
1583 <Reference name="OpenSim.Framework"/>
1584 <Reference name="OpenSim.Framework.Communications"/>
1585 <Reference name="OpenSim.Region.Framework"/>
1586 <Reference name="OpenSim.Server.Base"/>
1587 <Reference name="OpenSim.Server.Handlers"/>
1588 <Reference name="OpenSim.Framework.Console"/>
1589 <Reference name="OpenSim.Region.Physics.Manager"/>
1590 <Reference name="OpenSim.Framework.Communications"/>
1591 <Reference name="OpenSim.Region.CoreModules"/>
1592 <Reference name="Nini" path="../../../bin/"/>
1593 <Reference name="log4net" path="../../../bin/"/>
1594
1595 <!-- To allow regions to have mono addins -->
1596 <Reference name="Mono.Addins" path="../../../bin/"/>
1597
1598 <Files>
1599 <Match pattern="*.cs" recurse="true"/>
1600 <Match buildAction="EmbeddedResource" path="Resources" pattern="*.addin.xml" recurse="true"/>
1601 </Files>
1602 </Project>
1603
1604 <Project frameworkVersion="v3_5" name="OpenSim.Region.ClientStack" path="OpenSim/Region/ClientStack" type="Library"> 1500 <Project frameworkVersion="v3_5" name="OpenSim.Region.ClientStack" path="OpenSim/Region/ClientStack" type="Library">
1605 <Configuration name="Debug"> 1501 <Configuration name="Debug">
1606 <Options> 1502 <Options>
@@ -1723,6 +1619,111 @@
1723 </Files> 1619 </Files>
1724 </Project> 1620 </Project>
1725 1621
1622 <Project frameworkVersion="v3_5" name="OpenSim.Region.CoreModules" path="OpenSim/Region/CoreModules" type="Library">
1623 <Configuration name="Debug">
1624 <Options>
1625 <OutputPath>../../../bin/</OutputPath>
1626 <AllowUnsafe>true</AllowUnsafe>
1627 </Options>
1628 </Configuration>
1629 <Configuration name="Release">
1630 <Options>
1631 <OutputPath>../../../bin/</OutputPath>
1632 <AllowUnsafe>true</AllowUnsafe>
1633 </Options>
1634 </Configuration>
1635
1636 <ReferencePath>../../../bin/</ReferencePath>
1637 <Reference name="System"/>
1638 <Reference name="System.Core"/>
1639 <Reference name="System.Xml"/>
1640 <Reference name="System.Xml.Linq"/>
1641 <Reference name="System.Drawing"/>
1642 <Reference name="System.Web"/>
1643 <Reference name="NDesk.Options" path="../../../bin/"/>
1644 <Reference name="OpenMetaverseTypes" path="../../../bin/"/>
1645 <Reference name="OpenMetaverse.StructuredData" path="../../../bin/"/>
1646 <Reference name="OpenMetaverse" path="../../../bin/"/>
1647 <Reference name="CSJ2K" path="../../../bin/"/>
1648 <Reference name="Warp3D" path="../../../bin/"/>
1649 <Reference name="OpenSim.Capabilities"/>
1650 <Reference name="OpenSim.Data"/>
1651 <Reference name="OpenSim.Framework"/>
1652 <Reference name="OpenSim.Framework.Communications"/>
1653 <Reference name="OpenSim.Framework.Console"/>
1654 <Reference name="OpenSim.Framework.Monitoring"/>
1655 <Reference name="OpenSim.Framework.Serialization"/>
1656 <Reference name="OpenSim.Framework.Servers"/>
1657 <Reference name="OpenSim.Framework.Servers.HttpServer"/>
1658 <Reference name="OpenSim.Region.ClientStack.LindenUDP"/>
1659 <Reference name="OpenSim.Region.Framework"/>
1660 <Reference name="OpenSim.Region.Physics.Manager"/>
1661 <Reference name="OpenSim.Server.Base"/>
1662 <Reference name="OpenSim.Server.Handlers"/>
1663 <Reference name="OpenSim.Services.Connectors"/>
1664 <Reference name="OpenSim.Services.Base"/>
1665 <Reference name="OpenSim.Services.Interfaces"/>
1666 <Reference name="Ionic.Zip" path="../../../bin/"/>
1667
1668 <Reference name="GlynnTucker.Cache" path="../../../bin/"/>
1669
1670 <!-- For scripting in funny languages by default -->
1671 <Reference name="XMLRPC" path="../../../bin/"/>
1672 <Reference name="OpenSim.Framework.Communications"/>
1673 <Reference name="Nini" path="../../../bin/"/>
1674 <Reference name="log4net" path="../../../bin/"/>
1675 <Reference name="DotNetOpenMail" path="../../../bin/"/>
1676
1677 <!-- To allow regions to have mono addins -->
1678 <Reference name="Mono.Addins" path="../../../bin/"/>
1679
1680 <Files>
1681 <Match buildAction="EmbeddedResource" path="Resources" pattern="*.addin.xml" recurse="true"/>
1682 <Match pattern="*.cs" recurse="true">
1683 <Exclude name="Tests" pattern="Tests"/>
1684 </Match>
1685 <Match buildAction="EmbeddedResource" path="Resources" pattern="*.addin.xml" recurse="true"/>
1686 </Files>
1687 </Project>
1688
1689 <Project frameworkVersion="v3_5" name="OpenSim.Region.RegionCombinerModule" path="OpenSim/Region/RegionCombinerModule" type="Library">
1690 <Configuration name="Debug">
1691 <Options>
1692 <OutputPath>../../../bin/</OutputPath>
1693 </Options>
1694 </Configuration>
1695 <Configuration name="Release">
1696 <Options>
1697 <OutputPath>../../../bin/</OutputPath>
1698 </Options>
1699 </Configuration>
1700
1701 <ReferencePath>../../../bin/</ReferencePath>
1702 <Reference name="System"/>
1703 <Reference name="System.Xml"/>
1704 <Reference name="OpenMetaverseTypes" path="../../../bin/"/>
1705 <Reference name="OpenMetaverse" path="../../../bin/"/>
1706 <Reference name="OpenSim.Framework"/>
1707 <Reference name="OpenSim.Framework.Communications"/>
1708 <Reference name="OpenSim.Region.Framework"/>
1709 <Reference name="OpenSim.Server.Base"/>
1710 <Reference name="OpenSim.Server.Handlers"/>
1711 <Reference name="OpenSim.Framework.Console"/>
1712 <Reference name="OpenSim.Region.Physics.Manager"/>
1713 <Reference name="OpenSim.Framework.Communications"/>
1714 <Reference name="OpenSim.Region.CoreModules"/>
1715 <Reference name="Nini" path="../../../bin/"/>
1716 <Reference name="log4net" path="../../../bin/"/>
1717
1718 <!-- To allow regions to have mono addins -->
1719 <Reference name="Mono.Addins" path="../../../bin/"/>
1720
1721 <Files>
1722 <Match pattern="*.cs" recurse="true"/>
1723 <Match buildAction="EmbeddedResource" path="Resources" pattern="*.addin.xml" recurse="true"/>
1724 </Files>
1725 </Project>
1726
1726 <Project frameworkVersion="v3_5" name="OpenSim.Region.OptionalModules" path="OpenSim/Region/OptionalModules" type="Library"> 1727 <Project frameworkVersion="v3_5" name="OpenSim.Region.OptionalModules" path="OpenSim/Region/OptionalModules" type="Library">
1727 <Configuration name="Debug"> 1728 <Configuration name="Debug">
1728 <Options> 1729 <Options>
@@ -1883,6 +1884,7 @@
1883 <Reference name="System.Core"/> 1884 <Reference name="System.Core"/>
1884 <Reference name="System.Xml"/> 1885 <Reference name="System.Xml"/>
1885 <Reference name="Mono.Addins" path="../../../bin/"/> 1886 <Reference name="Mono.Addins" path="../../../bin/"/>
1887 <Reference name="NDesk.Options" path="../../../bin/"/>
1886 <Reference name="OpenMetaverseTypes" path="../../../bin/"/> 1888 <Reference name="OpenMetaverseTypes" path="../../../bin/"/>
1887 <Reference name="OpenMetaverse.StructuredData" path="../../../bin/"/> 1889 <Reference name="OpenMetaverse.StructuredData" path="../../../bin/"/>
1888 <Reference name="OpenMetaverse" path="../../../bin/"/> 1890 <Reference name="OpenMetaverse" path="../../../bin/"/>
@@ -3093,6 +3095,7 @@
3093 <Match path="World/Media/Moap/Tests" pattern="*.cs" recurse="true"/> 3095 <Match path="World/Media/Moap/Tests" pattern="*.cs" recurse="true"/>
3094 <Match path="World/Serialiser/Tests" pattern="*.cs" recurse="true"/> 3096 <Match path="World/Serialiser/Tests" pattern="*.cs" recurse="true"/>
3095 <Match path="World/Terrain/Tests" pattern="*.cs" recurse="true"/> 3097 <Match path="World/Terrain/Tests" pattern="*.cs" recurse="true"/>
3098 <Match path="ServiceConnectorsOut/Asset/Tests" pattern="*.cs" recurse="true"/>
3096 <Match path="ServiceConnectorsOut/Grid/Tests" pattern="*.cs" recurse="true"/> 3099 <Match path="ServiceConnectorsOut/Grid/Tests" pattern="*.cs" recurse="true"/>
3097 <Match path="ServiceConnectorsOut/Presence/Tests" pattern="*.cs" recurse="true"/> 3100 <Match path="ServiceConnectorsOut/Presence/Tests" pattern="*.cs" recurse="true"/>
3098 </Files> 3101 </Files>
@@ -3373,7 +3376,48 @@
3373 </Files> 3376 </Files>
3374 </Project> 3377 </Project>
3375 3378
3376 <Project frameworkVersion="v3_5" name="OpenSim.Tests.Torture" path="OpenSim/Tests/Torture" type="Library"> 3379 <Project frameworkVersion="v3_5" name="OpenSim.Tests.Stress" path="OpenSim/Tests/Stress" type="Library">
3380 <Configuration name="Debug">
3381 <Options>
3382 <OutputPath>../../../bin/</OutputPath>
3383 </Options>
3384 </Configuration>
3385 <Configuration name="Release">
3386 <Options>
3387 <OutputPath>../../../bin/</OutputPath>
3388 </Options>
3389 </Configuration>
3390
3391 <ReferencePath>../../../bin/</ReferencePath>
3392 <Reference name="System"/>
3393 <Reference name="System.Core"/>
3394 <Reference name="System.Xml"/>
3395 <Reference name="System.Data"/>
3396 <Reference name="log4net" path="../../../bin/"/>
3397 <Reference name="Nini" path="../../../bin/"/>
3398 <Reference name="nunit.framework" path="../../../bin/"/>
3399 <Reference name="OpenMetaverse" path="../../../bin/"/>
3400 <Reference name="OpenMetaverseTypes" path="../../../bin/"/>
3401 <Reference name="OpenMetaverse.StructuredData" path="../../../bin/"/>
3402 <Reference name="XMLRPC" path="../../../bin/"/>
3403 <Reference name="OpenSim.Framework"/>
3404 <Reference name="OpenSim.Framework.Communications"/>
3405 <Reference name="OpenSim.Framework.Console"/>
3406 <Reference name="OpenSim.Framework.Servers.HttpServer"/>
3407 <Reference name="OpenSim.Region.CoreModules"/>
3408 <Reference name="OpenSim.Region.Framework"/>
3409 <Reference name="OpenSim.Region.OptionalModules"/>
3410 <Reference name="OpenSim.Region.ScriptEngine.Shared"/>
3411 <Reference name="OpenSim.Region.ScriptEngine.XEngine"/>
3412 <Reference name="OpenSim.Services.Interfaces"/>
3413 <Reference name="OpenSim.Services.AvatarService"/>
3414 <Reference name="OpenSim.Tests.Common"/>
3415 <Files>
3416 <Match pattern="*.cs" recurse="false"/>
3417 </Files>
3418 </Project>
3419
3420 <Project frameworkVersion="v3_5" name="OpenSim.Tests.Performance" path="OpenSim/Tests/Performance" type="Library">
3377 <Configuration name="Debug"> 3421 <Configuration name="Debug">
3378 <Options> 3422 <Options>
3379 <OutputPath>../../../bin/</OutputPath> 3423 <OutputPath>../../../bin/</OutputPath>